Add signal handling support

- resource uv_signal_init([resource $loop])
- void uv_signal_start(resource $sigHandle, callable $onSignal, int $signal)
- void uv_signal_stop($signalResource)

Example:

    <?php
    $sigHandle = uv_signal_init();
    $onSigint = function($sigHandle, $sigNum) {
        printf("Caught signal: %d\n", $sigNum);
        uv_signal_stop($sigHandle);
        uv_stop();
    };
    uv_signal_start($sigHandle, $onSigint, UV::SIGINT);
    uv_run();

New signal constants (these vary by OS):

    <?php
    $refl = new ReflectionClass('UV');
    print_r($refl->getConstants());
This commit is contained in:
Daniel Lowrey 2014-05-07 15:53:06 -04:00
parent 096eedc215
commit 1e32c24608
3 changed files with 208 additions and 2 deletions

142
php_uv.c Normal file → Executable file
View File

@ -65,6 +65,21 @@ zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0
TSRMLS_SET_CTX(uv->thread_ctx); \ TSRMLS_SET_CTX(uv->thread_ctx); \
uv->resource_id = PHP_UV_LIST_INSERT(uv, uv_resource_handle); \ uv->resource_id = PHP_UV_LIST_INSERT(uv, uv_resource_handle); \
#define PHP_UV_INIT_SIGNAL(uv, uv_type) \
uv = (php_uv_t *)emalloc(sizeof(php_uv_t)); \
if (!uv) { \
php_error_docref(NULL TSRMLS_CC, E_ERROR, "emalloc failed"); \
RETURN_FALSE; \
} \
if (uv_signal_init(loop, &uv->uv.signal)) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "uv_signal_init failed");\
RETURN_FALSE;\
} \
uv->type = uv_type; \
PHP_UV_INIT_ZVALS(uv) \
TSRMLS_SET_CTX(uv->thread_ctx); \
uv->resource_id = PHP_UV_LIST_INSERT(uv, uv_resource_handle); \
#define PHP_UV_INIT_CONNECT(req, uv) \ #define PHP_UV_INIT_CONNECT(req, uv) \
req = (uv_connect_t*)emalloc(sizeof(uv_connect_t)); \ req = (uv_connect_t*)emalloc(sizeof(uv_connect_t)); \
req->data = uv; req->data = uv;
@ -285,6 +300,8 @@ static void php_uv_timer_cb(uv_timer_t *handle, int status);
static void php_uv_idle_cb(uv_timer_t *handle, int status); static void php_uv_idle_cb(uv_timer_t *handle, int status);
static void php_uv_signal_cb(uv_signal_t *handle, int sig_num);
static char *php_uv_map_resource_name(enum php_uv_resource_type type) static char *php_uv_map_resource_name(enum php_uv_resource_type type)
{ {
@ -2215,6 +2232,31 @@ static void php_uv_timer_cb(uv_timer_t *handle, int status)
zval_ptr_dtor(&client); zval_ptr_dtor(&client);
} }
static void php_uv_signal_cb(uv_signal_t *handle, int sig_num)
{
zval *retval_ptr, *zsig, *client= NULL;
zval **params[2];
php_uv_t *uv = (php_uv_t*)handle->data;
TSRMLS_FETCH_FROM_CTX(uv->thread_ctx);
MAKE_STD_ZVAL(zsig);
ZVAL_LONG(zsig, sig_num);
MAKE_STD_ZVAL(client);
ZVAL_RESOURCE(client, uv->resource_id);
zend_list_addref(uv->resource_id);
params[0] = &client;
params[1] = &zsig;
php_uv_do_callback2(&retval_ptr, uv, params, 2, PHP_UV_SIGNAL_CB TSRMLS_CC);
if (retval_ptr != NULL) {
zval_ptr_dtor(&retval_ptr);
}
zval_ptr_dtor(&zsig);
zval_ptr_dtor(&client);
}
static inline uv_stream_t* php_uv_get_current_stream(php_uv_t *uv) static inline uv_stream_t* php_uv_get_current_stream(php_uv_t *uv)
{ {
uv_stream_t *stream; uv_stream_t *stream;
@ -3341,6 +3383,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_poll_stop, 0, 0, 1)
ZEND_ARG_INFO(0, handle) ZEND_ARG_INFO(0, handle)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_signal_init, 0, 0, 1)
ZEND_ARG_INFO(0, loop)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_signal_start, 0, 0, 3)
ZEND_ARG_INFO(0, sig_handle)
ZEND_ARG_INFO(0, sig_callback)
ZEND_ARG_INFO(0, sig_num)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_signal_stop, 0, 0, 1)
ZEND_ARG_INFO(0, sig_handle)
ZEND_END_ARG_INFO()
/* PHP Functions */ /* PHP Functions */
/* {{{ proto void uv_unref(resource $uv_t) /* {{{ proto void uv_unref(resource $uv_t)
@ -3503,6 +3559,88 @@ PHP_FUNCTION(uv_stop)
} }
/* }}} */ /* }}} */
/* {{{ proto resource uv_signal_init([resource $uv_loop])
*/
PHP_FUNCTION(uv_signal_init)
{
zval *zloop = NULL;
uv_loop_t *loop;
php_uv_t *uv;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"|z",&zloop) == FAILURE) {
return;
}
PHP_UV_FETCH_UV_DEFAULT_LOOP(loop, zloop);
PHP_UV_INIT_SIGNAL(uv, IS_UV_SIGNAL)
uv->uv.signal.data = uv;
ZVAL_RESOURCE(return_value, uv->resource_id);
}
/* }}} */
/* {{{ proto void uv_signal_start(resource $sig_handle, callable $sig_callback, int $sig_num)
*/
PHP_FUNCTION(uv_signal_start)
{
zval *sig_handle;
long sig_num;
php_uv_t *uv;
zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fcc = empty_fcall_info_cache;
php_uv_cb_t *cb;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"rfl", &sig_handle, &fci, &fcc, &sig_num) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(uv, php_uv_t *, &sig_handle, -1, PHP_UV_RESOURCE_NAME, uv_resource_handle);
PHP_UV_TYPE_CHECK(uv, IS_UV_SIGNAL);
if (uv_is_active((uv_handle_t*)&uv->uv.signal)) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "passed uv signal resource has been started. you don't have to call this method");
RETURN_FALSE;
}
zend_list_addref(uv->resource_id);
php_uv_cb_init(&cb, uv, &fci, &fcc, PHP_UV_SIGNAL_CB);
uv_signal_start((uv_signal_t*)&uv->uv.signal, php_uv_signal_cb, sig_num);
}
/* }}} */
/* {{{ proto int uv_signal_stop(resource $sig_handle)
*/
PHP_FUNCTION(uv_signal_stop)
{
zval *sig_handle;
php_uv_t *uv;
int r = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"r", &sig_handle) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(uv, php_uv_t *, &sig_handle, -1, PHP_UV_RESOURCE_NAME, uv_resource_handle);
PHP_UV_TYPE_CHECK(uv, IS_UV_SIGNAL);
if (!uv_is_active((uv_handle_t*)&uv->uv.signal)) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "passed uv signal resource has been stopped. you don't have to call this method");
RETURN_FALSE;
}
r = uv_signal_stop((uv_signal_t*)&uv->uv.signal);
RETURN_LONG(r);
}
/* }}} */
/* {{{ proto long uv_run_once([resource $uv_loop]) /* {{{ proto long uv_run_once([resource $uv_loop])
*/ */
PHP_FUNCTION(uv_run_once) PHP_FUNCTION(uv_run_once)
@ -6622,6 +6760,10 @@ static zend_function_entry uv_functions[] = {
PHP_FE(uv_cwd, NULL) PHP_FE(uv_cwd, NULL)
PHP_FE(uv_chdir, arginfo_uv_chdir) PHP_FE(uv_chdir, arginfo_uv_chdir)
PHP_FE(uv_resident_set_memory, NULL) PHP_FE(uv_resident_set_memory, NULL)
/* signal handling */
PHP_FE(uv_signal_init, arginfo_uv_signal_init)
PHP_FE(uv_signal_start, arginfo_uv_signal_start)
PHP_FE(uv_signal_stop, arginfo_uv_signal_stop)
/* http parser */ /* http parser */
PHP_FE(uv_http_parser_init, arginfo_uv_http_parser_init) PHP_FE(uv_http_parser_init, arginfo_uv_http_parser_init)
PHP_FE(uv_http_parser_execute, arginfo_uv_http_parser_execute) PHP_FE(uv_http_parser_execute, arginfo_uv_http_parser_execute)

7
php_uv.h Normal file → Executable file
View File

@ -89,7 +89,8 @@ enum php_uv_resource_type{
IS_UV_TTY = 16, IS_UV_TTY = 16,
IS_UV_FS_POLL = 17, IS_UV_FS_POLL = 17,
IS_UV_POLL = 18, IS_UV_POLL = 18,
IS_UV_MAX = 19 IS_UV_SIGNAL = 19,
IS_UV_MAX = 20
}; };
enum php_uv_callback_type{ enum php_uv_callback_type{
@ -116,7 +117,8 @@ enum php_uv_callback_type{
PHP_UV_FS_EVENT_CB = 20, PHP_UV_FS_EVENT_CB = 20,
PHP_UV_FS_POLL_CB = 21, PHP_UV_FS_POLL_CB = 21,
PHP_UV_POLL_CB = 22, PHP_UV_POLL_CB = 22,
PHP_UV_CB_MAX = 23 PHP_UV_SIGNAL_CB = 23,
PHP_UV_CB_MAX = 24
}; };
typedef struct { typedef struct {
@ -152,6 +154,7 @@ typedef struct {
uv_tty_t tty; uv_tty_t tty;
uv_fs_poll_t fs_poll; uv_fs_poll_t fs_poll;
uv_poll_t poll; uv_poll_t poll;
uv_signal_t signal;
} uv; } uv;
char *buffer; char *buffer;
zval *address; zval *address;

61
uv.c Normal file → Executable file
View File

@ -66,6 +66,67 @@ static int php_uv_class_init(TSRMLS_D)
zend_declare_class_constant_long(uv_class_entry, "S_IROTH", sizeof("S_IROTH")-1, S_IROTH TSRMLS_CC); zend_declare_class_constant_long(uv_class_entry, "S_IROTH", sizeof("S_IROTH")-1, S_IROTH TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "S_IWOTH", sizeof("S_IWOTH")-1, S_IWOTH TSRMLS_CC); zend_declare_class_constant_long(uv_class_entry, "S_IWOTH", sizeof("S_IWOTH")-1, S_IWOTH TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "S_IXOTH", sizeof("S_IXOTH")-1, S_IXOTH TSRMLS_CC); zend_declare_class_constant_long(uv_class_entry, "S_IXOTH", sizeof("S_IXOTH")-1, S_IXOTH TSRMLS_CC);
/* Non-windows Signal Constants */
zend_declare_class_constant_long(uv_class_entry, "SIG_IGN", sizeof("SIG_IGN")-1, (long) SIG_IGN TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIG_DFL", sizeof("SIG_DFL")-1, (long) SIG_DFL TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIG_ERR", sizeof("SIG_ERR")-1, (long) SIG_ERR TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGHUP", sizeof("SIGHUP")-1, (long) SIGHUP TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGINT", sizeof("SIGINT")-1, (long) SIGINT TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGQUIT", sizeof("SIGQUIT")-1, (long) SIGQUIT TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGILL", sizeof("SIGILL")-1, (long) SIGILL TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGTRAP", sizeof("SIGTRAP")-1, (long) SIGTRAP TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGABRT", sizeof("SIGABRT")-1, (long) SIGABRT TSRMLS_CC);
#ifdef SIGIOT
zend_declare_class_constant_long(uv_class_entry, "SIGIOT", sizeof("SIGIOT")-1, (long) SIGIOT TSRMLS_CC);
#endif
zend_declare_class_constant_long(uv_class_entry, "SIGBUS", sizeof("SIGBUS")-1, (long) SIGBUS TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGFPE", sizeof("SIGFPE")-1, (long) SIGFPE TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGKILL", sizeof("SIGKILL")-1, (long) SIGKILL TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGUSR1", sizeof("SIGUSR1")-1, (long) SIGUSR1 TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGSEGV", sizeof("SIGSEGV")-1, (long) SIGSEGV TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGUSR2", sizeof("SIGUSR2")-1, (long) SIGUSR2 TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGPIPE", sizeof("SIGPIPE")-1, (long) SIGPIPE TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGALRM", sizeof("SIGALRM")-1, (long) SIGALRM TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGTERM", sizeof("SIGTERM")-1, (long) SIGTERM TSRMLS_CC);
#ifdef SIGSTKFLT
zend_declare_class_constant_long(uv_class_entry, "SIGSTKFLT",sizeof("SIGSTKFLT")-1, (long) SIGSTKFLT TSRMLS_CC);
#endif
#ifdef SIGCLD
zend_declare_class_constant_long(uv_class_entry, "SIGCLD", sizeof("SIGCLD")-1, (long) SIGCLD TSRMLS_CC);
#endif
#ifdef SIGCHLD
zend_declare_class_constant_long(uv_class_entry, "SIGCHLD", sizeof("SIGCHLD")-1, (long) SIGCHLD TSRMLS_CC);
#endif
zend_declare_class_constant_long(uv_class_entry, "SIGCONT", sizeof("SIGCONT")-1, (long) SIGCONT TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGSTOP", sizeof("SIGSTOP")-1, (long) SIGSTOP TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGTSTP", sizeof("SIGTSTP")-1, (long) SIGTSTP TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGTTIN", sizeof("SIGTTIN")-1, (long) SIGTTIN TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGTTOU", sizeof("SIGTTOU")-1, (long) SIGTTOU TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGURG", sizeof("SIGURG")-1, (long) SIGURG TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGXCPU", sizeof("SIGXCPU")-1, (long) SIGXCPU TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGXFSZ", sizeof("SIGXFSZ")-1, (long) SIGXFSZ TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGVTALRM",sizeof("SIGVTALRM")-1, (long) SIGVTALRM TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGPROF", sizeof("SIGPROF")-1, (long) SIGPROF TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGWINCH", sizeof("SIGWINCH")-1, (long) SIGWINCH TSRMLS_CC);
#ifdef SIGPOLL
zend_declare_class_constant_long(uv_class_entry, "SIGPOLL", sizeof("SIGPOLL")-1, (long) SIGPOLL TSRMLS_CC);
#endif
zend_declare_class_constant_long(uv_class_entry, "SIGIO", sizeof("SIGIO")-1, (long) SIGIO TSRMLS_CC);
#ifdef SIGPWR
zend_declare_class_constant_long(uv_class_entry, "SIGPWR", sizeof("SIGPWR")-1, (long) SIGPWR TSRMLS_CC);
#endif
#ifdef SIGSYS
zend_declare_class_constant_long(uv_class_entry, "SIGSYS", sizeof("SIGSYS")-1, (long) SIGSYS TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGBABY", sizeof("SIGBABY")-1, (long) SIGSYS TSRMLS_CC);
#endif
#else
/* Windows Signal Constants */
zend_declare_class_constant_long(uv_class_entry, "SIGBREAK", sizeof("SIGBREAK")-1, (long) SIGBREAK TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGINT", sizeof("SIGINT")-1, (long) SIGINT TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGHUP", sizeof("SIGHUP")-1, (long) SIGHUP TSRMLS_CC);
zend_declare_class_constant_long(uv_class_entry, "SIGWINCH", sizeof("SIGWINCH")-1, (long) SIGWINCH TSRMLS_CC);
#endif #endif
zend_declare_class_constant_long(uv_class_entry, "AF_INET", sizeof("AF_INET")-1, AF_INET TSRMLS_CC); zend_declare_class_constant_long(uv_class_entry, "AF_INET", sizeof("AF_INET")-1, AF_INET TSRMLS_CC);