[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] Forked processes and signals



Nick Mathewson wrote:

Hello Nick,


In theory, this approach is supposed to work: what problems are you
seeing in the master process?  (event_base_free sounds like what you
want if you do not want to use the original event_base in the
subprocess. )

If I understand right, you start with a master process with an
event_base with some signal events pending in it.  Then you fork, and
create new event_bases in the subprocesses, and you want to add
signals to them instead.  Given that (IIUC) you do not plan to use the
original event_base in the subprocesses, so it should be okay to free
it.
That's exactly what I want to do.


Of course, if this isn't working for you, then something has gone
wrong.  What failure mode have you found when you try to do this?

I've attached an example program which shows the problem.
With event_base_free(master_base) called in the subprocesses,
the master process cannot receive anymore the SIGHUP signal
(whereas it's fine for the subprocesses).

If you remove event_base_free(master_base), all the processes
handle the SIGHUP signal correctly, but there are warning
messages. In fact, with evsig_set_base() in the subprocesses,
the warning messages are not displayed, and everything seems
to work fine (all processes handle the signal correctly).
I guess this behavior is related to the epoll mechanism.

Thanks for your help,

Christophe

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>

#include <event2/event-config.h>
#include <event2/event.h>

static struct event_base *master_base;

static void subproc_sighup_handler(evutil_socket_t fd,short ev_type,
                                   void *arg)
{
   long id = (long)arg;
   printf("Subprocess %ld: SIGHUP received!\n",id);
}

static void subproc_work(int id)
{
   struct event_base *base;
   struct event *ev_sighup;

   //event_base_free(master_base);

   printf("Subprocess %d: creating event base\n",id);
   base = event_base_new();
   assert(base != NULL);

   evsig_set_base(base);

   ev_sighup = evsignal_new(base,SIGHUP,subproc_sighup_handler,
                            (void *)(long)id);
   assert(ev_sighup != NULL);
   evsignal_add(ev_sighup,NULL);

   event_base_dispatch(base);
}

static void subproc_create(int id)
{
   pid_t pid;

   switch((pid = fork())) {
      case -1:
         abort();
      case 0:
         printf("Subprocess %d created\n",id);
         subproc_work(id);
         break;
      default:
         printf("Master: subprocess %d created with PID=%ld\n",
                id,(long)pid);
   }
}

static void master_sighup_handler(evutil_socket_t fd,short ev_type,void *arg)
{
   printf("Master: SIGHUP received!\n");
}

int main(void)
{
   struct event *ev_sighup;

   printf("Master: PID = %ld\n",(long)getpid());

   printf("Master: creating event base and events...\n");
   master_base = event_base_new();
   assert(master_base != NULL);

   ev_sighup = evsignal_new(master_base,SIGHUP,master_sighup_handler,NULL);
   assert(ev_sighup != NULL);
   evsignal_add(ev_sighup,NULL);

   printf("Master: creating sub-processes:\n");
   subproc_create(0);
   subproc_create(1);

   printf("Master: running event loop...\n");
   event_base_dispatch(master_base);
   return(0);
}