Revive Zend Signals handler (and fixed bug #61083)

This commit is contained in:
Xinchen Hui 2015-03-05 18:11:22 +08:00
parent c498cc7407
commit fd5a756ad4
5 changed files with 44 additions and 52 deletions

View file

@ -715,6 +715,10 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
tsrm_set_new_thread_end_handler(zend_new_thread_end_handler); tsrm_set_new_thread_end_handler(zend_new_thread_end_handler);
#endif #endif
#ifdef ZEND_SIGNALS
zend_signal_startup();
#endif
return SUCCESS; return SUCCESS;
} }
/* }}} */ /* }}} */
@ -769,9 +773,6 @@ void zend_post_startup(void) /* {{{ */
void zend_shutdown(void) /* {{{ */ void zend_shutdown(void) /* {{{ */
{ {
#ifdef ZEND_SIGNALS
zend_signal_shutdown();
#endif
zend_destroy_rsrc_list(&EG(persistent_list)); zend_destroy_rsrc_list(&EG(persistent_list));
if (EG(active)) if (EG(active))
{ {

View file

@ -75,12 +75,12 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
int errno_save = errno; int errno_save = errno;
zend_signal_queue_t *queue, *qtmp; zend_signal_queue_t *queue, *qtmp;
if (SIGG(active)) { if (EXPECTED(SIGG(active))) {
if (SIGG(depth) == 0) { /* try to handle signal */ if (UNEXPECTED(SIGG(depth) == 0)) { /* try to handle signal */
if (SIGG(blocked) != -1) { /* inverse */ if (UNEXPECTED(SIGG(blocked))) {
SIGG(blocked) = -1; /* signal is not blocked */ SIGG(blocked) = 0;
} }
if (SIGG(running) == 0) { if (EXPECTED(SIGG(running) == 0)) {
SIGG(running) = 1; SIGG(running) = 1;
zend_signal_handler(signo, siginfo, context); zend_signal_handler(signo, siginfo, context);
@ -98,7 +98,7 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
SIGG(running) = 0; SIGG(running) = 0;
} }
} else { /* delay signal handling */ } else { /* delay signal handling */
SIGG(blocked) = 0; /* signal is blocked */ SIGG(blocked) = 1; /* signal is blocked */
if ((queue = SIGG(pavail))) { /* if none available it's simply forgotton */ if ((queue = SIGG(pavail))) { /* if none available it's simply forgotton */
SIGG(pavail) = queue->next; SIGG(pavail) = queue->next;
@ -135,7 +135,7 @@ ZEND_API void zend_signal_handler_unblock(void)
zend_signal_queue_t *queue; zend_signal_queue_t *queue;
zend_signal_t zend_signal; zend_signal_t zend_signal;
if (SIGG(active)) { if (EXPECTED(SIGG(active))) {
SIGNAL_BEGIN_CRITICAL(); /* procmask to protect handler_defer as if it were called by the kernel */ SIGNAL_BEGIN_CRITICAL(); /* procmask to protect handler_defer as if it were called by the kernel */
queue = SIGG(phead); queue = SIGG(phead);
SIGG(phead) = queue->next; SIGG(phead) = queue->next;
@ -282,7 +282,7 @@ void zend_signal_activate(void)
memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers)); memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers));
for (x=0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) { for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
zend_signal_register(zend_sigs[x], zend_signal_handler_defer); zend_signal_register(zend_sigs[x], zend_signal_handler_defer);
} }
@ -294,15 +294,15 @@ void zend_signal_activate(void)
* */ * */
void zend_signal_deactivate(void) void zend_signal_deactivate(void)
{ {
int x;
struct sigaction sa = {{0}};
if (SIGG(check)) { if (SIGG(check)) {
int x;
struct sigaction sa = {{0}};
if (SIGG(depth) != 0) { if (SIGG(depth) != 0) {
zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth)); zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
} }
/* did anyone steal our installed handler */ /* did anyone steal our installed handler */
for (x=0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) { for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
sigaction(zend_sigs[x], NULL, &sa); sigaction(zend_sigs[x], NULL, &sa);
if (sa.sa_sigaction != zend_signal_handler_defer) { if (sa.sa_sigaction != zend_signal_handler_defer) {
zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]); zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
@ -313,18 +313,17 @@ void zend_signal_deactivate(void)
SIGNAL_BEGIN_CRITICAL(); SIGNAL_BEGIN_CRITICAL();
SIGG(active) = 0; SIGG(active) = 0;
SIGG(running) = 0; SIGG(running) = 0;
SIGG(blocked) = -1; SIGG(blocked) = 0;
SIGG(depth) = 0; SIGG(depth) = 0;
SIGNAL_END_CRITICAL(); SIGNAL_END_CRITICAL();
} }
/* }}} */ /* }}} */
static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals) static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals) /* {{{ */
{ {
size_t x; size_t x;
memset(zend_signal_globals, 0, sizeof(*zend_signal_globals)); memset(zend_signal_globals, 0, sizeof(*zend_signal_globals));
zend_signal_globals->blocked = -1;
for (x = 0; x < sizeof(zend_signal_globals->pstorage) / sizeof(*zend_signal_globals->pstorage); ++x) { for (x = 0; x < sizeof(zend_signal_globals->pstorage) / sizeof(*zend_signal_globals->pstorage); ++x) {
zend_signal_queue_t *queue = &zend_signal_globals->pstorage[x]; zend_signal_queue_t *queue = &zend_signal_globals->pstorage[x];
@ -333,21 +332,35 @@ static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals)
zend_signal_globals->pavail = queue; zend_signal_globals->pavail = queue;
} }
} }
/* }}} */
static void zend_signal_globals_dtor(zend_signal_globals_t *zend_signal_globals) void zend_signal_init() /* {{{ */
{ {
zend_signal_globals->blocked = -1; int signo;
struct sigaction sa = {{0}};
/* Save previously registered signal handlers into orig_handlers */
memset(&global_orig_handlers, 0, sizeof(global_orig_handlers));
for (signo = 1; signo < NSIG; ++signo) {
if (sigaction(signo, NULL, &sa) == 0) {
global_orig_handlers[signo-1].flags = sa.sa_flags;
if (sa.sa_flags & SA_SIGINFO) {
global_orig_handlers[signo-1].handler = (void *) sa.sa_sigaction;
} else {
global_orig_handlers[signo-1].handler = (void *) sa.sa_handler;
}
}
}
} }
/* }}} */
/* {{{ zend_signal_startup /* {{{ zend_signal_startup
* alloc zend signal globals */ * alloc zend signal globals */
void zend_signal_startup() void zend_signal_startup()
{ {
int signo;
struct sigaction sa = {{0}};
#ifdef ZTS #ifdef ZTS
ts_allocate_id(&zend_signal_globals_id, sizeof(zend_signal_globals_t), (ts_allocate_ctor) zend_signal_globals_ctor, (ts_allocate_dtor) zend_signal_globals_dtor); ts_allocate_id(&zend_signal_globals_id, sizeof(zend_signal_globals_t), (ts_allocate_ctor) zend_signal_globals_ctor, NULL);
#else #else
zend_signal_globals_ctor(&zend_signal_globals); zend_signal_globals_ctor(&zend_signal_globals);
#endif #endif
@ -374,28 +387,7 @@ void zend_signal_startup()
sigdelset(&global_sigmask, SIGTRAP); sigdelset(&global_sigmask, SIGTRAP);
#endif #endif
/* Save previously registered signal handlers into orig_handlers */ zend_signal_init();
memset(&global_orig_handlers, 0, sizeof(global_orig_handlers));
for (signo = 1; signo < NSIG; ++signo) {
if (sigaction(signo, NULL, &sa) == 0) {
global_orig_handlers[signo-1].flags = sa.sa_flags;
if (sa.sa_flags & SA_SIGINFO) {
global_orig_handlers[signo-1].handler = (void *) sa.sa_sigaction;
} else {
global_orig_handlers[signo-1].handler = (void *) sa.sa_handler;
}
}
}
}
/* }}} */
/* {{{ zend_signal_shutdown
* called by zend_shutdown */
void zend_signal_shutdown(void)
{
#ifndef ZTS
zend_signal_globals_dtor(&zend_signal_globals);
#endif
} }
/* }}} */ /* }}} */

View file

@ -55,10 +55,9 @@ typedef struct _zend_signal_queue_t {
/* Signal Globals */ /* Signal Globals */
typedef struct _zend_signal_globals_t { typedef struct _zend_signal_globals_t {
int depth; int depth;
int blocked; /* 0==TRUE, -1==FALSE */ int blocked; /* 1==TRUE, 0==FALSE */
int running; /* in signal handler execution */ int running; /* in signal handler execution */
int active; /* internal signal handling is enabled */ int active; /* internal signal handling is enabled */
int initialized; /* memory initialized */
zend_bool check; /* check for replaced handlers on shutdown */ zend_bool check; /* check for replaced handlers on shutdown */
zend_signal_entry_t handlers[NSIG]; zend_signal_entry_t handlers[NSIG];
zend_signal_queue_t pstorage[ZEND_SIGNAL_QUEUE_SIZE], *phead, *ptail, *pavail; /* pending queue */ zend_signal_queue_t pstorage[ZEND_SIGNAL_QUEUE_SIZE], *phead, *ptail, *pavail; /* pending queue */
@ -70,12 +69,12 @@ BEGIN_EXTERN_C()
ZEND_API extern int zend_signal_globals_id; ZEND_API extern int zend_signal_globals_id;
END_EXTERN_C() END_EXTERN_C()
# define ZEND_SIGNAL_BLOCK_INTERRUPUTIONS() if (EXPECTED(zend_signal_globals_id)) { SIGG(depth)++; } # define ZEND_SIGNAL_BLOCK_INTERRUPUTIONS() if (EXPECTED(zend_signal_globals_id)) { SIGG(depth)++; }
# define ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() if (EXPECTED(zend_signal_globals_id) && UNEXPECTED((--SIGG(depth))==SIGG(blocked))) { zend_signal_handler_unblock(); } # define ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() if (EXPECTED(zend_signal_globals_id) && UNEXPECTED(((SIGG(depth)--) == SIGG(blocked)))) { zend_signal_handler_unblock(); }
#else /* ZTS */ #else /* ZTS */
# define SIGG(v) (zend_signal_globals.v) # define SIGG(v) (zend_signal_globals.v)
extern ZEND_API zend_signal_globals_t zend_signal_globals; extern ZEND_API zend_signal_globals_t zend_signal_globals;
# define ZEND_SIGNAL_BLOCK_INTERRUPUTIONS() SIGG(depth)++; # define ZEND_SIGNAL_BLOCK_INTERRUPUTIONS() SIGG(depth)++;
# define ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() if (UNEXPECTED((--SIGG(depth))==SIGG(blocked))) { zend_signal_handler_unblock(); } # define ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() if (((SIGG(depth)--) == SIGG(blocked))) { zend_signal_handler_unblock(); }
#endif /* not ZTS */ #endif /* not ZTS */
# define SIGNAL_BEGIN_CRITICAL() sigset_t oldmask; \ # define SIGNAL_BEGIN_CRITICAL() sigset_t oldmask; \
@ -87,6 +86,7 @@ ZEND_API void zend_signal_handler_unblock();
void zend_signal_activate(void); void zend_signal_activate(void);
void zend_signal_deactivate(void); void zend_signal_deactivate(void);
void zend_signal_startup(); void zend_signal_startup();
void zend_signal_init();
void zend_signal_shutdown(void); void zend_signal_shutdown(void);
ZEND_API int zend_signal(int signo, void (*handler)(int)); ZEND_API int zend_signal(int signo, void (*handler)(int));
ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact); ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact);

View file

@ -83,10 +83,6 @@ SAPI_API sapi_module_struct sapi_module;
SAPI_API void sapi_startup(sapi_module_struct *sf) SAPI_API void sapi_startup(sapi_module_struct *sf)
{ {
#ifdef ZEND_SIGNALS
zend_signal_startup();
#endif
sf->ini_entries = NULL; sf->ini_entries = NULL;
sapi_module = *sf; sapi_module = *sf;

View file

@ -717,6 +717,9 @@ void php_ap2_register_hook(apr_pool_t *p)
ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
#ifdef ZEND_SIGNALS
ap_hook_child_init(zend_signal_init, NULL, NULL, APR_HOOK_MIDDLE);
#endif
ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
} }