- changed status to on hold
Event::add() on event signal notice in forked child...
Description:
i initialise EventBase on master process. $this->base = new EventBase();
i add signal event like that on master process:
$event = new Event($this->base, SIGTERM, Event::SIGNAL | Event::PERSIST , array($this, "EventTERM")); $event->add();
i initialise another eventbase
$this->listenerbase = new EventBase();
i initialise EventListener on socket in master process on this base. $listener = new EventListener($this->listenerbase, [$this, 'ev_accept'], $this, EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, -1, "localhost:80"))
i fork and in the child i reinit the EventListener EventBase and try to unset the first EventBase who i've attached the signal SIGTERM and add new signal event SIGTERM on the listenerbase then dispatch on them.
but notice a the message: Notice: Event::add(): Added a signal to event base 0x1d43f30 with signals already added to event_base 0x1d3aec0. Only one can have signals at a time with the epoll backend.
when searching on the net about this message i found similar use of signal handler on libevent list: http://archives.seul.org/libevent/users/Mar-2011/msg00008.html http://sourceforge.net/p/levent/bugs/224/
the probleme are in fact that cannot free completly the master process eventbase on the child...
i've tryed to reinit, and delete/free all event, and unset the eventbase object... and force collecting garbage...
and the notice while continue to appeare...
Expected result:
to abel to completely free the eventbase to avoid this notice message. in the object version of this extension the freeing of the eventbase rely on the destruction of the object... adding free method on the eventbase to explicitly free the object while resolve the probleme i think...
Comments (5)
-
repo owner -
i've added method free on event_base object to call event_base_free. and using it after fork resolve the problem has espected in libevent bugtraker.
-
diff --git a/classes/base.c b/classes/base.c index 8f3520a..28fa00c 100644 --- a/classes/base.c +++ b/classes/base.c @@ -318,6 +318,23 @@ PHP_METHOD(EventBase, updateCacheTime) /* }}} */ #endif +/* {{{ proto void EventBase::free(void); */ +PHP_METHOD(EventBase, free) +{ + zval *zbase = getThis(); + php_event_base_t *b; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + PHP_EVENT_FETCH_BASE(b, zbase); + + event_base_free(b->base); + b->base=NULL; +} +/* }}} */ + /* {{{ proto bool EventBase::reInit(void); * Re-initialize event base. Should be called after a fork. * XXX pthread_atfork() in MINIT */ diff --git a/src/fe.c b/src/fe.c index 11c3794..98c6da5 100644 --- a/src/fe.c +++ b/src/fe.c @@ -527,6 +527,7 @@ const zend_function_entry php_event_base_ce_functions[] = {/* {{{ */ PHP_ME(EventBase, gotExit, arginfo_event__void, ZEND_ACC_PUBLIC) PHP_ME(EventBase, getTimeOfDayCached, arginfo_event__void, ZEND_ACC_PUBLIC) PHP_ME(EventBase, reInit, arginfo_event__void, ZEND_ACC_PUBLIC) + PHP_ME(EventBase, free, arginfo_event__void, ZEND_ACC_PUBLIC) #if LIBEVENT_VERSION_NUMBER >= 0x02010100 PHP_ME(EventBase, updateCacheTime, arginfo_event__void, ZEND_ACC_PUBLIC) #endif diff --git a/src/fe.h b/src/fe.h index 0f89336..5d93049 100644 --- a/src/fe.h +++ b/src/fe.h @@ -50,6 +50,7 @@ PHP_METHOD(EventBase, getTimeOfDayCached); PHP_METHOD(EventBase, updateCacheTime); #endif PHP_METHOD(EventBase, reInit); +PHP_METHOD(EventBase, free); #if LIBEVENT_VERSION_NUMBER >= 0x02010200 PHP_METHOD(EventBase, resume); #endif
-
her the snipet of code...
// in master process create two event base ($base), one for managing child exit signal and timer to supervise information about child // the second event base ($listenbase) are attached with eventlistener on socket that while be listened on child // when fork to create worker: function create_worker() { $pid = pcntl_fork(); if ( $pid === -1 ) { printf("Fork Failure\n"); return false; } if ( $pid === 0 ) { $worker_pid = posix_getpid(); printf("Worker with pid:%s started at <%s>\n",$worker_pid,gmdate('r')); // The child process ignores SIGINT (small race here) pcntl_sigprocmask( SIG_BLOCK, array(SIGINT) ); // purge global event base // and lets go of the parent's libevent base if (!$base->reInit()) { die("Error EventBase reInit!\n"); } // and breaks out of the service event loop if (!$base->stop()) { die("Error EventBase reInit!\n"); } // in process master a store refence of all added event // and in child i dismantles the whole event structure foreach ( $this->events as $i => &$event ) { $event->free(); unset($events); } // try to free eventbase $base->free(); unset($base); // worker running there ... $listenbase->reInit() // add signal on child handling to handle TERM signal form master process when it die // without the event_base_free when add signal on signal already added on master process on the other eventbase they send the warning ... // Notice: Event::add(): Added a signal to event base 0x1d43f30 with signals already added to event_base 0x1d3aec0. Only one can have signals at a time with the epoll backend. // and then dispatch to listen on eventlistener initialised on socket in master process $listenbase->dispatch(); } }
-
repo owner - changed status to closed
I've added the method to
master
. Please check if it works.Thanks!
- Log in to comment
Just to avoid misunderstandings please post a code snippet demonstrating the issue.
Also I'd recommend to have a look at the code of the phpDaemon project: https://github.com/kakserpom/phpdaemon . Once, the author of that project had similar issues.