mdbx-test: rework/fix actor_poll() to avoid loosing SIGCHLD.

Change-Id: I93aa2aa40e07e807795e050cd468d77dab62e67a
This commit is contained in:
Leonid Yuriev 2019-10-12 10:24:18 +03:00
parent c51a6e6d95
commit 23733bf4af

View File

@ -179,7 +179,11 @@ bool osal_progress_push(bool active) {
static std::unordered_map<pid_t, actor_status> childs; static std::unordered_map<pid_t, actor_status> childs;
static void handler_SIGCHLD(int signum) { (void)signum; } static volatile sig_atomic_t sigalarm_head;
static void handler_SIGCHLD(int signum) {
if (signum == SIGALRM)
sigalarm_head += 1;
}
mdbx_pid_t osal_getpid(void) { return getpid(); } mdbx_pid_t osal_getpid(void) { return getpid(); }
@ -191,6 +195,7 @@ int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) {
memset(&act, 0, sizeof(act)); memset(&act, 0, sizeof(act));
act.sa_handler = handler_SIGCHLD; act.sa_handler = handler_SIGCHLD;
sigaction(SIGCHLD, &act, nullptr); sigaction(SIGCHLD, &act, nullptr);
sigaction(SIGALRM, &act, nullptr);
act.sa_handler = handler_SIGUSR; act.sa_handler = handler_SIGUSR;
sigaction(SIGUSR1, &act, nullptr); sigaction(SIGUSR1, &act, nullptr);
sigaction(SIGUSR2, &act, nullptr); sigaction(SIGUSR2, &act, nullptr);
@ -229,17 +234,25 @@ void osal_killall_actors(void) {
} }
int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
struct timespec ts; static sig_atomic_t sigalarm_tail;
ts.tv_nsec = 0; alarm(0) /* cancel prev timeout */;
ts.tv_sec = (timeout > INT_MAX) ? INT_MAX : timeout; sigalarm_tail = sigalarm_head /* reset timeout flag */;
retry:
int status, options = WNOHANG; int options = WNOHANG;
if (timeout) {
alarm((timeout > INT_MAX) ? INT_MAX : timeout);
options = 0;
}
#ifdef WUNTRACED #ifdef WUNTRACED
options |= WUNTRACED; options |= WUNTRACED;
#endif #endif
#ifdef WCONTINUED #ifdef WCONTINUED
options |= WCONTINUED; options |= WCONTINUED;
#endif #endif
while (sigalarm_tail == sigalarm_head) {
int status;
pid = waitpid(0, &status, options); pid = waitpid(0, &status, options);
if (pid > 0) { if (pid > 0) {
@ -264,35 +277,24 @@ retry:
if (sigusr1_tail != sigusr1_head) { if (sigusr1_tail != sigusr1_head) {
sigusr1_tail = sigusr1_head; sigusr1_tail = sigusr1_head;
logging::progress_canary(true); logging::progress_canary(true);
if (pid < 0 && errno == EINTR)
continue;
} }
if (sigusr2_tail != sigusr2_head) { if (sigusr2_tail != sigusr2_head) {
sigusr2_tail = sigusr2_head; sigusr2_tail = sigusr2_head;
logging::progress_canary(false); logging::progress_canary(false);
if (pid < 0 && errno == EINTR)
continue;
} }
if (pid == 0) { if (pid == 0)
/* child still running */ break;
if (ts.tv_sec == 0 && ts.tv_nsec == 0)
ts.tv_nsec = 1;
if (nanosleep(&ts, &ts) == 0) {
/* timeout and no signal from child */
pid = 0;
return 0;
}
if (errno == EINTR)
goto retry;
}
switch (errno) { int err = errno;
case EINTR: if (err != EINTR)
pid = 0; return err;
return 0;
case ECHILD:
default:
pid = 0;
return errno;
} }
return 0 /* timeout */;
} }
void osal_yield(void) { void osal_yield(void) {