/* * ipc_recv_path() * * Get the next archive file to process from the queue. */ int ipc_recv_path(char *buf) { queue_elem *elem; int rc; struct { long mtype; char mtext[MSGMAX]; } msg; while (true) { if (ipc_poll(false) < 0) { ipc_finish(true); return -1; } /* * If something requested an immediate shutdown, don't report any * more logfiles back. */ if (shutdown_immed_requested) { ipc_finish(true); return 0; } /* * If a smart shutdown was requested, try to close the queue * but don't force it. */ if (shutdown_smart_requested) { if ((rc = ipc_finish(false)) == 0) { return 0; } if (rc < 0) { ipc_finish(true); return -1; } } /* * If we have something in the queue, return that. */ if (archive_queue_head != NULL) { elem = archive_queue_head; archive_queue_head = archive_queue_head->next; if (archive_queue_head == NULL) archive_queue_tail = NULL; strcpy(buf, elem->archive_path); free(elem->archive_path); free(elem); return 1; } /* * Receive one single message blocking for it. */ rc = msgrcv(msgid, &msg, sizeof(msg), 0, IPC_NOWAIT); if (rc < 0) { if (errno == ENOMSG) return -2; if (errno == EINTR) continue; fprintf(stderr, "msgrcv() failed in ipc_recv_path(): %s\n", strerror(errno)); ipc_finish(true); return -1; } if (msg.mtype == 2) shutdown_smart_requested = true; else if (msg.mtype == 3) shutdown_immed_requested = true; else if (msg.mtype == 4) wait_for_resume = false; else if (msg.mtype == 5) logfile_switch_requested = true; else if (ipc_add_path(msg.mtext) < 0) { ipc_finish(true); return -1; } } }
/* * -- start_child * * fork a child with the given function and process name. * If 'procname' is NULL then don't fork, as this is the supervisor. * The last argument is an optional fd to be passed to the program. */ pid_t start_child(ipc_peer_full_t * child, mainloop_fn mainloop, memmap_t * shmemmap, FILE *client_stream, como_node_t * node) { pid_t pid; int i, p[2]; char c; ipc_peer_t * who = (ipc_peer_t *) child; /* find a slot for the child */ for (i = 0; i < MAX_CHILDREN; i++) { if (s_child_info[i].who == NULL) break; } if (i == MAX_CHILDREN) { warn("cannot create child, no more slots\n"); return -1; } /* * set a pipe which will be used to tell child it may start. * this avoids a race condition when the child exists before * SU has registered it. */ pipe(p); /* ok, fork a regular process and return pid to the caller. */ debug("start_child -- forking\n"); pid = fork(); if (pid < 0) { /* fork() fails */ warn("fork() failed: %s\n", strerror(errno)); close(p[0]); close(p[1]); return -1; } else if (pid == 0) { /* child */ int supervisor_fd; debug("child: waiting for start signal\n"); close(p[1]); /* not going to write to the pipe */ como_read(p[0], &c, 1); /* wait for start signal */ close(p[0]); /* done with the pipe */ debug("child: starting\n"); #ifdef ENABLE_PROFILING enable_profiling(); #endif signal(SIGHUP, SIG_IGN); /* ignore SIGHUP */ /* initialize the s_child_info array */ bzero(s_child_info, sizeof(s_child_info)); /* XXX TODO: close unneeded sockets */ // fclose(stdout); // XXX // fclose(stderr); // XXX /* ipc_finish will close all FDs. We must retain a copy of client_fd */ ipc_finish(FALSE); ipc_init(child, NULL, NULL); /* connect to SUPERVISOR */ supervisor_fd = ipc_connect(COMO_SU); assert(supervisor_fd != -1); setproctitle("%s", ipc_peer_get_name(who)); notice("starting process %s pid %d\n", ipc_peer_get_name(who), getpid()); mainloop((ipc_peer_t *) COMO_SU, shmemmap, client_stream, node); exit(0); } /* parent */ close(p[0]); /* will not read from pipe */ s_child_info[i].who = child; /* register the child info */ s_child_info[i].pid = pid; s_children++; como_write(p[1], &c, 1); /* child process can start now */ close(p[1]); /* done with the pipe */ return pid; }