our_kill_is_busted.c [plain text]
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int
main(void)
{
int wstatus;
pid_t p, wr;
int kill_r, killpg_r, r;
int kill_e, killpg_e;
p = fork();
assert(p != -1);
if (p == 0) {
r = setsid();
assert(r != -1);
_exit(EXIT_SUCCESS);
}
sleep(1);
errno = 0;
kill_r = kill(p, SIGTERM);
kill_e = errno;
errno = 0;
killpg_r = kill(-(p), SIGTERM);
killpg_e = errno;
if (kill_r != killpg_r) {
fprintf(stderr, "Bug. kill() is inconsistent.\n");
fprintf(stderr, "kill( p, SIGTERM) returned %d and errno == %d\n", kill_r, kill_e);
fprintf(stderr, "kill(-(p), SIGTERM) returned %d and errno == %d\n", killpg_r, killpg_e);
if (kill_e == EPERM || killpg_e == EPERM) {
fprintf(stderr, "The kernel lied. We should have the right to kill 'p' and it returned EPERM.\n");
}
if (kill_e == ESRCH || killpg_e == ESRCH) {
fprintf(stderr, "The kernel is confused. PID 'p' exists, but the kernel couldn't find it.\n");
}
exit(EXIT_FAILURE);
}
wr = waitpid(p, &wstatus, 0);
assert(wr == p);
exit(EXIT_SUCCESS);
}