[CRIU] [PATCH]v2 service: SIGCHLD handler
Ruslan Kuprieiev
kupruser at gmail.com
Thu Oct 31 16:52:29 PDT 2013
On 31.10.2013 20:06, Pavel Emelyanov wrote:
> On 10/31/2013 04:44 AM, Ruslan Kuprieiev wrote:
>> Hi!
>>
>> Now we're ignoring SIGCHLD from forked children.
>> This patch provides SIGCHLD handler, that will wait for child and write some
>> information about it's exit status to logfile.
>>
>> P.S. This is my first signal handler, so please take a good look at this patch.
>>
>> v2: fixed few mistakes. Thanks Andrew Vagin <avagin at parallels.com> for help.
>>
>> Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
>> ---
>> cr-service.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 75 insertions(+), 2 deletions(-)
>>
>> diff --git a/cr-service.c b/cr-service.c
>> index a79ebc7..a920824 100644
>> --- a/cr-service.c
>> +++ b/cr-service.c
>> @@ -253,6 +253,53 @@ err:
>> return -1;
>> }
>>
>> +static void reap_worker(int signo)
>> +{
>> + int saved_errno;
>> + int status;
>> + pid_t pid;
>> +
>> + saved_errno = errno;
>> +
>> + /*
>> + * Accordingly to signal(7):
>> + * Multiple instances of real-time signals can be queued. By
>> + * contrast, if multiple instances of a standard signal are
>> + * delivered while that signal is currently blocked, then only one
>> + * instance is queued.
> No need in citing man page in code.
>
>> + * So, as we block SIGCHLD, lets wait for every child that has
>> + * changed state.
>> + */
>> + while (1) {
>> + pid = waitpid(-1, &status, WNOHANG|WUNTRACED|WCONTINUED);
> Why just WNOHANG is not enough?
To provide more information.
>> +
>> + if (pid <= 0) {
>> + errno = saved_errno;
>> + return;
>> + }
>> +
>> + if (WIFEXITED(status))
>> + pr_info("Worker(pid %d) exited with %d\n",
>> + pid, WEXITSTATUS(status));
>> +
>> + else if (WIFSIGNALED(status)) {
>> + pr_info("Worker(pid %d) ", pid);
>> +#ifdef WCOREDUMP
>> + if (WCOREDUMP(status))
>> + pr_info("prodused a core dump and ");
>> +#endif
>> + pr_info("was killed by %d\n", WTERMSIG(status));
>> +
>> + } else if (WIFSTOPPED(status))
>> + pr_info("Worker(pid %d) was stopped by %d\n",
>> + pid, WSTOPSIG(status));
>> +
>> + else if (WIFCONTINUED(status))
>> + pr_info("Worker(pid %d) was continued\n", pid);
> I'm not sure we need all the events. Exited and killed is more than enough.
I thought more information is better. Especially, when we got all
information about children from logfile. I also thought, criu has
parasite and stuff and works with kernel, so it wouldn't do any harm, if
we'll provide more information. Or would it?
>> +
>> + }
>> +}
>> +
>> int cr_service(bool daemon_mode)
>> {
>> int server_fd = -1;
>> @@ -264,6 +311,9 @@ int cr_service(bool daemon_mode)
>> socklen_t server_addr_len;
>> socklen_t client_addr_len;
>>
>> + struct sigaction new_action, old_action;
>> + sigset_t block_mask;
> No need in dedicated block_mask, you can fill the mask
> right on sigaction.
>
>> +
>> server_fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
>> if (server_fd == -1) {
>> pr_perror("Can't initialize service socket.");
>> @@ -323,8 +373,25 @@ int cr_service(bool daemon_mode)
>> }
>> }
>>
>> - /* FIXME Do not ignore children's return values */
>> - signal(SIGCHLD, SIG_IGN);
>> + /* Set SIGCHLD handler */
>> + sigemptyset(&block_mask);
>> +
>> + /* FIXME May need to block some other signals too */
>> + sigaddset(&block_mask, SIGCHLD);
>> + sigaddset(&block_mask, SIGINT);
>> + sigaddset(&block_mask, SIGQUIT);
>> + sigaddset(&block_mask, SIGHUP);
>> + sigaddset(&block_mask, SIGTERM);
>> + sigaddset(&block_mask, SIGTSTP);
> Any explanation to this choice?
I've opened man and looked for signals, that may wait for handler to
finish writing to logfile.
>
>> +
>> + new_action.sa_handler = reap_worker;
>> + new_action.sa_mask = block_mask;
>> + new_action.sa_flags = SA_RESTART;
>> +
>> + if (sigaction(SIGCHLD, &new_action, &old_action)) {
>> + pr_perror("Can't setup SIGCHLD handler");
>> + return -1;
>> + }
>>
>> while (1) {
>> int sk;
>> @@ -342,6 +409,12 @@ int cr_service(bool daemon_mode)
>> if (child_pid == 0) {
>> int ret;
>>
>> + /* Set default SIGCHLD handler back */
>> + if (sigaction(SIGCHLD, &old_action, NULL)) {
>> + pr_perror("Can't setup default SIGCHLD handler back");
>> + exit(1);
>> + }
>> +
>> close(server_fd);
>> ret = cr_service_work(sk);
>> close(sk);
>>
>
More information about the CRIU
mailing list