34
34
#define fpm_event_set_timeout (ev , now ) timeradd(&(now), &(ev)->frequency, &(ev)->timeout);
35
35
36
36
static void fpm_event_cleanup (int which , void * arg );
37
+ static void fpm_postponed_children_bury (struct fpm_event_s * ev , short which , void * arg );
37
38
static void fpm_got_signal (struct fpm_event_s * ev , short which , void * arg );
38
39
static struct fpm_event_s * fpm_event_queue_isset (struct fpm_event_queue_s * queue , struct fpm_event_s * ev );
39
40
static int fpm_event_queue_add (struct fpm_event_queue_s * * queue , struct fpm_event_s * ev );
@@ -43,6 +44,7 @@ static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue);
43
44
static struct fpm_event_module_s * module ;
44
45
static struct fpm_event_queue_s * fpm_event_queue_timer = NULL ;
45
46
static struct fpm_event_queue_s * fpm_event_queue_fd = NULL ;
47
+ static struct fpm_event_s children_bury_timer ;
46
48
47
49
static void fpm_event_cleanup (int which , void * arg ) /* {{{ */
48
50
{
@@ -51,6 +53,12 @@ static void fpm_event_cleanup(int which, void *arg) /* {{{ */
51
53
}
52
54
/* }}} */
53
55
56
+ static void fpm_postponed_children_bury (struct fpm_event_s * ev , short which , void * arg ) /* {{{ */
57
+ {
58
+ fpm_children_bury ();
59
+ }
60
+ /* }}} */
61
+
54
62
static void fpm_got_signal (struct fpm_event_s * ev , short which , void * arg ) /* {{{ */
55
63
{
56
64
char c ;
@@ -72,7 +80,12 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{
72
80
switch (c ) {
73
81
case 'C' : /* SIGCHLD */
74
82
zlog (ZLOG_DEBUG , "received SIGCHLD" );
75
- fpm_children_bury ();
83
+ /* epoll_wait() may report signal fd before read events for a finished child
84
+ * in the same bunch of events. Prevent immediate free of the child structure
85
+ * and so the fpm_event_s instance. Otherwise use after free happens during
86
+ * attemp to process following read event. */
87
+ fpm_event_set_timer (& children_bury_timer , 0 , & fpm_postponed_children_bury , NULL );
88
+ fpm_event_add (& children_bury_timer , 0 );
76
89
break ;
77
90
case 'I' : /* SIGINT */
78
91
zlog (ZLOG_DEBUG , "received SIGINT" );
0 commit comments