diff --git a/configure.ac b/configure.ac index f3fa8b736b..e96d7b8a77 100644 --- a/configure.ac +++ b/configure.ac @@ -292,6 +292,7 @@ fi AC_CHECK_FUNCS(mlockall) AC_CHECK_FUNCS(getpagesizes) AC_CHECK_FUNCS(memcntl) +AC_CHECK_FUNCS(sigignore) AC_DEFUN([AC_C_ALIGNMENT], [AC_CACHE_CHECK(for alignment, ac_cv_c_alignment, @@ -353,9 +354,11 @@ if test "$ICC" = "yes" then dnl ICC trying to be gcc. CFLAGS="$CFLAGS -diag-disable 187 -Wall -Werror" + AC_DEFINE([_GNU_SOURCE],[1],[find sigignore on Linux]) elif test "$GCC" = "yes" then CFLAGS="$CFLAGS -Wall -Werror -pedantic -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls" + AC_DEFINE([_GNU_SOURCE],[1],[find sigignore on Linux]) elif test "$SUNCC" = "yes" then CFLAGS="$CFLAGS -errfmt=error -errwarn -errshort=tags" diff --git a/internal_tests.c b/internal_tests.c index b7661a0007..3429c26ac3 100644 --- a/internal_tests.c +++ b/internal_tests.c @@ -1,8 +1,9 @@ /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ - +#undef NDEBUG #include #include #include +#include #include "memcached.h" @@ -104,11 +105,33 @@ static void test_safe_strtol() { assert(val == 123); } +static void test_issue_44(void) { + char pidfile[80]; + char buffer[256]; + sprintf(pidfile, "/tmp/memcached.%d", getpid()); + sprintf(buffer, "./memcached-debug -p 0 -P %s -d", pidfile); + assert(system(buffer) == 0); + sleep(1); + FILE *fp = fopen(pidfile, "r"); + assert(fp); + assert(fgets(buffer, sizeof(buffer), fp)); + fclose(fp); + pid_t pid = atol(buffer); + assert(kill(pid, 0) == 0); + assert(kill(pid, SIGHUP) == 0); + sleep(1); + assert(kill(pid, 0) == 0); + assert(kill(pid, SIGTERM) == 0); + assert(remove(pidfile) == 0); +} + + int main(int argc, char **argv) { test_safe_strtoull(); test_safe_strtoll(); test_safe_strtoul(); test_safe_strtol(); + test_issue_44(); printf("OK.\n"); return 0; } diff --git a/memcached.c b/memcached.c index e3af50f969..a2d4c59861 100644 --- a/memcached.c +++ b/memcached.c @@ -3895,6 +3895,18 @@ static void sig_handler(const int sig) { exit(EXIT_SUCCESS); } +#ifndef HAVE_SIGIGNORE +static int sigignore(int sig) { + struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = 0 }; + + if (sigemptyset(&sa.sa_mask) == -1 || sigaction(sig, &sa, 0) == -1) { + return -1; + } + return 0; +} +#endif + + #if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) /* * On systems that supports multiple page sizes we may reduce the @@ -3945,7 +3957,6 @@ int main (int argc, char **argv) { char *username = NULL; char *pid_file = NULL; struct passwd *pw; - struct sigaction sa; struct rlimit rlim; /* listening sockets */ static int *l_socket = NULL; @@ -4159,9 +4170,10 @@ int main (int argc, char **argv) { /* daemonize if requested */ /* if we want to ensure our ability to dump core, don't chdir to / */ if (do_daemonize) { - int res; - res = daemonize(maxcore, settings.verbose); - if (res == -1) { + if (sigignore(SIGHUP) == -1) { + perror("Failed to ignore SIGHUP"); + } + if (daemonize(maxcore, settings.verbose) == -1) { fprintf(stderr, "failed to daemon() in order to daemonize\n"); exit(EXIT_FAILURE); } @@ -4196,10 +4208,7 @@ int main (int argc, char **argv) { * ignore SIGPIPE signals; we can use errno == EPIPE if we * need that information */ - sa.sa_handler = SIG_IGN; - sa.sa_flags = 0; - if (sigemptyset(&sa.sa_mask) == -1 || - sigaction(SIGPIPE, &sa, 0) == -1) { + if (sigignore(SIGPIPE) == -1) { perror("failed to ignore SIGPIPE; sigaction"); exit(EX_OSERR); }