Replace threads by timing fds for ecu version, timing packets and watchdog.
[profile/ivi/dlt-daemon.git] / src / daemon / dlt-daemon.c
index 20cba66..87663c6 100644 (file)
 /** Global text output buffer, mainly used for creation of error/warning strings */
 static char str[DLT_DAEMON_TEXTBUFSIZE];
 
-static DltDaemonTimingPacketThreadData dlt_daemon_timingpacket_thread_data;
-
-static pthread_t      dlt_daemon_timingpacket_thread_handle;
-static pthread_attr_t dlt_daemon_timingpacket_thread_attr;
-
-static DltDaemonECUVersionThreadData dlt_daemon_ecu_version_thread_data;
-static pthread_t      dlt_daemon_ecu_version_thread_handle;
-
-#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE)
-// Allow main loop to execute every 100ms
-#define DLT_SELECT_TIMEOUT_USEC (1000 * 100)
-static DltDaemonTimingPacketThreadData dlt_daemon_systemd_watchdog_thread_data;
-static pthread_t      dlt_daemon_systemd_watchdog_thread_handle;
-#endif
-
 /**
  * Print usage information of tool.
  */
@@ -221,6 +206,7 @@ int option_file_parser(DltDaemonLocal *daemon_local)
        daemon_local->flags.loggingMode = 0;
        daemon_local->flags.loggingLevel = 6;
        strncpy(daemon_local->flags.loggingFilename, DLT_USER_DIR "/dlt.log",sizeof(daemon_local->flags.loggingFilename));
+       daemon_local->timeoutOnSend = 4;
        daemon_local->flags.sendECUSoftwareVersion = 0;
        memset(daemon_local->flags.pathToECUSoftwareVersion, 0, sizeof(daemon_local->flags.pathToECUSoftwareVersion));
 
@@ -344,6 +330,11 @@ int option_file_parser(DltDaemonLocal *daemon_local)
                                                         strncpy(daemon_local->flags.loggingFilename,value,sizeof(daemon_local->flags.loggingFilename) - 1);
                                                        //printf("Option: %s=%s\n",token,value);
                                                }
+                               else if(strcmp(token,"TimeOutOnSend")==0)
+                                               {
+                                                       daemon_local->timeoutOnSend = atoi(value);
+                                                       //printf("Option: %s=%s\n",token,value);
+                                               }
                                                else if(strcmp(token,"SharedMemorySize")==0)
                                                {
                                                        daemon_local->flags.sharedMemorySize = atoi(value);
@@ -406,19 +397,6 @@ int main(int argc, char* argv[])
     DltDaemon daemon;
     int i,back;
 
-#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE)
-       /* Timeout for select */
-       struct timeval tvTimeout;
-       tvTimeout.tv_sec = 0;
-       tvTimeout.tv_usec = DLT_SELECT_TIMEOUT_USEC;
-
-       /* Set watchdog flag immediately, not to timeout while init */
-       if(sd_notify(0, "WATCHDOG=1") < 0)
-       {
-               fprintf (stderr, "Could not initialize systemd watchdog\n");
-               return -1;
-       }
-#endif
     /* Command line option handling */
        if ((back = option_handling(&daemon_local,argc,argv))<0)
        {
@@ -474,31 +452,33 @@ int main(int argc, char* argv[])
     }
     /* --- Daemon init phase 2 end --- */
 
-    while (1)
+    // create fd for watchdog
+#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     {
-#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE)
-       /* Set timeout to defined usecs
-        * select might modify this value: POSIX.1-2001 */
-               tvTimeout.tv_sec = 0;
-               tvTimeout.tv_usec = DLT_SELECT_TIMEOUT_USEC;
+        char* watchdogUSec = getenv("WATCHDOG_USEC");
+        int watchdogTimeoutSeconds = 0;
 
-       /* update the watchdog time structure */
-               daemon_local.lastOperationTime = dlt_uptime();
-
-       /* wait for events from all FIFO and sockets, with timeout */
-        daemon_local.read_fds = daemon_local.master;
-        int selectRet = select(daemon_local.fdmax+1, &(daemon_local.read_fds), NULL, NULL, &tvTimeout);
-        if (selectRet == -1)
+        dlt_log(LOG_DEBUG, "Systemd watchdog initialization\n");
+        if( watchdogUSec )
         {
-            dlt_log(LOG_CRIT, "select() failed!\n");
-            return -1 ;
-        } /* if */
-        else if(selectRet == 0)
-        {
-               /* No pending reads, continue while(1)*/
-               continue;
+            watchdogTimeoutSeconds = atoi(watchdogUSec)/2000000;
         }
-#else
+        create_timer_fd(&daemon_local, watchdogTimeoutSeconds, watchdogTimeoutSeconds, &daemon_local.timer_wd, "Systemd watchdog");
+    }
+#endif
+
+    // create fd for timer timing packets
+    create_timer_fd(&daemon_local, 1, 1, &daemon_local.timer_timingpacket, "Timing packet");
+
+    // create fd for timer ecu version
+    if(daemon_local.flags.sendECUSoftwareVersion > 0)
+    {
+        //dlt_daemon_init_ecuversion(&daemon_local);
+        create_timer_fd(&daemon_local, 60, 60, &daemon_local.timer_ecuversion, "ECU version");
+    }
+
+    while (1)
+    {
 
         /* wait for events from all FIFO and sockets */
         daemon_local.read_fds = daemon_local.master;
@@ -507,7 +487,7 @@ int main(int argc, char* argv[])
             dlt_log(LOG_CRIT, "select() failed!\n");
             return -1 ;
         } /* if */
-#endif
+
         /* run through the existing FIFO and sockets to check for events */
         for (i = 0; i <= daemon_local.fdmax; i++)
         {
@@ -540,6 +520,55 @@ int main(int argc, char* argv[])
                         return -1;
                     }
                 }
+#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                else if (i == daemon_local.timer_wd)
+                {
+                    uint64_t expir=0;
+                    ssize_t res = read(daemon_local.timer_wd, &expir, sizeof(expir));
+                    if(res < 0) {
+                        sprintf(str,"Failed to read timer_wd; %s\n", strerror(errno) );
+                        dlt_log(LOG_WARNING, str);
+                        // Activity received on timer_wd, but unable to read the fd:
+                        // let's go on sending notification
+                    }
+
+                    dlt_log(LOG_DEBUG, "Timer watchdog\n");
+
+                    if(sd_notify(0, "WATCHDOG=1") < 0)
+                    {
+                        dlt_log(LOG_CRIT, "Could not reset systemd watchdog\n");
+                    }
+                }
+#endif
+                else if (i == daemon_local.timer_timingpacket)
+                {
+                    uint64_t expir=0;
+                    ssize_t res = read(daemon_local.timer_timingpacket, &expir, sizeof(expir));
+                    if(res < 0) {
+                        sprintf(str,"Failed to read timer_timingpacket; %s\n", strerror(errno) );
+                        dlt_log(LOG_WARNING, str);
+                        // Activity received on timer_wd, but unable to read the fd:
+                        // let's go on sending notification
+                    }
+                    dlt_daemon_send_timingpacket(&daemon, &daemon_local);
+                    dlt_log(LOG_DEBUG, "Timer timingpacket\n");
+
+                 }
+
+                else if (i == daemon_local.timer_ecuversion)
+                {
+                    uint64_t expir=0;
+                    ssize_t res = read(daemon_local.timer_ecuversion, &expir, sizeof(expir));
+                    if(res < 0) {
+                        sprintf(str,"Failed to read timer_ecuversion; %s\n", strerror(errno) );
+                        dlt_log(LOG_WARNING, str);
+                        // Activity received on timer_wd, but unable to read the fd:
+                        // let's go on sending notification
+                    }
+                    dlt_daemon_send_ecuversion(&daemon, &daemon_local);
+                    dlt_log(LOG_DEBUG, "Timer ecuversion\n");
+
+                }
                 else
                 {
                     /* event from tcp connection to client received */
@@ -696,19 +725,6 @@ int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, in
                        return -1;
         }
     }
-
-    /* setup period thread for timing packets */
-    if (pthread_attr_init(&dlt_daemon_timingpacket_thread_attr)<0)
-    {
-        dlt_log(LOG_WARNING, "Initialization of default thread stack size failed!\n");
-    }
-    else
-    {
-        if (pthread_attr_setstacksize(&dlt_daemon_timingpacket_thread_attr,DLT_DAEMON_TIMINGPACKET_THREAD_STACKSIZE)<0)
-        {
-            dlt_log(LOG_WARNING, "Setting of default thread stack size failed!\n");
-        }
-    }
     
     /* configure sending timing packets */
     if (daemon_local->flags.sendMessageTime)    
@@ -723,22 +739,6 @@ int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, in
         return -1;
     }
 
-    /* start thread */
-    dlt_daemon_timingpacket_thread_data.daemon = daemon;
-    dlt_daemon_timingpacket_thread_data.daemon_local = daemon_local;
-
-    if (pthread_create(&(dlt_daemon_timingpacket_thread_handle),
-                       &dlt_daemon_timingpacket_thread_attr,
-                       (void *) &dlt_daemon_timingpacket_thread,
-                       (void *)&dlt_daemon_timingpacket_thread_data)!=0)
-       {
-               dlt_log(LOG_ERR,"Could not initialize timing packet thread\n");
-               pthread_attr_destroy(&dlt_daemon_timingpacket_thread_attr);
-        return -1;
-       }
-
-    pthread_attr_destroy(&dlt_daemon_timingpacket_thread_attr);
-
     /* Get ECU version info from a file. If it fails, use dlt_version as fallback. */
     if(dlt_daemon_local_ecu_version_init(daemon, daemon_local, daemon_local->flags.vflag) < 0)
     {
@@ -746,38 +746,6 @@ int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, in
        dlt_get_version(daemon->ECUVersionString);
     }
 
-    /* start thread for ECU version, if enabled */
-    if(daemon_local->flags.sendECUSoftwareVersion > 0)
-    {
-               dlt_daemon_ecu_version_thread_data.daemon = daemon;
-               dlt_daemon_ecu_version_thread_data.daemon_local = daemon_local;
-
-               if (pthread_create(&(dlt_daemon_ecu_version_thread_handle),
-                                                  NULL,
-                                                  (void *) &dlt_daemon_ecu_version_thread,
-                                                  (void *)&dlt_daemon_ecu_version_thread_data)!=0)
-               {
-                       dlt_log(LOG_ERR,"Could not initialize ECU version thread\n");
-                       return -1;
-               }
-    }
-
-#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE)
-
-    dlt_daemon_systemd_watchdog_thread_data.daemon = daemon;
-    dlt_daemon_systemd_watchdog_thread_data.daemon_local = daemon_local;
-
-       if (pthread_create(&(dlt_daemon_systemd_watchdog_thread_handle),
-                                          NULL,
-                                          (void *) &dlt_daemon_systemd_watchdog_thread,
-                                          (void *) &dlt_daemon_systemd_watchdog_thread_data)!=0)
-       {
-               dlt_log(LOG_ERR,"Could not initialize systemd watchdog thread\n");
-               return -1;
-       }
-#endif
-
-
     return 0;
 }
 
@@ -800,10 +768,27 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_l
     /* open named pipe(FIFO) to receive DLT messages from users */
     umask(0);
 
+    ret=mkdir(DLT_USER_DIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH  | S_IWOTH | S_ISVTX );
+    if (ret==-1 && errno != EEXIST)
+    {
+        sprintf(str,"FIFO user dir %s cannot be created!\n", DLT_USER_DIR);
+        dlt_log(LOG_ERR, str);
+        return -1;
+    }
+
+    // S_ISGID cannot be set by mkdir, let's reassign right bits
+    ret=chmod(DLT_USER_DIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH  | S_IWOTH | S_IXOTH | S_ISGID | S_ISVTX );
+    if (ret==-1)
+    {
+        sprintf(str,"FIFO user dir %s cannot be chmoded!\n", DLT_USER_DIR);
+        dlt_log(LOG_ERR, str);
+        return -1;
+    }
+
     /* Try to delete existing pipe, ignore result of unlink */
     unlink(DLT_USER_FIFO);
 
-    ret=mkfifo(DLT_USER_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH  | S_IWOTH );
+    ret=mkfifo(DLT_USER_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
     if (ret==-1)
     {
         sprintf(str,"FIFO user %s cannot be created!\n",DLT_USER_FIFO);
@@ -826,7 +811,12 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_l
         return -1;
     } /* if */
 
-    setsockopt(daemon_local->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
+    if ( -1 == setsockopt(daemon_local->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)))
+    {
+        sprintf(str,"Setsockopt error in dlt_daemon_local_connection_init: %s\n",strerror(errno));
+        dlt_log(LOG_ERR, str);
+        return -1;
+    }
     memset(&servAddr, 0, sizeof(servAddr));
     servAddr.sin_family      = AF_INET;
     servAddr.sin_addr.s_addr = INADDR_ANY;
@@ -1177,6 +1167,13 @@ int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_
     dlt_daemon_applications_invalidate_fd(daemon,in_sock,verbose);
     dlt_daemon_contexts_invalidate_fd(daemon,in_sock,verbose);
 
+    /* Set socket timeout in reception */
+    struct timeval timeout_send;
+    timeout_send.tv_sec = daemon_local->timeoutOnSend;
+    timeout_send.tv_usec = 0;
+    if (setsockopt (in_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout_send, sizeof(timeout_send)) < 0)
+        dlt_log(LOG_ERR, "setsockopt failed\n");
+
     //sprintf("str,"Client Connection from %s\n", inet_ntoa(cli.sin_addr));
     //dlt_log(str);
     FD_SET(in_sock, &(daemon_local->master)); /* add to master set */
@@ -1193,6 +1190,15 @@ int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_
         dlt_log(LOG_INFO, str);
     }
 
+    // send connection info about connected
+    dlt_daemon_control_message_connection_info(in_sock,daemon,DLT_CONNECTION_STATUS_CONNECTED,"",verbose);
+
+    // send ecu version string
+    if(daemon_local->flags.sendECUSoftwareVersion > 0)
+    {
+       dlt_daemon_send_ecuversion(daemon,daemon_local);
+    }
+
     if (daemon_local->client_connections==1)
     {
         if (daemon_local->flags.vflag)
@@ -1227,9 +1233,9 @@ int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon
 
     if (dlt_receiver_receive_socket(&(daemon_local->receiverSock))<=0)
     {
-        close(daemon_local->receiverSock.fd);
-        daemon_local->receiverSock.fd = 0;
+        close(daemon_local->receiverSock.fd);        
         FD_CLR(daemon_local->receiverSock.fd, &(daemon_local->master));
+        daemon_local->receiverSock.fd = -1;
 
         if (daemon_local->client_connections)
         {
@@ -1249,6 +1255,7 @@ int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon
             dlt_log(LOG_INFO, str);
         }
 
+        dlt_daemon_control_message_connection_info(DLT_DAEMON_STORE_TO_BUFFER,daemon,DLT_CONNECTION_STATUS_DISCONNECTED,"",verbose);
         /* check: return 0; */
     }
 
@@ -1256,7 +1263,7 @@ int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon
     while (dlt_message_read(&(daemon_local->msg),(uint8_t*)daemon_local->receiverSock.buf,daemon_local->receiverSock.bytesRcvd,daemon_local->flags.nflag,daemon_local->flags.vflag)==0)
     {
         /* Check for control message */
-        if ( 0 != daemon_local->receiverSock.fd && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)) )
+        if ( 0 < daemon_local->receiverSock.fd && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)) )
         {
             dlt_daemon_control_process_control(daemon_local->receiverSock.fd, daemon, &(daemon_local->msg), daemon_local->flags.vflag);
         }
@@ -1517,6 +1524,7 @@ int dlt_daemon_process_user_messages(DltDaemon *daemon, DltDaemonLocal *daemon_l
 int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
 {
     int j, sent;
+    DltUserControlMsgBufferOverflow *userpayload;
 
     PRINT_FUNCTION_VERBOSE(verbose);
 
@@ -1526,6 +1534,15 @@ int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *
         return -1;
     }
 
+    if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgBufferOverflow)))
+    {
+       /* Not enough bytes received */
+        return -1;
+    }
+
+    /* get the payload of the user message */
+    userpayload = (DltUserControlMsgBufferOverflow*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
+
     /* Store in daemon, that a message buffer overflow has occured */
     daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_OVERFLOW;
 
@@ -1538,9 +1555,13 @@ int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *
         if (FD_ISSET(j, &(daemon_local->master)))
         {
             /* except the listener and ourselves */
-            if ((j != daemon_local->fp) && (j != daemon_local->sock))
+            if ((j != daemon_local->fp) && (j != daemon_local->sock)
+#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                        && (j!=daemon_local->timer_wd)
+#endif
+                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
             {
-                dlt_daemon_control_message_buffer_overflow(j, daemon, verbose);
+                dlt_daemon_control_message_buffer_overflow(j, daemon, userpayload->overflow_counter,userpayload->apid,verbose);
                 sent=1;
                 /* Reset overflow state */
                 daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_NO_OVERFLOW;
@@ -1551,11 +1572,17 @@ int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *
     /* message was not sent, so store it in ringbuffer */
     if (sent==0)
     {
-        dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_STORE_TO_BUFFER, daemon, verbose);
+        if(dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_STORE_TO_BUFFER, daemon, userpayload->overflow_counter,
+                                                             userpayload->apid,verbose))
+        {
+               /* there was an error when storing message */
+               /* add the counter of lost messages to the daemon counter */
+               daemon->overflow_counter+=userpayload->overflow_counter;
+        }
     }
 
     /* keep not read data in buffer */
-    if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader))==-1)
+    if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgBufferOverflow))==-1)
     {
                dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message overflow\n");
                return -1;
@@ -1564,6 +1591,53 @@ int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *
     return 0;
 }
 
+int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
+{
+    int j, sent;
+
+    PRINT_FUNCTION_VERBOSE(verbose);
+
+    if ((daemon==0)  || (daemon_local==0))
+    {
+       dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
+        return -1;
+    }
+
+    /* Store in daemon, that a message buffer overflow has occured */
+    daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_OVERFLOW;
+
+    /* look if TCP connection to client is available */
+    sent = 0;
+
+    for (j = 0; j <= daemon_local->fdmax; j++)
+    {
+        /* send to everyone! */
+        if (FD_ISSET(j, &(daemon_local->master)))
+        {
+            /* except the listener and ourselves */
+            if ((j != daemon_local->fp) && (j != daemon_local->sock)
+#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                        && (j!=daemon_local->timer_wd)
+#endif
+                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
+            {
+                dlt_daemon_control_message_buffer_overflow(j, daemon,daemon->overflow_counter,"", verbose);
+                sent=1;
+                /* Reset overflow state */
+                daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_NO_OVERFLOW;
+            } /* if */
+        } /* if */
+    } /* for */
+
+    /* message was not sent, so report to caller that sending failed */
+    if (sent==0)
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
 int dlt_daemon_process_user_message_register_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
 {
     uint32_t len=0;
@@ -1763,7 +1837,11 @@ int dlt_daemon_process_user_message_register_context(DltDaemon *daemon, DltDaemo
             if (FD_ISSET(j, &(daemon_local->master)))
             {
                 /* except the listener and ourselves */
-                if ((j != daemon_local->fp) && (j != daemon_local->sock))
+                if ((j != daemon_local->fp) && (j != daemon_local->sock)
+    #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                            && (j!=daemon_local->timer_wd)
+    #endif
+                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
                 {
                     dlt_daemon_control_get_log_info(j , daemon, &msg, verbose);
                     sent=1;
@@ -1902,6 +1980,38 @@ int dlt_daemon_process_user_message_unregister_context(DltDaemon *daemon, DltDae
                }
     }
 
+    /* Create automatic unregister context response for unregistered context */
+    if (daemon_local->flags.rflag)
+    {
+        int sent=0;
+        int j;
+
+        /* Send response to get log info request to DLT clients */
+        for (j = 0; j <= daemon_local->fdmax; j++)
+        {
+            /* send to everyone! */
+            if (FD_ISSET(j, &(daemon_local->master)))
+            {
+                /* except the listener and ourselves */
+                if ((j != daemon_local->fp) && (j != daemon_local->sock)
+    #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                            && (j!=daemon_local->timer_wd)
+    #endif
+                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
+                {
+                       dlt_daemon_control_message_unregister_context(j,daemon,usercontext->apid, usercontext->ctid, "remo",verbose);
+                    sent=1;
+                }
+            }
+        }
+
+        if (sent==0)
+        {
+            /* Store to buffer */
+               dlt_daemon_control_message_unregister_context(DLT_DAEMON_STORE_TO_BUFFER,daemon,usercontext->apid, usercontext->ctid, "remo",verbose);
+        }
+    }
+
     /* keep not read data in buffer */
     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgUnregisterContext))==-1)
     {
@@ -1999,6 +2109,17 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltDaemonLocal *daemo
                                sent = 1;
                        }
 
+                       /* check if overflow occurred */
+                       if(daemon->overflow_counter)
+                       {
+                               if(dlt_daemon_send_message_overflow(daemon,daemon_local,verbose)==0)
+                               {
+                                       sprintf(str,"%u messages discarded!\n",daemon->overflow_counter);
+                                       dlt_log(LOG_ERR, str);
+                                       daemon->overflow_counter=0;
+                               }
+                       }
+
             /* look if TCP connection to client is available */
             for (j = 0;((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) &&  (j <= daemon_local->fdmax); j++)
             {
@@ -2015,7 +2136,11 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltDaemonLocal *daemo
                         third_value = daemon_local->sock;
                     }
 
-                    if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value))
+                                       if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value)
+               #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                                                               && (j!=daemon_local->timer_wd)
+               #endif
+                                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
                     {
                         DLT_DAEMON_SEM_LOCK();
 
@@ -2075,7 +2200,9 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltDaemonLocal *daemo
                                     0, 0
                                    )<0)
                                {
-                                       dlt_log(LOG_ERR,"Storage of message in history buffer failed! Message discarded.\n");
+                       if(daemon->overflow_counter==0)
+                                       dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
+                       daemon->overflow_counter+=1;
                                }
                 DLT_DAEMON_SEM_FREE();
             }
@@ -2430,7 +2557,11 @@ int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daem
                     third_value = daemon_local->sock;
                 }
 
-                if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value))
+                               if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value)
+       #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                                                       && (j!=daemon_local->timer_wd)
+       #endif
+                               && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
                 {
                     DLT_DAEMON_SEM_LOCK();
 
@@ -2475,167 +2606,6 @@ int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daem
     return 0;
 }
 
-void dlt_daemon_timingpacket_thread(void *ptr)
-{
-    DltDaemonPeriodicData info;
-    int j;
-
-    DltDaemonTimingPacketThreadData *data;
-    DltDaemon *daemon;
-    DltDaemonLocal *daemon_local;
-
-    if (ptr==0)
-    {
-       dlt_log(LOG_ERR, "No data pointer passed to timingpacket thread\n");
-        return;
-    }
-
-    data = (DltDaemonTimingPacketThreadData*)ptr;
-    daemon = data->daemon;
-    daemon_local = data->daemon_local;
-
-    if ((daemon==0) || (daemon_local==0))
-    {
-       dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_timingpacket_thread()");
-        return;
-    }
-
-    if (dlt_daemon_make_periodic (1000000, &info, daemon_local->flags.vflag)<0)
-    {
-        dlt_log(LOG_CRIT,"Can't initialize thread timer!\n");
-        return;
-    }
-
-    while (1)
-    {
-        /* If enabled, send timing packets to all clients */
-        if (daemon->timingpackets)
-        {
-            for (j = 0; j <= daemon_local->fdmax; j++)
-            {
-                /* send to everyone! */
-                if (FD_ISSET(j, &(daemon_local->master)))
-                {
-                    /* except the listener and ourselves */
-                    if ((j != daemon_local->fp) && (j != daemon_local->sock))
-                    {
-                        dlt_daemon_control_message_time(j, daemon, daemon_local->flags.vflag);
-                    }
-                }
-            }
-        }
-        /* Wait for next period */
-        dlt_daemon_wait_period (&info, daemon_local->flags.vflag);
-    }
-}
-
-void dlt_daemon_ecu_version_thread(void *ptr)
-{
-       DltDaemonECUVersionThreadData *data = (DltDaemonECUVersionThreadData *)ptr;
-       DltDaemonPeriodicData info;
-       const unsigned int DLT_ECU_VERSION_PERIOD_TIME = 1000000*60; // 60 Seconds
-
-       if (dlt_daemon_make_periodic (DLT_ECU_VERSION_PERIOD_TIME, &info, data->daemon_local->flags.vflag)<0)
-    {
-        dlt_log(LOG_CRIT,"Can't initialize thread timer!\n");
-        return;
-    }
-
-       while(1)
-       {
-               int i;
-               for (i = 0; i <= data->daemon_local->fdmax; i++)
-               {
-                       /* send to everyone! */
-                       if (FD_ISSET(i, &(data->daemon_local->master)))
-                       {
-                               /* except the listener and ourselves */
-                               if ((i != data->daemon_local->fp) && (i != data->daemon_local->sock))
-                               {
-                                       dlt_daemon_control_get_software_version(i, data->daemon, data->daemon_local->flags.vflag);
-                               }
-                       }
-               }
-               dlt_daemon_wait_period (&info, data->daemon_local->flags.vflag);
-       }
-}
-
-#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE)
-void dlt_daemon_systemd_watchdog_thread(void *ptr)
-{
-    char *watchdogUSec;
-    int watchdogTimeoutSeconds;
-    int notifyPeriodNSec;
-    DltDaemonPeriodicData info;
-    DltDaemonTimingPacketThreadData *data;
-    DltDaemon *daemon;
-    DltDaemonLocal *daemon_local;
-    static uint32_t lastDaemonOperation;
-
-    if (ptr==0)
-    {
-       dlt_log(LOG_ERR, "No data pointer passed to systemd watchdog thread\n");
-        return;
-    }
-
-    data = (DltDaemonTimingPacketThreadData*)ptr;
-    daemon = data->daemon;
-    daemon_local = data->daemon_local;
-
-    if ((daemon==0) || (daemon_local==0))
-    {
-       dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_timingpacket_thread()");
-        return;
-    }
-
-    watchdogUSec = getenv("WATCHDOG_USEC");
-
-       if(watchdogUSec)
-       {
-               watchdogTimeoutSeconds = atoi(watchdogUSec);
-               // Calculate half of WATCHDOG_USEC in ns for timer tick
-               notifyPeriodNSec = watchdogTimeoutSeconds / 2 ;
-
-               if( notifyPeriodNSec > 0 )
-               {
-                       sprintf(str,"systemd watchdog timeout: %i nsec - timer will be initialized: %i nsec\n", watchdogTimeoutSeconds, notifyPeriodNSec );
-                       dlt_log(LOG_INFO, str);
-
-                       if (dlt_daemon_make_periodic (notifyPeriodNSec, &info, daemon_local->flags.vflag)<0)
-                       {
-                               dlt_log(LOG_CRIT, "Could not initialize systemd watchdog timer");
-                               return;
-                       }
-
-                       while (1)
-                       {
-                               /* If main thread has changed its last operation time, reset watchdog */
-                               if(daemon_local->lastOperationTime != lastDaemonOperation)
-                               {
-                                       if(sd_notify(0, "WATCHDOG=1") < 0)
-                                       {
-                                               dlt_log(LOG_CRIT, "Could not reset systemd watchdog\n");
-                                       }
-                                       lastDaemonOperation = daemon_local->lastOperationTime;
-                               }
-
-                               /* Wait for next period */
-                               dlt_daemon_wait_period (&info, daemon_local->flags.vflag);
-                       }
-               }
-               else
-               {
-                       sprintf(str,"systemd watchdog timeout incorrect: %i\n", watchdogTimeoutSeconds);
-                       dlt_log(LOG_CRIT, str);
-               }
-       }
-       else
-       {
-               dlt_log(LOG_CRIT, "systemd watchdog timeout (WATCHDOG_USEC) is null!\n");
-       }
-}
-#endif
-
 int dlt_daemon_make_periodic (unsigned int period, DltDaemonPeriodicData *info, int verbose)
 {
     int ret;
@@ -2695,6 +2665,118 @@ void dlt_daemon_wait_period (DltDaemonPeriodicData *info, int verbose)
     }
 }
 
+int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, int* fd, const char* timer_name)
+{
+    int local_fd;
+    struct itimerspec l_timer_spec;
+
+    if(timer_name == NULL)
+    {
+        timer_name = "timer_not_named";
+    }
+
+    if( fd == NULL )
+    {
+        snprintf(str, sizeof(str), "<%s> fd is NULL pointer\n", timer_name );
+        dlt_log(DLT_LOG_ERROR, str);
+        return -1;
+    }
+
+    if( period_sec > 0 ) {
+        local_fd = timerfd_create(CLOCK_MONOTONIC, 0);
+        if( local_fd < 0)
+        {
+            snprintf(str, sizeof(str), "<%s> timerfd_create failed: %s\n", timer_name, strerror(errno));
+            dlt_log(DLT_LOG_ERROR, str);
+        }
+
+        l_timer_spec.it_interval.tv_sec = period_sec;
+        l_timer_spec.it_interval.tv_nsec = 0;
+        l_timer_spec.it_value.tv_sec = starts_in;
+        l_timer_spec.it_value.tv_nsec = 0;
+
+        if( timerfd_settime( local_fd, 0, &l_timer_spec, NULL) < 0)
+        {
+            snprintf(str, sizeof(str), "<%s> timerfd_settime failed: %s\n", timer_name, strerror(errno));
+            dlt_log(DLT_LOG_ERROR, str);
+            local_fd = -1;
+        }
+    }
+    else {
+        // timer not activated via the service file
+        snprintf(str, sizeof(str), "<%s> not set: period=0\n", timer_name);
+        dlt_log(DLT_LOG_INFO, str);
+        local_fd = -1;
+    }
+
+    // If fd is fully initialized, let's add it to the fd sets
+    if(local_fd>0)
+    {
+        snprintf(str, sizeof(str), "<%s> initialized with %ds timer\n", timer_name, period_sec);
+        dlt_log(DLT_LOG_INFO, str);
+
+        FD_SET(local_fd, &(daemon_local->master));
+        //FD_SET(local_fd, &(daemon_local->timer_fds));
+        if (local_fd > daemon_local->fdmax)
+        {
+            daemon_local->fdmax = local_fd;
+        }
+    }
+
+    *fd = local_fd;
+
+    return local_fd;
+}
+
+void dlt_daemon_send_timingpacket(DltDaemon *daemon, DltDaemonLocal *daemon_local)
+{
+    int j;
+
+    if (daemon->timingpackets)
+    {
+        for (j = 0; j <= daemon_local->fdmax; j++)
+        {
+            /* send to everyone! */
+            if (FD_ISSET(j, &(daemon_local->master)))
+            {
+                /* except the listener and ourselves */
+                if ((j != daemon_local->fp) && (j != daemon_local->sock)
+#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                        && (j!=daemon_local->timer_wd)
+#endif
+                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion) )
+                {
+                    dlt_log(LOG_DEBUG, "timingpacket\n");
+                    dlt_daemon_control_message_time(j, daemon, daemon_local->flags.vflag);
+                }
+            }
+        }
+    }
+}
+
+void dlt_daemon_send_ecuversion(DltDaemon *daemon, DltDaemonLocal *daemon_local)
+{
+    int j;
+
+    for (j = 0; j <= daemon_local->fdmax; j++)
+    {
+        /* send to everyone! */
+        if (FD_ISSET(j, &(daemon_local->master)))
+        {
+            /* except the listener and ourselves */
+            if ((j != daemon_local->fp) && (j != daemon_local->sock)
+#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
+                        && (j!=daemon_local->timer_wd)
+#endif
+                       && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
+            {
+                dlt_log(LOG_DEBUG, "ecu_version\n");
+                               dlt_daemon_control_get_software_version(j, daemon, daemon_local->flags.vflag);
+            }
+        }
+    }
+}
+
 /**
   \}
 */