1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = childhandler;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n",
argv[0], strerror(errno));
MERO_EXIT(1);
}
/**
* Handles SIGCHLD signals, that is, signals that a parent receives
* about its children. This handler deals with terminated children, by
* deregistering them from the internal administration (_mero_topdp)
* with the necessary cleanup.
*/
void childhandler(int sig, siginfo_t *si, void *unused)
{
dpair p, q;
(void)sig;
(void)unused;
/* wait for the child to get properly terminated, hopefully filling
* in the siginfo struct on FreeBSD */
wait(NULL);
if (si->si_code != CLD_EXITED &&
si->si_code != CLD_KILLED &&
si->si_code != CLD_DUMPED)
{
/* ignore traps, stops and continues, we only want terminations
* of the client process */
return;
}
pthread_mutex_lock(&_mero_topdp_lock);
/* get the pid from the former child, and locate it in our list */
q = _mero_topdp->next;
p = q->next;
while (p != NULL) {
if (p->pid == si->si_pid) {
/* log everything that's still in the pipes */
logFD(p->out, "MSG", p->dbname, (long long int)p->pid, _mero_logfile);
/* remove from the list */
q->next = p->next;
/* close the descriptors */
close(p->out);
close(p->err);
if (si->si_code == CLD_EXITED) {
Mfprintf(stdout, "database '%s' (%lld) has exited with "
"exit status %d\n", p->dbname,
(long long int)p->pid, si->si_status);
} else if (si->si_code == CLD_KILLED) {
char *sigstr = sigtostr(si->si_status);
char signum[8];
if (sigstr == NULL) {
snprintf(signum, 8, "%d", si->si_status);
sigstr = signum;
}
Mfprintf(stdout, "database '%s' (%lld) was killed by signal "
"%s\n", p->dbname,
(long long int)p->pid, sigstr);
} else if (si->si_code == CLD_DUMPED) {
Mfprintf(stdout, "database '%s' (%lld) has crashed "
"(dumped core)\n", p->dbname,
(long long int)p->pid);
}
if (p->dbname)
free(p->dbname);
free(p);
pthread_mutex_unlock(&_mero_topdp_lock);
return;
}
q = p;
p = q->next;
}
pthread_mutex_unlock(&_mero_topdp_lock);
Mfprintf(stdout, "received SIGCHLD from unknown child with pid %lld\n",
(long long int)si->si_pid);
}
|