From 43eb56c7c738e3642f0981e3dd6ab9e082eec798 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Thu, 11 Aug 2016 16:15:45 +0300 Subject: [PATCH] tests: use waitpid(..., WNOWAIT) to fix failing of main/fork under solaris According to solaris docs: "One instance of a SIGCHLD signal is queued for each child process whose status has changed. If waitpid() returns because the status of a child process is available, and WNOWAIT was not specified in options, any pending SIGCHLD signal associated with the process ID of that child process is discarded. Any other pending SIGCHLD signals remain pending." And interesting thing that it works if you add sleep(1) before waitpid(), and also if you run with --verbose (some race or what). But linux doesn't support WNOWAIT in waitpid() so add detection into cmake/autotools. Fixes: #387 Link: https://bugzilla.redhat.com/show_bug.cgi?id=840782 --- CMakeLists.txt | 2 ++ cmake/CheckWaitpidSupportWNOWAIT.cmake | 18 ++++++++++++++++++ configure.ac | 20 ++++++++++++++++++++ event-config.h.cmake | 3 +++ test/regress.c | 9 +++++++-- 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 cmake/CheckWaitpidSupportWNOWAIT.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 81d3ce14..0323be13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -486,6 +486,8 @@ CHECK_TYPE_SIZE("void *" EVENT__SIZEOF_VOID_P) #CHECK_FILE_OFFSET_BITS() #set(EVENT___FILE_OFFSET_BITS _FILE_OFFSET_BITS) +include(CheckWaitpidSupportWNOWAIT) + # Verify kqueue works with pipes. if (EVENT__HAVE_KQUEUE) if (CMAKE_CROSSCOMPILING AND NOT EVENT__FORCE_KQUEUE_CHECK) diff --git a/cmake/CheckWaitpidSupportWNOWAIT.cmake b/cmake/CheckWaitpidSupportWNOWAIT.cmake new file mode 100644 index 00000000..1a73db37 --- /dev/null +++ b/cmake/CheckWaitpidSupportWNOWAIT.cmake @@ -0,0 +1,18 @@ +include(CheckCSourceRuns) + +check_c_source_runs( +" +#include +#include +#include +#include + +int +main(int argc, char** argv) +{ + pid_t pid; + int status; + if ((pid = fork()) == 0) _exit(0); + _exit(waitpid(pid, &status, WNOWAIT) == -1); +}" +EVENT__HAVE_WAITPID_WITH_WNOWAIT) diff --git a/configure.ac b/configure.ac index 315d97a5..0c41de65 100644 --- a/configure.ac +++ b/configure.ac @@ -605,6 +605,26 @@ main(int argc, char **argv) fi AM_CONDITIONAL(EPOLL_BACKEND, [test "x$haveepoll" = "xyes"]) +AC_MSG_CHECKING(waitpid support WNOWAIT) +AC_TRY_RUN( +#include +#include +#include +#include + +int +main(int argc, char** argv) +{ + pid_t pid; + int status; + if ((pid = fork()) == 0) _exit(0); + _exit(waitpid(pid, &status, WNOWAIT) == -1); +}, [AC_MSG_RESULT(yes) +AC_DEFINE(HAVE_WAITPID_WITH_WNOWAIT, 1, +[Define if waitpid() supports WNOWAIT]) +], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) + + haveeventports=no AC_CHECK_FUNCS(port_create, [haveeventports=yes], ) if test "x$haveeventports" = "xyes" ; then diff --git a/event-config.h.cmake b/event-config.h.cmake index b47a7c4c..6a322a69 100644 --- a/event-config.h.cmake +++ b/event-config.h.cmake @@ -535,4 +535,7 @@ /* Define to 1 if you have ERR_remove_thread_stat(). */ #cmakedefine EVENT__HAVE_ERR_REMOVE_THREAD_STATE +/* Define if waitpid() supports WNOWAIT */ +#cmakedefine EVENT__HAVE_WAITPID_WITH_WNOWAIT + #endif diff --git a/test/regress.c b/test/regress.c index 8879d161..6b6ca9f4 100644 --- a/test/regress.c +++ b/test/regress.c @@ -855,6 +855,11 @@ test_fork(void) int status; struct event ev, sig_ev, usr_ev, existing_ev; pid_t pid; + int wait_flags = 0; + +#ifdef EVENT__HAVE_WAITPID_WITH_WNOWAIT + wait_flags |= WNOWAIT; +#endif setup_test("After fork: "); @@ -929,8 +934,8 @@ test_fork(void) } TT_BLATHER(("Before waitpid")); - if (waitpid(pid, &status, 0) == -1) { - fprintf(stdout, "FAILED (fork)\n"); + if (waitpid(pid, &status, wait_flags) == -1) { + perror("waitpid"); exit(1); } TT_BLATHER(("After waitpid"));