Ejemplo n.º 1
0
/*
 * 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;
			}
	}
}
Ejemplo n.º 2
0
/*
 * -- 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;
}