using c how do I wait for PID X to exit when it is not a child of my current process?
Kill(pid, SIGTERM);
waitpid(pid,NULL,0);
The above does not work as 'pid' is not a child process.
When wait() returns they also define exit status (which tells our, a process why terminated) via pointer, If status are not NULL. If any process has no child process then wait() returns immediately “-1”.
while(wait(NULL) > 0); This ensures that you wait for ALL the child processes and only when all have returned, you move to the next instruction.
wait() and waitpid() The wait() system call suspends execution of the calling thread until one of its children terminates. The call wait(&wstatus) is equivalent to: waitpid(-1, &wstatus, 0); The waitpid() system call suspends execution of the calling thread until a child specified by pid argument has changed state.
This is working sample how to subscribe and use PROC_EVENT_EXIT / PROC_EVENT_FORK events. Tested on kernel 3.3.8
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/connector.h>
#include <linux/cn_proc.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <errno.h>
#define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
sizeof(int))
static int nl_sock;
int connect_to_netlink()
{
struct sockaddr_nl sa_nl; /* netlink interface info */
char buff[NL_MESSAGE_SIZE];
struct nlmsghdr *hdr; /* for telling netlink what we want */
struct cn_msg *msg; /* the actual connector message */
/* connect to netlink socket */
nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
if (-1 == nl_sock) {
perror("socket failed");
return errno;
}
bzero(&sa_nl, sizeof(sa_nl));
sa_nl.nl_family = AF_NETLINK;
sa_nl.nl_groups = CN_IDX_PROC;
sa_nl.nl_pid = getpid();
if (-1 == bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl))) {
perror("bind failed");
return errno;
}
/* Fill header */
hdr = (struct nlmsghdr *)buff;
hdr->nlmsg_len = NL_MESSAGE_SIZE;
hdr->nlmsg_type = NLMSG_DONE;
hdr->nlmsg_flags = 0;
hdr->nlmsg_seq = 0;
hdr->nlmsg_pid = getpid();
/* Fill message */
msg = (struct cn_msg *)NLMSG_DATA(hdr);
msg->id.idx = CN_IDX_PROC; /* Connecting to process information */
msg->id.val = CN_VAL_PROC;
msg->seq = 0;
msg->ack = 0;
msg->flags = 0;
msg->len = sizeof(int);
*(int*)msg->data = PROC_CN_MCAST_LISTEN;
if (-1 == send(nl_sock, hdr, hdr->nlmsg_len, 0)) {
perror("send failed");
return errno;
}
return 0;
}
void handle_events()
{
char buff[CONNECTOR_MAX_MSG_SIZE];
struct nlmsghdr *hdr;
struct proc_event *event;
fd_set fds;
while (1) {
FD_ZERO(&fds);
FD_SET(nl_sock, &fds);
if (0 > select(nl_sock + 1, &fds, NULL, NULL, NULL)) {
perror("select failed");
return ;
}
/* If there were no events detected, return */
if (! FD_ISSET(nl_sock, &fds)) {
return ;
}
/* if there are events, make calls */
if (-1 == recv(nl_sock, buff, sizeof(buff), 0)) {
perror("recv failed");
return ;
}
hdr = (struct nlmsghdr *)buff;
if (NLMSG_ERROR == hdr->nlmsg_type) {
perror("NLMSG_ERROR");
} else if (NLMSG_DONE == hdr->nlmsg_type) {
event = (struct proc_event *)((struct cn_msg *)NLMSG_DATA(hdr))->data;
switch(event->what) {
case proc_event::PROC_EVENT_EXIT:
printf("Process %d (tgid %d) exit with code %d, signal %d\n",
event->event_data.exit.process_pid,
event->event_data.exit.process_tgid,
event->event_data.exit.exit_code,
event->event_data.exit.exit_signal);
break;
case proc_event::PROC_EVENT_FORK:
printf("New process %d (tgid %d), parent %d (tgid %d)\n",
event->event_data.fork.child_pid,
event->event_data.fork.child_tgid,
event->event_data.fork.parent_pid,
event->event_data.fork.parent_tgid);
break;
default:
break;
}
}
}
}
int main(int argc, char *argv[])
{
if (!connect_to_netlink()) {
handle_events();
}
return 0;
}
Compile & run:
# g++ -o psev psev.cpp
# ./psev
Output:
New process 27465 (tgid 27465), parent 2351 (tgid 2351)
Process 27465 (tgid 27465) exit with code 0, signal 17
See this answer by chaos:
The usual practice is to poll using kill(0, pid) and looking for return value -1 and errno of ESRCH to indicate that the process is gone
Based on the man page for kill, it might be kill(pid,0)
instead. But the idea is the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With