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
This commit is contained in:
Azat Khuzhin 2016-08-11 16:15:45 +03:00
parent 16d220cb6f
commit 43eb56c7c7
5 changed files with 50 additions and 2 deletions

View File

@ -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)

View File

@ -0,0 +1,18 @@
include(CheckCSourceRuns)
check_c_source_runs(
"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
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)

View File

@ -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 <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
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

View File

@ -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

View File

@ -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"));