"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/lib-test/test-subprocess.c" between
dovecot-2.3.16.tar.gz and dovecot-2.3.17.tar.gz

About: Dovecot is an IMAP and POP3 server, written with security primarily in mind.

test-subprocess.c  (dovecot-2.3.16):test-subprocess.c  (dovecot-2.3.17)
/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */ /* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
#include "lib.h" #include "lib.h"
#include "lib-signals.h" #include "lib-signals.h"
#include "hostpid.h" #include "hostpid.h"
#include "array.h" #include "array.h"
#include "ioloop.h" #include "ioloop.h"
#include "sleep.h"
#include "test-common.h" #include "test-common.h"
#include "test-subprocess.h" #include "test-subprocess.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
struct test_subprocess { struct test_subprocess {
pid_t pid; pid_t pid;
}; };
volatile sig_atomic_t test_subprocess_is_child = 0; volatile sig_atomic_t test_subprocess_is_child = 0;
static bool test_subprocess_lib_init = FALSE; static bool test_subprocess_lib_init = FALSE;
static volatile bool test_subprocess_notification_signal_received[SIGUSR1 + 1];
static struct event *test_subprocess_event = NULL; static struct event *test_subprocess_event = NULL;
static ARRAY(struct test_subprocess *) test_subprocesses = ARRAY_INIT; static ARRAY(struct test_subprocess *) test_subprocesses = ARRAY_INIT;
static void (*test_subprocess_cleanup_callback)(void) = NULL; static void (*test_subprocess_cleanup_callback)(void) = NULL;
static void static void
test_subprocess_signal(const siginfo_t *si ATTR_UNUSED, test_subprocess_signal(const siginfo_t *si ATTR_UNUSED,
void *context ATTR_UNUSED) void *context ATTR_UNUSED)
{ {
io_loop_stop(current_ioloop); io_loop_stop(current_ioloop);
} }
skipping to change at line 87 skipping to change at line 89
test_exit((test_has_failed() ? 1 : 0)); test_exit((test_has_failed() ? 1 : 0));
} }
#undef test_subprocess_fork #undef test_subprocess_fork
void test_subprocess_fork(int (*func)(void *context), void *context, void test_subprocess_fork(int (*func)(void *context), void *context,
bool continue_test) bool continue_test)
{ {
struct test_subprocess *subprocess; struct test_subprocess *subprocess;
subprocess = i_new(struct test_subprocess, 1); subprocess = i_new(struct test_subprocess, 1);
array_push_back(&test_subprocesses, &subprocess);
lib_signals_ioloop_detach(); lib_signals_ioloop_detach();
/* avoid races: fork the child process with test_subprocess_is_child
set to 1 in case it immediately receives a signal. */
test_subprocess_is_child = 1;
if ((subprocess->pid = fork()) == (pid_t)-1) if ((subprocess->pid = fork()) == (pid_t)-1)
i_fatal("test: sub-process: fork() failed: %m"); i_fatal("test: sub-process: fork() failed: %m");
if (subprocess->pid == 0) { if (subprocess->pid == 0) {
test_subprocess_is_child = 1;
test_subprocess_free_all(); test_subprocess_free_all();
test_subprocess_child(func, context, continue_test); test_subprocess_child(func, context, continue_test);
i_unreached(); i_unreached();
} }
test_subprocess_is_child = 0;
array_push_back(&test_subprocesses, &subprocess);
lib_signals_ioloop_attach(); lib_signals_ioloop_attach();
} }
static void test_subprocess_verify_exit_status(int status) static void test_subprocess_verify_exit_status(int status)
{ {
test_out_quiet("sub-process ended properly", test_out_quiet("sub-process ended properly",
WIFEXITED(status) && WEXITSTATUS(status) == 0); WIFEXITED(status) && WEXITSTATUS(status) == 0);
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) { if (WEXITSTATUS(status) != 0) {
e_warning(test_subprocess_event, e_warning(test_subprocess_event,
skipping to change at line 131 skipping to change at line 136
WSTOPSIG(status)); WSTOPSIG(status));
} else { } else {
e_warning(test_subprocess_event, e_warning(test_subprocess_event,
"Sub-process terminated abnormally with status %d", "Sub-process terminated abnormally with status %d",
status); status);
} }
} }
static void test_subprocess_kill_forced(struct test_subprocess *subp) static void test_subprocess_kill_forced(struct test_subprocess *subp)
{ {
i_assert(subp->pid > 0);
(void)kill(subp->pid, SIGKILL); (void)kill(subp->pid, SIGKILL);
(void)waitpid(subp->pid, NULL, 0); (void)waitpid(subp->pid, NULL, 0);
} }
void test_subprocess_kill_all(unsigned int timeout_secs) void test_subprocess_kill_all(unsigned int timeout_secs)
{ {
struct test_subprocess **subps; struct test_subprocess **subps;
unsigned int subps_count, subps_left, i; unsigned int subps_count, subps_left, i;
subps = array_get_modifiable(&test_subprocesses, &subps_count); subps = array_get_modifiable(&test_subprocesses, &subps_count);
skipping to change at line 284 skipping to change at line 290
int signo = si->si_signo; int signo = si->si_signo;
if (terminating != 0) if (terminating != 0)
raise(signo); raise(signo);
terminating = 1; terminating = 1;
/* Perform important cleanups */ /* Perform important cleanups */
test_subprocess_cleanup(); test_subprocess_cleanup();
(void)signal(signo, SIG_DFL); (void)signal(signo, SIG_DFL);
raise(signo); if (signo == SIGTERM)
_exit(0);
else
raise(signo);
} }
static void test_atexit(void) static void test_atexit(void)
{ {
/* NOTICE: This is also called by children, so be careful. */ /* NOTICE: This is also called by children, so be careful. */
/* Perform important cleanups */ /* Perform important cleanups */
test_subprocess_cleanup(); test_subprocess_cleanup();
} }
void test_subprocess_set_cleanup_callback(void (*callback)(void)) void test_subprocess_set_cleanup_callback(void (*callback)(void))
{ {
test_subprocess_cleanup_callback = callback; test_subprocess_cleanup_callback = callback;
} }
void test_subprocess_notify_signal_send(int signo, pid_t pid)
{
if (kill(pid, signo) < 0)
i_fatal("kill(%ld, SIGHUP) failed: %m", (long)pid);
}
void test_subprocess_notify_signal_send_parent(int signo)
{
test_subprocess_notify_signal_send(signo, getppid());
}
void test_subprocess_notify_signal_reset(int signo)
{
i_assert(signo >= 0 &&
(unsigned int)signo < N_ELEMENTS(test_subprocess_notification_si
gnal_received));
test_subprocess_notification_signal_received[signo] = FALSE;
}
void test_subprocess_notify_signal_wait(int signo, unsigned int timeout_msecs)
{
unsigned int i, count = timeout_msecs / 10;
for (i = 0; i < count; i++) {
if (test_subprocess_notification_signal_received[signo])
return;
i_sleep_msecs(10);
}
i_fatal("Didn't receive wait notification signal from server");
}
static void
test_subprocess_notification_signal(const siginfo_t *si,
void *context ATTR_UNUSED)
{
int signo = si->si_signo;
i_assert(signo >= 0 &&
(unsigned int)signo < N_ELEMENTS(test_subprocess_notification_si
gnal_received));
test_subprocess_notification_signal_received[signo] = TRUE;
}
void test_subprocesses_init(bool debug) void test_subprocesses_init(bool debug)
{ {
if (!lib_is_initialized()) { if (!lib_is_initialized()) {
lib_init(); lib_init();
test_subprocess_lib_init = TRUE; test_subprocess_lib_init = TRUE;
} }
lib_signals_init(); lib_signals_init();
atexit(test_atexit); atexit(test_atexit);
lib_signals_ignore(SIGPIPE, TRUE); lib_signals_ignore(SIGPIPE, TRUE);
lib_signals_set_handler(SIGALRM, 0, test_subprocess_alarm, NULL); lib_signals_set_handler(SIGALRM, 0, test_subprocess_alarm, NULL);
lib_signals_set_handler(SIGTERM, 0, test_subprocess_terminate, NULL); lib_signals_set_handler(SIGTERM, 0, test_subprocess_terminate, NULL);
lib_signals_set_handler(SIGQUIT, 0, test_subprocess_terminate, NULL); lib_signals_set_handler(SIGQUIT, 0, test_subprocess_terminate, NULL);
lib_signals_set_handler(SIGINT, 0, test_subprocess_terminate, NULL); lib_signals_set_handler(SIGINT, 0, test_subprocess_terminate, NULL);
lib_signals_set_handler(SIGSEGV, 0, test_subprocess_terminate, NULL); lib_signals_set_handler(SIGSEGV, 0, test_subprocess_terminate, NULL);
lib_signals_set_handler(SIGABRT, 0, test_subprocess_terminate, NULL); lib_signals_set_handler(SIGABRT, 0, test_subprocess_terminate, NULL);
lib_signals_set_handler(SIGHUP, LIBSIG_FLAG_RESTART,
test_subprocess_notification_signal, NULL);
lib_signals_set_handler(SIGUSR1, LIBSIG_FLAG_RESTART,
test_subprocess_notification_signal, NULL);
i_array_init(&test_subprocesses, 8); i_array_init(&test_subprocesses, 8);
test_subprocess_event = event_create(NULL); test_subprocess_event = event_create(NULL);
event_set_forced_debug(test_subprocess_event, debug); event_set_forced_debug(test_subprocess_event, debug);
event_set_append_log_prefix(test_subprocess_event, "test: "); event_set_append_log_prefix(test_subprocess_event, "test: ");
} }
void test_subprocesses_deinit(void) void test_subprocesses_deinit(void)
{ {
 End of changes. 11 change blocks. 
3 lines changed or deleted 59 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)