mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-20 05:18:21 +08:00
mdbx-test: rework/fix actor_poll() to avoid loosing SIGCHLD.
Change-Id: I93aa2aa40e07e807795e050cd468d77dab62e67a
This commit is contained in:
parent
c51a6e6d95
commit
23733bf4af
@ -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,70 +234,67 @@ 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
|
||||||
pid = waitpid(0, &status, options);
|
|
||||||
|
|
||||||
if (pid > 0) {
|
while (sigalarm_tail == sigalarm_head) {
|
||||||
if (WIFEXITED(status))
|
int status;
|
||||||
childs[pid] =
|
pid = waitpid(0, &status, options);
|
||||||
(WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed;
|
|
||||||
else if (WCOREDUMP(status))
|
|
||||||
childs[pid] = as_coredump;
|
|
||||||
else if (WIFSIGNALED(status))
|
|
||||||
childs[pid] = as_killed;
|
|
||||||
else if (WIFSTOPPED(status))
|
|
||||||
childs[pid] = as_debuging;
|
|
||||||
else if (WIFCONTINUED(status))
|
|
||||||
childs[pid] = as_running;
|
|
||||||
else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sig_atomic_t sigusr1_tail, sigusr2_tail;
|
if (pid > 0) {
|
||||||
if (sigusr1_tail != sigusr1_head) {
|
if (WIFEXITED(status))
|
||||||
sigusr1_tail = sigusr1_head;
|
childs[pid] =
|
||||||
logging::progress_canary(true);
|
(WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed;
|
||||||
}
|
else if (WCOREDUMP(status))
|
||||||
if (sigusr2_tail != sigusr2_head) {
|
childs[pid] = as_coredump;
|
||||||
sigusr2_tail = sigusr2_head;
|
else if (WIFSIGNALED(status))
|
||||||
logging::progress_canary(false);
|
childs[pid] = as_killed;
|
||||||
}
|
else if (WIFSTOPPED(status))
|
||||||
|
childs[pid] = as_debuging;
|
||||||
if (pid == 0) {
|
else if (WIFCONTINUED(status))
|
||||||
/* child still running */
|
childs[pid] = as_running;
|
||||||
if (ts.tv_sec == 0 && ts.tv_nsec == 0)
|
else {
|
||||||
ts.tv_nsec = 1;
|
assert(false);
|
||||||
if (nanosleep(&ts, &ts) == 0) {
|
}
|
||||||
/* timeout and no signal from child */
|
|
||||||
pid = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (errno == EINTR)
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (errno) {
|
static sig_atomic_t sigusr1_tail, sigusr2_tail;
|
||||||
case EINTR:
|
if (sigusr1_tail != sigusr1_head) {
|
||||||
pid = 0;
|
sigusr1_tail = sigusr1_head;
|
||||||
return 0;
|
logging::progress_canary(true);
|
||||||
|
if (pid < 0 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sigusr2_tail != sigusr2_head) {
|
||||||
|
sigusr2_tail = sigusr2_head;
|
||||||
|
logging::progress_canary(false);
|
||||||
|
if (pid < 0 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
case ECHILD:
|
if (pid == 0)
|
||||||
default:
|
break;
|
||||||
pid = 0;
|
|
||||||
return errno;
|
int err = errno;
|
||||||
|
if (err != EINTR)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
return 0 /* timeout */;
|
||||||
}
|
}
|
||||||
|
|
||||||
void osal_yield(void) {
|
void osal_yield(void) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user