You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by vi...@apache.org on 2008/02/04 20:17:45 UTC

svn commit: r618388 - /stdcxx/branches/4.2.x/tests/src/process.cpp

Author: vitek
Date: Mon Feb  4 11:17:43 2008
New Revision: 618388

URL: http://svn.apache.org/viewvc?rev=618388&view=rev
Log:

2008-02-04  Travis Vitek  <vi...@roguewave.com>

	Merged rev 618385 from trunk.

	STDCXX-625
	* tests/src/process.cpp (rw_waitpid): Use sigaction() instead of
	signal() where available.


Modified:
    stdcxx/branches/4.2.x/tests/src/process.cpp

Modified: stdcxx/branches/4.2.x/tests/src/process.cpp
URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/tests/src/process.cpp?rev=618388&r1=618387&r2=618388&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/tests/src/process.cpp (original)
+++ stdcxx/branches/4.2.x/tests/src/process.cpp Mon Feb  4 11:17:43 2008
@@ -193,6 +193,7 @@
 #  include <unistd.h>     // for fork(), execv(), access(), sleep()
 #  include <setjmp.h>     // for setjmp(), longjmp()
 #  include <signal.h>     // for signal()
+#  include <time.h>       // for time()
 
 /**************************************************************************/
 
@@ -519,97 +520,140 @@
 
 extern "C" {
 
-typedef void sig_handler_t (int);
+static int alarm_timeout;
 
-static void
-sig_handler (int)
-{
-    // do not re-register for signal here. it causes
-    // a stack overflow problem on HP-UX and AIX.
+static void handle_alarm_signal (int) {
+    alarm_timeout = 1;
 }
 
+typedef void (*signal_handler_t) (int);
+
 }
 
 _TEST_EXPORT rw_pid_t
-rw_waitpid (rw_pid_t pid, int* result, int timeout/* = -1*/)
+rw_waitpid (rw_pid_t pid, int* presult, int timeout/* = -1*/)
 {
-    int status = 0;
-    const int options = 0 > timeout ? 0 : WNOHANG;
+#ifdef _RWSTD_EDG_ECCP
+#  define _RWSTD_NO_SIGACTION
+#endif
 
-    rw_pid_t ret = waitpid (pid, &status, options);
-    if (-1 == ret)
-        rw_error (0, __FILE__, __LINE__,
-                  "waitpid (%{P}, %#p, %{?}WNOHANG%{:}%i%{;}) failed: "
-                  "errno = %{#m} (%{m})",
-                  pid, &status, WNOHANG == options, options);
+#ifndef _RWSTD_NO_SIGACTION
+    struct sigaction prev_alarm_action;
+#else
+    signal_handler_t prev_alarm_handler = 0;
+#endif
+    int              prev_alarm_timeout = 0;
+
+    alarm_timeout = 0;
+    if (0 < timeout) {
 
-    if (0 < timeout && 0 == ret) {
-        // process still active, wait
+#ifndef _RWSTD_NO_SIGACTION
+        struct sigaction alarm_action;
+        memset (&alarm_action, 0, sizeof alarm_action);
 
-        unsigned utimeout = unsigned (timeout);
+        const signal_handler_t handler_fun = handle_alarm_signal;
+        memcpy (&alarm_action.sa_handler, &handler_fun,
+                sizeof alarm_action.sa_handler);
 
-        do {
-            sig_handler_t* old_handler = signal (SIGCHLD, sig_handler);
+        sigaction (SIGALRM, &alarm_action, &prev_alarm_action);
+#else
+        prev_alarm_handler = signal (SIGALRM, handle_alarm_signal);
+#endif
+        prev_alarm_timeout = alarm (timeout);
 
-            utimeout = sleep (utimeout);
+    }
 
-            signal (SIGCHLD, old_handler);
+    int result = 0;
+    if (!presult)
+        presult = &result;
 
-            if (utimeout) {
-                // possible that the child has exited
-                ret = waitpid (pid, &status, WNOHANG);
-                if (-1 == ret) {
-                    rw_error (0, __FILE__, __LINE__,
-                              "waitpid (%{P}, %#p, WNOHANG) failed: "
-                              "errno = %{#m} (%{m})",
-                              pid, &status);
-                }
-                else if (0 == ret) {
-                    // child still active
-                    continue;
-                }
-                else {
-                    // child has exited
-                    RW_ASSERT (pid == ret);
-                }
+    const time_t start = time(0);
+
+    int status   = 0;
+    rw_pid_t ret = 0;
+    do {
+
+        ret = waitpid (pid, &status, 0);
+
+        if (-1 == ret) {
+
+            if (EINTR == errno && alarm_timeout) {
+
+                // we are expected to return 0 on timeout
+                ret = 0;
+            }
+            else if (EINTR == errno) {
+
+                rw_warn (0, __FILE__, __LINE__,
+                         "waitpid (%{P}, %#p, 0) interrupted: "
+                         "errno = %{#m} (%{m})",
+                         pid, &status);
+
+                continue; // try again
             }
             else {
-                // timeout elapsed
-                RW_ASSERT (0 == ret);
+
+                rw_error (0, __FILE__, __LINE__,
+                          "waitpid (%{P}, %#p, 0) failed: "
+                          "errno = %{#m} (%{m})",
+                          pid, &status);
             }
+
         }
-        while (false);
-    }
+        else if (ret == pid) {
 
-    if (ret == pid) {
+            if (WIFSIGNALED (status)) {
+                // process exited with a signal
+                const int signo = WTERMSIG (status);
 
-        if (WIFSIGNALED (status)) {
-            // process exited with a signal
-            const int signo = WTERMSIG (status);
+                rw_error (0, __FILE__, __LINE__,
+                          "the process (pid=%{P}) exited with signal %d (%{K})",
+                          pid, signo, signo);
 
-            rw_error (0, __FILE__, __LINE__,
-                      "the process (pid=%{P}) exited with signal %d (%{K})",
-                      pid, signo, signo);
+                *presult = signo;
+            }
+            else if (WIFEXITED (status)) {
+                // process exited with a status
+                const int retcode = WEXITSTATUS (status);
 
-            if (result)
-                *result = signo;
+                if (retcode)
+                    rw_error (0, __FILE__, __LINE__,
+                              "the process (pid=%{P}) exited with return code %d",
+                              pid, retcode);
+
+                *presult = retcode;
+            }
+            else {
+                *presult = -1;
+            }
+        }
+        else {
+            *presult = -1;
         }
-        else if (WIFEXITED (status)) {
-            // process exited with a status
-            const int retcode = WEXITSTATUS (status);
 
-            if (retcode)
-                rw_error (0, __FILE__, __LINE__,
-                          "the process (pid=%{P}) exited with return code %d",
-                          pid, retcode);
+    } while(false);
 
-            if (result)
-                *result = retcode;
+    if (0 < timeout) {
+
+        if (prev_alarm_timeout) {
+            const int delta = time(0) - start;
+
+            if (delta < prev_alarm_timeout)
+                prev_alarm_timeout -= delta;
+            else
+                prev_alarm_timeout = 1;
         }
-        else if (result)
-            *result = -1;
-    }
 
+        alarm (prev_alarm_timeout);
+
+#ifndef _RWSTD_NO_SIGACTION
+        sigaction (SIGALRM, &prev_alarm_action, 0);
+#else
+        signal (SIGALRM, prev_alarm_handler);
+#endif
+
+    }    
+    
     return ret;
 }