Linux/MacOSX: fix timeout implementation 21/18121/2
Clément DAVID [Tue, 26 Apr 2016 06:53:08 +0000 (08:53 +0200)]
timer_create is not available on MacOS X yet, this implementation uses the
POSIX Thread API to implement a similar behavior.

Change-Id: Iad712e1eacf1d96b3f7aa70dc0b9496c3003f43a

scilab/modules/core/includes/backtrace_print.h
scilab/modules/core/src/c/signal_mgmt.c
scilab/modules/core/src/cpp/backtrace_print.cpp
scilab/modules/startup/src/cpp/scilab.cpp

index c14cc30..c2027c9 100644 (file)
@@ -22,6 +22,6 @@
  * @param unmangle if !=0 then demangle the functions names
  * @return a string (to be freed) containing the complete backtrace
  */
-const char * backtrace_print(int first_level, int unmangle);
+char * backtrace_print(int first_level, int unmangle);
 
 #endif // __BACKTRACE_PRINT_H__
index 503f88a..5f40700 100644 (file)
 */
 
 
+#include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <signal.h>
-#include <time.h>
 #include <string.h>
+#include <time.h>
 #include <libintl.h>
+#include <pthread.h>
 
 #include <setjmp.h>
 
 #include <sys/types.h>          /* getpid */
+#include <sys/time.h>           /* gettimeofday */
 #include <unistd.h>             /* gethostname */
 
 #include "csignal.h"
@@ -64,12 +67,14 @@ static void sig_fatal(int signum, siginfo_t * info, void *p)
 
     char stacktrace_hostname[64];
 
-    const char * bt;
+    char* bt;
 
     gethostname(stacktrace_hostname, sizeof(stacktrace_hostname));
     stacktrace_hostname[sizeof(stacktrace_hostname) - 1] = '\0';
     /* to keep these somewhat readable, only print the machine name */
-    for (i = 0; i < (int)sizeof(stacktrace_hostname); ++i)
+    for (i = 0;
+            i < (int)sizeof(stacktrace_hostname) && stacktrace_hostname[i] != '\0';
+            ++i)
     {
         if (stacktrace_hostname[i] == '.')
         {
@@ -486,25 +491,59 @@ void base_error_init(void)
     }
 }
 
+static void* watchdog_thread(void* arg)
+{
+    long timeoutDelay = (long) arg;
+
+    pthread_mutex_t watchdog_mutex;
+    pthread_cond_t dummy_condition;
+    struct timeval tv;
+    struct timespec abstime;
+
+    if (pthread_mutex_init(&watchdog_mutex, NULL) != 0)
+    {
+        return NULL;
+    }
+
+    if (pthread_cond_init(&dummy_condition, NULL) != 0)
+    {
+        pthread_mutex_destroy(&watchdog_mutex);
+        return NULL;
+    }
+
+    if (gettimeofday(&tv, NULL) != 0)
+    {
+        pthread_cond_destroy(&dummy_condition);
+        pthread_mutex_destroy(&watchdog_mutex);
+        return NULL;
+    }
+
+    memset(&abstime, 0, sizeof(struct timespec));
+    abstime.tv_sec = tv.tv_sec + timeoutDelay;
+
+    while (1)
+    {
+        if (pthread_cond_timedwait(&dummy_condition, &watchdog_mutex, &abstime) == ETIMEDOUT)
+        {
+            /*
+             * Send a SIGABRT to ensure process termination, if used with the signal
+             * trap a backtrace might be displayed.
+             */
+            kill(getpid(), SIGABRT);
+        }
+    }
+    return NULL;
+}
+
 void timeout_process_after(int timeoutDelay)
 {
-    struct sigevent event_timer;
-    timer_t timerid;
-    struct itimerspec value;
-
-    /*
-     * Send a SIGABRT to ensure process termination, if used with the signal
-     * trap a backtrace might be displayed.
-     */
-    memset(&event_timer, 0, sizeof(struct sigevent));
-    event_timer.sigev_notify = SIGEV_SIGNAL;
-    event_timer.sigev_signo = SIGABRT;
-
-    timer_create(CLOCK_MONOTONIC, &event_timer, &timerid);
-
-    memset(&value, 0, sizeof(struct itimerspec));
-    value.it_value.tv_sec = timeoutDelay;
-    timer_settime(timerid, 0, &value, NULL);
+    pthread_t watchdog;
+
+    // Spawn a watchdog thread as POSIX timer API is not available on MacOS X
+    if (pthread_create(&watchdog, NULL, watchdog_thread, (void*) (long) timeoutDelay) != 0)
+    {
+        return;
+    }
 }
 
 /*--------------------------------------------------------------------------*/
index d715a5b..49fd0c3 100644 (file)
@@ -36,7 +36,7 @@ extern "C" {
 #define FUNCNAMEBUFFERSIZE 256
 #define BTBUFFERSIZE 1024
 
-const char * backtrace_print(int niv_debut, int unmangle)
+char * backtrace_print(int niv_debut, int unmangle)
 {
     size_t ind = 0;
     sci_backtrace_t * tr = 0;
index 18145dc..83c9814 100644 (file)
@@ -254,28 +254,26 @@ static int get_option(const int argc, char *argv[], ScilabEngineInfo* _pSEI)
                 char* str_end = NULL;
                 int iTimeoutDelay = strtol(timeout, &str_end, 0);
 
-                int modifier = 1;
-                if (str_end != '\0')
+                int modifier;
+                switch (*str_end)
                 {
-                    switch (*str_end)
-                    {
-                        case 'd':
-                            modifier = 86400;
-                            break;
-                        case 'h':
-                            modifier = 3600;
-                            break;
-                        case 'm':
-                            modifier = 60;
-                            break;
-                        case 's':
-                            modifier = 1;
-                            break;
-                        default:
-                            std::cerr << "Invalid timeout delay unit: s (for seconds), m (for minutes), h (for hours), d (for days) are supported" << std::endl;
-                            exit(EXIT_FAILURE);
-                            break;
-                    }
+                    case 'd':
+                        modifier = 86400;
+                        break;
+                    case 'h':
+                        modifier = 3600;
+                        break;
+                    case 'm':
+                        modifier = 60;
+                        break;
+                    case 's':
+                    case '\0': // no modifiers
+                        modifier = 1;
+                        break;
+                    default:
+                        std::cerr << "Invalid timeout delay unit: s (for seconds, default), m (for minutes), h (for hours), d (for days) are supported" << std::endl;
+                        exit(EXIT_FAILURE);
+                        break;
                 }
 
                 _pSEI->iTimeoutDelay = iTimeoutDelay * modifier;