Skip to content

Signals: Child is not receiving signal when sent to process group

When sending a signal to a process group with kill(-pgid, SIGABRT), a child process is not receiving the signal.

// When a negative pid is supplied to kill, all the processes in that group will be signalled

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include "../test_helpers.h"

int handler_called = 0;
void sig_handler(int signum)
{
	(void)signum;
	handler_called = 1;
}

int kill_group(pid_t pgrp_id, int signum)
{
	pid_t child_pid;
	pid_t wait_pid;
	struct sigaction act;
	int status;
	const struct timespec nanos = {
		0, 200000000L};

	handler_called = 0;

	act.sa_handler = sig_handler;
	act.sa_flags = 0;
	status = sigemptyset(&act.sa_mask);
	ERROR_IF(sigemptyset, status, == -1);

	status = sigaction(signum, &act, 0);
	ERROR_IF(sigaction, status, == -1);

	if ((child_pid = fork()) == 0)
	{
		status = sleep(2);

		if (handler_called != 1)
		{
			psignal(signum, "Child handler not called");
			printf("parent pgrp is %d, child pgrp is %d\n", pgrp_id, getpgid((pid_t)0));
			exit(EXIT_FAILURE);
		}
		UNEXP_IF(sleep, status, == 0);

		exit(EXIT_SUCCESS);
	}

	status = nanosleep(&nanos, NULL);
	ERROR_IF(nanosleep, status, != 0);

	status = kill(-pgrp_id, signum);
	ERROR_IF(kill, status, != 0);

	if (handler_called != 1)
	{
		psignal(signum, "Parent handler not called");
		exit(EXIT_FAILURE);
	}

	wait_pid = wait(&status);
	ERROR_IF(wait, wait_pid, != child_pid);

	if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS)
	{
		printf("Failure in child.\n");
		exit(EXIT_FAILURE);
	}

	return EXIT_SUCCESS;
}

int main()
{
	int status;
	pid_t pgrp_id;

	status = setpgid((pid_t)0, (pid_t)0);
	ERROR_IF(setpgid, status, != 0);

	pgrp_id = getpgid((pid_t)0);
	UNEXP_IF(getpgid, pgrp_id, != getpid());

        kill_group(pgrp_id, SIGABRT);

	printf("PASSED\n");
	return EXIT_SUCCESS;
}