I'm not cutting it with just the man pages and my least unsuccessful search, "sigaction example", hasn't helped me understand it much better. Some questions / assumptions:
- SA_RESTART: "restarting a signal", though it should no be used, means that if the signal (SIGCHLD I believe) is interrupted, the signal will be sent again until it is no longer interrupted? Ie. does "restarting a signal" mean "sending it again"?
- Omitting to set sa_flags causes the program to segfault right after the child exits. Is this because the default is then SA_SIGINFO which expects 3 arguments while my handler only accepts one? Should I use this and change my handler?
- In an example on the web I found the construct below to set the sa_flags and the source says it's a standard of some kind but does not explain what it does and why you'd want to. For example: "Restore the signal action to the default state once the signal handler has been called.", I don't know how to interpret that.
- If I would use SA_NOCLDWAIT, does that mean that the parent will not know whether or not the child was successfully reaped and thus a bad idea?
- Am I entirely missing the point here and should I be looking for something else?
Thanks,
heras
edit: btw, the code below fails to clean up child processes and intermittently returns "accept: Interrupted system call".
Code:
void sigchld_handler(int s)
{
while (waitpid(-1, NULL, WNOHANG) > 0);
}
Code:
int check_sigaction(struct sigaction *sa)
{
int ret;
while ((ret = sigaction(SIGCHLD, sa, NULL)) == -1 && errno == EINTR);
return (ret);
}
Code:
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_flags = sa.sa_flags | SA_NODEFER | SA_RESETHAND;
if (check_sigaction(&sa) == -1) {
perror("sigaction");
exit (EXIT_FAILURE);
}
while (1) {
sin_size = sizeof remote_address;
if ((new_fd = accept(sockfd, (struct sockaddr *)&remote_address, \
&sin_size)) == -1) {
perror("accept");
continue;
}
if (!fork()) {
close(sockfd);
if (recv(new_fd, message, sizeof(message), 0) == -1) {
perror("recv");
}
else {
printf("%s\n", message);
send(new_fd, reply, strlen(reply) + 1, 0);
}
close(new_fd);
exit (EXIT_SUCCESS);
}
close(new_fd);
}
return (EXIT_SUCCESS);
}