From 1e32c246081a1b33a52c51045014c4440c6d0924 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Wed, 7 May 2014 15:53:06 -0400 Subject: [PATCH] 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: getConstants()); --- php_uv.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ php_uv.h | 7 ++- uv.c | 61 ++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 2 deletions(-) mode change 100644 => 100755 php_uv.c mode change 100644 => 100755 php_uv.h mode change 100644 => 100755 uv.c diff --git a/php_uv.c b/php_uv.c old mode 100644 new mode 100755 index 0efa9a2..85c5d18 --- a/php_uv.c +++ b/php_uv.c @@ -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); \ 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) \ req = (uv_connect_t*)emalloc(sizeof(uv_connect_t)); \ 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_signal_cb(uv_signal_t *handle, int sig_num); + 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); } +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) { 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_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 */ /* {{{ 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]) */ PHP_FUNCTION(uv_run_once) @@ -6622,6 +6760,10 @@ static zend_function_entry uv_functions[] = { PHP_FE(uv_cwd, NULL) PHP_FE(uv_chdir, arginfo_uv_chdir) 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 */ PHP_FE(uv_http_parser_init, arginfo_uv_http_parser_init) PHP_FE(uv_http_parser_execute, arginfo_uv_http_parser_execute) diff --git a/php_uv.h b/php_uv.h old mode 100644 new mode 100755 index 04ffaf9..df43bd7 --- a/php_uv.h +++ b/php_uv.h @@ -89,7 +89,8 @@ enum php_uv_resource_type{ IS_UV_TTY = 16, IS_UV_FS_POLL = 17, IS_UV_POLL = 18, - IS_UV_MAX = 19 + IS_UV_SIGNAL = 19, + IS_UV_MAX = 20 }; enum php_uv_callback_type{ @@ -116,7 +117,8 @@ enum php_uv_callback_type{ PHP_UV_FS_EVENT_CB = 20, PHP_UV_FS_POLL_CB = 21, PHP_UV_POLL_CB = 22, - PHP_UV_CB_MAX = 23 + PHP_UV_SIGNAL_CB = 23, + PHP_UV_CB_MAX = 24 }; typedef struct { @@ -152,6 +154,7 @@ typedef struct { uv_tty_t tty; uv_fs_poll_t fs_poll; uv_poll_t poll; + uv_signal_t signal; } uv; char *buffer; zval *address; diff --git a/uv.c b/uv.c old mode 100644 new mode 100755 index f043768..7de9322 --- a/uv.c +++ b/uv.c @@ -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_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); + + /* 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 zend_declare_class_constant_long(uv_class_entry, "AF_INET", sizeof("AF_INET")-1, AF_INET TSRMLS_CC);