void evalcmd(char *argv[], int bg) { int status; pid_t pid; if ((pid = Fork()) == 0) // run cmd as child Execve(argv[0], argv, environ); if (!bg) Waitpid(pid, &status, 0); else { Waitpid(pid, &status, WNOHANG); printf("%d %s\n", pid, argv[0]); } return; }
int main(int argc, char **argv) { int pipe1[2], pipe2[2]; pid_t childpid; Pipe(pipe1); /* create two pipes */ Pipe(pipe2); if ( (childpid = Fork()) == 0) { /* child: write pipe2, read pipe1 */ Close(pipe1[1]); Close(pipe2[0]); server(pipe1[0], pipe2[1]); exit(0); } /* parent , read pipe2 , write pipe1*/ Close(pipe1[0]); Close(pipe2[1]); client(pipe2[0], pipe1[1]); Waitpid(childpid, NULL, 0); /* wait for child to terminate */ exit(0); }
int my_open(const char* pathname, int mode) { int fd, sockfd[2], status; pid_t childpid; char c, argsockfd[10], argmode[10]; Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd); if ((childpid = Fork()) == 0) { /* child process */ Close(sockfd[0]); snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]); snprintf(argmode, sizeof(argmode), "%d", mode); execl("./openfile", "openfile", argsockfd, pathname, argmode, (char*)NULL); err_sys("execl error"); } /* parent process - wait for the child to terminate */ Close(sockfd[1]); /* close the end we don't use */ Waitpid(childpid, &status, 0); if (WIFEXITED(status) == 0) err_quit("child did not terminate"); if ((status = WEXITSTATUS(status)) == 0) Read_fd(sockfd[0], &c, 1, &fd); else { errno = status; /* set errno value from child's status */ fd = -1; } Close(sockfd[0]); return (fd); }
int my_open(const char *pathname, int mode) { int fd, sockfd[2], status; pid_t childpid; char c, argsockfd[10], argmode[10]; Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd); //child process if ((childpid = Fork()) == 0) { Close(sockfd[0]); snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]); /* what is in sockfd[1] */ snprintf(argmode, sizeof(argmode), "%d", mode); execl("./openfile", "openfile", argsockfd, pathname, argmode, (char *)NULL); err_sys("execl error"); } //parent process Close(sockfd[1]); Waitpid(childpid, &status, 0); if (WIFEXITED(status) == 0) err_quit("child did not terminate"); if ((status = WEXITSTATUS(status)) == 0) read_fd(sockfd[0], &c, 1, &fd); else { errno = status; fd = -1; } Close(sockfd[0]); return (fd); }
int main(int argc, char **argv) { int fd1, fd2, *ptr1, *ptr2; pid_t childpid; struct stat stat; if (argc != 2) err_quit("Usage: test2 <name>"); Shm_unlink(Px_ipc_name(argv[1])); fd1 = Shm_open(Px_ipc_name(argv[1]), O_RDWR | O_CREAT | O_EXCL, FILE_MODE); Ftruncate(fd1, sizeof(int)); fd2 = Open("./shm", O_RDONLY); Fstat(fd2, &stat); if ((childpid = Fork()) == 0) { ptr2 = Mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd2, 0); ptr1 = Mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); printf("child: shm ptr = %p, motd ptr = %p\n", ptr1, ptr2); sleep(5); printf("shared memory integer = %d\n", *ptr1); exit(0); } //parent: map in reverse order from child ptr1 = Mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); ptr2 = Mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd2, 0); *ptr1 = 777; Waitpid(childpid, NULL, 0); exit(0); }
int main() { unsigned int pid; int val; pid = ForkExec("run2"); if (pid < 0) { PutString("Error while Fork\n"); return -1; } Waitpid(pid, &val); PutString("Child exit code was "); PutInt(val); PutChar('\n'); return 0; }
int main(int argc, char **argv) { int i, nprocs; pid_t childpid[MAXNPROC]; if (argc != 3) err_quit("usage: incr_rwlock5 <#loops> <#processes>"); nloop = atoi(argv[1]); nprocs = min(atoi(argv[2]), MAXNPROC); /* 4get shared memory for parent and children */ shared = My_shm(sizeof(struct shared)); /* 4initialize the read-write lock and obtain write lock */ Rwlock_init(&shared->rwlock, USYNC_PROCESS, NULL); Rw_wrlock(&shared->rwlock); /* 4create all the children */ for (i = 0; i < nprocs; i++) { if ( (childpid[i] = Fork()) == 0) { incr(NULL); exit(0); } } /* 4parent: start the timer and release the write lock */ Start_time(); Rw_unlock(&shared->rwlock); /* 4wait for all the children */ for (i = 0; i < nprocs; i++) { Waitpid(childpid[i], NULL, 0); } printf("microseconds: %.0f usec\n", Stop_time()); if (shared->counter != nloop * nprocs) printf("error: counter = %ld\n", shared->counter); exit(0); }
int main(int argc, char **argv) { int i, nprocs; pid_t childpid[MAXNPROC]; if (argc != 3) err_quit("usage: incr_pxsem9 <#loops> <#processes>"); nloop = atoi(argv[1]); nprocs = min(atoi(argv[2]), MAXNPROC); /* 4get shared memory for parent and children */ shared = My_shm(sizeof(struct shared)); /* 4initialize memory-based semaphore to 0 */ Sem_init(&mutex, 1, 0); /* 4create all the children */ for (i = 0; i < nprocs; i++) { if ( (childpid[i] = Fork()) == 0) { incr(NULL); exit(0); } } /* 4parent: start the timer and release the semaphore */ Start_time(); Sem_post(&mutex); /* 4wait for all the children */ for (i = 0; i < nprocs; i++) { Waitpid(childpid[i], NULL, 0); } printf("microseconds: %.0f usec\n", Stop_time()); if (shared->counter != nloop * nprocs) printf("error: counter = %ld\n", shared->counter); exit(0); }
int main(int argc, char **argv) { int rc; pid_t childpid; mymqd_t mqd; unsigned int prio; struct sigevent sigev; struct mymq_attr attr, info; if (argc != 2) err_quit("usage: testmymq <pathname>"); /***************************************************************/ /* test mq_unlink() error return */ mymq_unlink(argv[1]); if ( ( rc = mymq_unlink(argv[1])) == 0 || errno != ENOENT) err_sys("mq_unlink returned %d", rc); /***************************************************************/ /* create a queue with default attributes */ mqd = Mymq_open(argv[1], O_CREAT | O_EXCL | O_RDWR, FILE_MODE, NULL); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 128 || info.mq_msgsize != 1024 || info.mq_flags != 0 || info.mq_curmsgs != 0) err_msg("message queue defaults:\n" "maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); Mymq_close(mqd); /***************************************************************/ /* check O_EXCL */ mqd = mymq_open(argv[1], O_CREAT | O_EXCL | O_RDWR, FILE_MODE, NULL); if (mqd != (mqd_t) -1 || errno != EEXIST) err_sys("mq_open returned %d", rc); Mymq_unlink(argv[1]); /***************************************************************/ /* create with attributes */ attr.mq_maxmsg = 4; attr.mq_msgsize = 7; mqd = Mymq_open(argv[1], O_CREAT | O_EXCL | O_RDWR, FILE_MODE, &attr); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != 0 || info.mq_curmsgs != 0) err_quit("1: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); /***************************************************************/ /* send/receive 1 message */ Mymq_send(mqd, msg1, 1, 1); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /* send/receive 1 0-byte message */ Mymq_send(mqd, msg0, 0, 0); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 0) err_quit("mq_receive returned %d, expected 0", rc); if (prio != 0) err_quit("mq_receive returned prio %d, expected 0", prio); /* send 2 messages/receive in reverse order */ Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg2, 2, 2); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /* send 3 messages/receive in reverse order */ Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg2, 2, 2); Mymq_send(mqd, msg3, 3, 3); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /* send 4 messages/receive in reverse order */ Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg2, 2, 2); Mymq_send(mqd, msg3, 3, 3); Mymq_send(mqd, msg4, 4, 4); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /***************************************************************/ /* send/receive 1 message */ Mymq_send(mqd, msg4, 4, 4); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); /* send 2 messages/receive in order */ Mymq_send(mqd, msg4, 4, 4); Mymq_send(mqd, msg3, 3, 3); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); /* send 3 messages/receive in order */ Mymq_send(mqd, msg4, 4, 4); Mymq_send(mqd, msg3, 3, 3); Mymq_send(mqd, msg2, 2, 2); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); /* send 4 messages/receive in order */ /* first check EMSGSIZE */ if ( (rc = mymq_send(mqd, msg4, 8, 4)) == 0 || errno != EMSGSIZE) err_sys("mq_send returned %d, expected EMSGSIZE", rc); Mymq_send(mqd, msg4, 4, 4); Mymq_send(mqd, msg3, 3, 3); Mymq_send(mqd, msg2, 2, 2); Mymq_send(mqd, msg1, 1, 1); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); /* first check EMSGSIZE */ if ( (rc = mymq_receive(mqd, msg, 6, &prio)) == 0 || errno != EMSGSIZE) err_sys("mq_receive returned %d, expected EMSGSIZE", rc); if ( (rc = Mymq_receive(mqd, msg, BUFFLEN, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /* fill queue then close it */ Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg2, 2, 2); Mymq_send(mqd, msg4, 4, 4); Mymq_send(mqd, msg3, 3, 3); Mymq_close(mqd); /* open existing queue nonblocking and read */ mqd = Mymq_open(argv[1], O_RDWR | O_NONBLOCK); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != O_NONBLOCK || info.mq_curmsgs != 4) err_quit("2: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /* check nonblockiing receive */ if ( (rc = mymq_receive(mqd, msg, info.mq_msgsize, &prio)) == 0 || errno != EAGAIN) err_sys("mq_receive returned %d, expected EAGAIN", rc); /* fill queue then close it */ Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg4, 4, 4); Mymq_send(mqd, msg2, 2, 2); Mymq_send(mqd, msg3, 3, 3); /* first check nonblocking send */ if ( (rc = mymq_send(mqd, msg5, 5, 5)) == 0 || errno != EAGAIN) err_sys("mq_send returned %d, expected EAGAIN", rc); Mymq_close(mqd); /* open existing queue and read */ mqd = Mymq_open(argv[1], O_RDWR); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 4) err_quit("mq_receive returned %d, expected 4", rc); if (prio != 4) err_quit("mq_receive returned prio %d, expected 4", prio); /* now set nonblocking with mq_setattr */ attr.mq_flags = O_NONBLOCK; Mymq_setattr(mqd, &attr, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != 0 || info.mq_curmsgs != 3) err_quit("3: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != O_NONBLOCK || info.mq_curmsgs != 3) err_quit("4: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); /* check nonblocking receive */ if ( (rc = mymq_receive(mqd, msg, info.mq_msgsize, &prio)) == 0 || errno != EAGAIN) err_sys("mq_receive returned %d, expected EAGAIN", rc); /* now clear nonblocking with mq_setattr */ attr.mq_flags = 0; Mymq_setattr(mqd, &attr, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != O_NONBLOCK || info.mq_curmsgs != 0) err_quit("5: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != 0 || info.mq_curmsgs != 0) err_quit("6: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); #ifdef notdef /* queue is empty; check that mymq_receive is interruptable */ Signal(SIGALRM, sig_alrm); blocked = 1; alarm(4); if ( (rc = mymq_receive(mqd, msg, info.mq_msgsize, &prio)) == 0 || errno != EINTR) err_sys("mq_receive returned %d, expected EINTR", rc); alarm(0); printf("mymq_receive interrupted, as expected\n"); /* fill queue */ Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg2, 2, 2); Mymq_send(mqd, msg3, 3, 3); Mymq_send(mqd, msg4, 4, 4); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != 0 || info.mq_curmsgs != 4) err_quit("7: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); /* queue is full; check that mymq_send is interruptable */ Signal(SIGALRM, sig_alrm); blocked = 1; alarm(4); printf("about to call mymq_send\n"); if ( (rc = mymq_send(mqd, msg5, 5, 5)) == 0 || errno != EINTR) err_sys("mq_send returned %d, expected EINTR", rc); alarm(0); printf("mymq_send interrupted, as expected\n"); #endif /* queue is empty, register for notification */ sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = SIGUSR1; Signal(SIGUSR1, sig_usr1); Mymq_notify(mqd, &sigev); /* verify we cannot register twice */ if ( (rc = mymq_notify(mqd, &sigev)) == 0 || errno != EBUSY) err_sys("mq_notify returned %d, expected EBUSY", rc); /* now unregister, then reregister */ Mymq_notify(mqd, NULL); Mymq_notify(mqd, &sigev); /* verify we cannot register twice */ if ( (rc = mymq_notify(mqd, &sigev)) == 0 || errno != EBUSY) err_sys("mq_notify returned %d, expected EBUSY", rc); /* make certain child cannot register if we are registered */ if ( (childpid = Fork()) == 0) { if ( (rc = mymq_notify(mqd, &sigev)) == 0 || errno != EBUSY) err_sys("mq_notify returned %d, expected EBUSY", rc); exit(0); } Waitpid(childpid, NULL, 0); /* send a message and verify SIGUSR1 is delivered */ sigusr1 = 0; Mymq_send(mqd, msg5, 5, 5); sleep(1); if (sigusr1 != 1) err_quit("sigusr1 = %d, expected 1", sigusr1); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 5) err_quit("mq_receive returned %d, expected 5", rc); if (prio != 5) err_quit("mq_receive returned prio %d, expected 5", prio); /* send another and make certain another signal is not sent */ Mymq_send(mqd, msg2, 2, 2); sleep(1); if (sigusr1 != 1) err_quit("sigusr1 = %d, expected 1", sigusr1); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 2) err_quit("mq_receive returned %d, expected 2", rc); if (prio != 2) err_quit("mq_receive returned prio %d, expected 2", prio); /* reregister */ Mymq_notify(mqd, &sigev); if ( (childpid = Fork()) == 0) { /* child calls mq_receive, which prevents notification */ if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 6) err_quit("mq_receive returned %d, expected 6", rc); if (prio != 6) err_quit("mq_receive returned prio %d, expected 6", prio); exit(0); } sleep(2); /* let child block in mq_receive() */ Mymq_send(mqd, msg6, 6, 6); Waitpid(childpid, NULL, 0); if (sigusr1 != 1) err_quit("sigusr1 = %d, expected 1", sigusr1); /* make certain parent can send messages to child, and vice versa */ if ( (childpid = Fork()) == 0) { sleep(2); /* let parent send two messages */ if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); exit(0); } Mymq_send(mqd, msg1, 1, 1); Mymq_send(mqd, msg3, 3, 3); Waitpid(childpid, NULL, 0); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != 0 || info.mq_curmsgs != 0) err_quit("8: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); if ( (childpid = Fork()) == 0) { Mymq_send(mqd, msg3, 3, 3); Mymq_send(mqd, msg5, 5, 5); Mymq_send(mqd, msg1, 1, 1); exit(0); } sleep(2); /* let child send 3 messages */ if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 5) err_quit("mq_receive returned %d, expected 5", rc); if (prio != 5) err_quit("mq_receive returned prio %d, expected 5", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 3) err_quit("mq_receive returned %d, expected 3", rc); if (prio != 3) err_quit("mq_receive returned prio %d, expected 3", prio); if ( (rc = Mymq_receive(mqd, msg, info.mq_msgsize, &prio)) != 1) err_quit("mq_receive returned %d, expected 1", rc); if (prio != 1) err_quit("mq_receive returned prio %d, expected 1", prio); Waitpid(childpid, NULL, 0); Mymq_getattr(mqd, &info); if (info.mq_maxmsg != 4 || info.mq_msgsize != 7 || info.mq_flags != 0 || info.mq_curmsgs != 0) err_quit("9: maxmsg = %ld, msgsize = %ld, flags = %ld, curmsgs = %ld\n", info.mq_maxmsg, info.mq_msgsize, info.mq_flags, info.mq_curmsgs); printf("done\n"); exit(0); }
static int sigChildHandler(int sig) { int status; Waitpid(-1, &status, 0); printf("handler has successful reap a child\n"); }
/* the current socat/xio implementation knows two kinds of children: exec/system addresses perform a fork: their children are registered and their death's influence the parents' flow; listen-socket with fork children: these children are "anonymous" and their death does not affect the parent process (now; maybe we have a child process counter later) */ void childdied(int signum #if HAVE_SIGACTION , siginfo_t *siginfo, void *context #endif /* HAVE_SIGACTION */ ) { pid_t pid; int _errno; int status = 0; bool wassig = false; int i; struct _xiosigchld_child *entry; _errno = errno; /* save current value; e.g., select() on Cygwin seems to set it to EINTR _before_ handling the signal, and then passes the value left by the signal handler to the caller of select(), accept() etc. */ /* is not thread/signal save, but confused messages in rare cases are better than no messages at all */ Info1("childdied(signum=%d)", signum); do { pid = Waitpid(-1, &status, WNOHANG); if (pid == 0) { Msg(wassig?E_INFO:E_WARN, "waitpid(-1, {}, WNOHANG): no child has exited"); Info("childdied() finished"); errno = _errno; return; } else if (pid < 0 && errno == ECHILD) { Msg1(wassig?E_INFO:E_WARN, "waitpid(-1, {}, WNOHANG): %s", strerror(errno)); Info("childdied() finished"); errno = _errno; return; } wassig = true; if (pid < 0) { Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno)); Info("childdied() finished"); errno = _errno; return; } #if 0 /*! indent */ /* check if it was a registered child process */ i = 0; while (i < XIO_MAXSOCK) { if (xio_checkchild(sock[i], i, pid)) break; ++i; } if (i == XIO_MAXSOCK) { Info2("childdied(%d): cannot identify child %d", signum, pid); if (diedunknown1 == 0) { diedunknown1 = pid; Debug("saving pid in diedunknown1"); } else if (diedunknown2 == 0) { diedunknown2 = pid; Debug("saving pid in diedunknown2"); } else if (diedunknown3 == 0) { diedunknown3 = pid; Debug("saving pid in diedunknown3"); } else { diedunknown4 = pid; Debug("saving pid in diedunknown4"); } } #else entry = _xiosigchld_find(pid); if (entry == NULL) { Info("dead child "F_pid" died unknown"); } else { (*entry->sigaction)(signum, siginfo, entry->context); xiosigchld_unregister(pid); } #endif if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { Info2("waitpid(): child %d exited with status %d", pid, WEXITSTATUS(status)); } else { Warn2("waitpid(): child %d exited with status %d", pid, WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { Info2("waitpid(): child %d exited on signal %d", pid, WTERMSIG(status)); } else if (WIFSTOPPED(status)) { Info2("waitpid(): child %d stopped on signal %d", pid, WSTOPSIG(status)); } else { Warn1("waitpid(): cannot determine status of child %d", pid); } #if !HAVE_SIGACTION /* we might need to re-register our handler */ if (Signal(SIGCHLD, childdied) == SIG_ERR) { Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno)); } #endif /* !HAVE_SIGACTION */ } while (1); Info("childdied() finished"); errno = _errno; }
void sigchld_handler(int s) { int olderrno = errno; pid = Waitpid(-1, NULL, 0); errno = olderrno; }
int xioshutdown(xiofile_t *sock, int how) { int result = 0; if (sock->tag == XIO_TAG_INVALID) { Error("xioshutdown(): invalid file descriptor"); errno = EINVAL; return -1; } if (sock->tag == XIO_TAG_DUAL) { if ((how+1)&1) { result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0); } if ((how+1)&2) { result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1); } return result; } switch (sock->stream.howtoshut) { char writenull; case XIOSHUT_NONE: return 0; case XIOSHUT_CLOSE: if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } return 0; case XIOSHUT_DOWN: if ((result = Shutdown(sock->stream.fd, how)) < 0) { Info3("shutdown(%d, %d): %s", sock->stream.fd, how, strerror(errno)); } return 0; #if _WITH_SOCKET case XIOSHUT_NULL: /* send an empty packet; only useful on datagram sockets? */ xiowrite(sock, &writenull, 0); return 0; #endif /* _WITH_SOCKET */ default: ; } if (false) { ; #if WITH_OPENSSL } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) { sycSSL_shutdown (sock->stream.para.openssl.ssl); /*! what about half/full close? */ #endif /* WITH_OPENSSL */ } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) { if ((how+1)&1) { if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } } if ((how+1)&2) { if (Close(sock->stream.para.bipipe.fdout) < 0) { Info2("close(%d): %s", sock->stream.para.bipipe.fdout, strerror(errno)); } } } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) { if ((how+1)&1) { if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } } if ((how+1)&2) { if (Close(sock->stream.para.exec.fdout) < 0) { Info2("close(%d): %s", sock->stream.para.exec.fdout, strerror(errno)); } } #if _WITH_SOCKET } else if (sock->stream.howtoend == END_SHUTDOWN) { if ((result = Shutdown(sock->stream.fd, how)) < 0) { Info3("shutdown(%d, %d): %s", sock->stream.fd, how, strerror(errno)); } } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) { if ((result = Shutdown(sock->stream.fd, how)) < 0) { Info3("shutdown(%d, %d): %s", sock->stream.fd, how, strerror(errno)); } if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) { /* the child process might want to flush some data before terminating */ int status = 0; /* we wait for the child process to die, but to prevent timeout we raise an alarm after some time. NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?), therefore we have to do the kill in the signal handler */ { struct sigaction act; sigfillset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = signal_kill_pid; Sigaction(SIGALRM, &act, NULL); } socat_kill_pid = sock->stream.para.exec.pid; #if HAVE_SETITIMER /*! with next feature release, we get usec resolution and an option */ #else Alarm(1 /*! sock->stream.para.exec.waitdie */); #endif /* !HAVE_SETITIMER */ if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) { Warn3("waitpid("F_pid", %p, 0): %s", sock->stream.para.exec.pid, &status, strerror(errno)); } Alarm(0); } } else if ((sock->stream.dtype & XIODATA_MASK) == (XIODATA_RECVFROM & XIODATA_MASK)) { if (how >= 1) { if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } sock->stream.eof = 2; sock->stream.fd = -1; } #endif /* _WITH_SOCKET */ #if 0 } else { Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype); return -1; #endif } #if 0 else if (sock->stream.howtoend == END_CLOSE &&
/*$sigChldHandler to protect zimble process */ static void sigChldHandler(int signo) { Waitpid(-1,NULL,WNOHANG); return; }