Skip to content

Commit 81cd617

Browse files
committed
Merge pull request #53 from rdlowrey/master
Add uv_stop, signal handling, etc.
2 parents 2b04d12 + cf36261 commit 81cd617

File tree

4 files changed

+267
-8
lines changed

4 files changed

+267
-8
lines changed

php_uv.c

Lines changed: 175 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0
6565
TSRMLS_SET_CTX(uv->thread_ctx); \
6666
uv->resource_id = PHP_UV_LIST_INSERT(uv, uv_resource_handle); \
6767

68+
#define PHP_UV_INIT_SIGNAL(uv, uv_type) \
69+
uv = (php_uv_t *)emalloc(sizeof(php_uv_t)); \
70+
if (!uv) { \
71+
php_error_docref(NULL TSRMLS_CC, E_ERROR, "emalloc failed"); \
72+
RETURN_FALSE; \
73+
} \
74+
if (uv_signal_init(loop, &uv->uv.signal)) { \
75+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "uv_signal_init failed");\
76+
RETURN_FALSE;\
77+
} \
78+
uv->type = uv_type; \
79+
PHP_UV_INIT_ZVALS(uv) \
80+
TSRMLS_SET_CTX(uv->thread_ctx); \
81+
uv->resource_id = PHP_UV_LIST_INSERT(uv, uv_resource_handle); \
82+
6883
#define PHP_UV_INIT_CONNECT(req, uv) \
6984
req = (uv_connect_t*)emalloc(sizeof(uv_connect_t)); \
7085
req->data = uv;
@@ -285,6 +300,8 @@ static void php_uv_timer_cb(uv_timer_t *handle, int status);
285300

286301
static void php_uv_idle_cb(uv_timer_t *handle, int status);
287302

303+
static void php_uv_signal_cb(uv_signal_t *handle, int sig_num);
304+
288305

289306
static char *php_uv_map_resource_name(enum php_uv_resource_type type)
290307
{
@@ -419,7 +436,7 @@ static inline int php_uv_common_init(php_uv_t **result, uv_loop_t *loop, enum ph
419436
{
420437
r = uv_check_init(loop, &uv->uv.check);
421438
if (r) {
422-
php_error_docref(NULL TSRMLS_CC, E_ERROR, "uv_prepare_init failed");
439+
php_error_docref(NULL TSRMLS_CC, E_ERROR, "uv_check_init failed");
423440
goto cleanup;
424441
}
425442

@@ -1231,6 +1248,7 @@ static int php_uv_do_callback2(zval **retval_ptr, php_uv_t *uv, zval ***params,
12311248
}
12321249

12331250
#ifdef ZTS
1251+
12341252
static int php_uv_do_callback3(zval **retval_ptr, php_uv_t *uv, zval ***params, int param_count, enum php_uv_callback_type type)
12351253
{
12361254
int error = 0;
@@ -1262,9 +1280,17 @@ static int php_uv_do_callback3(zval **retval_ptr, php_uv_t *uv, zval ***params,
12621280
uv->callback[type]->fcc.called_scope = NULL;
12631281
uv->callback[type]->fcc.object_ptr = ZEG->This;
12641282

1265-
if (zend_call_function(&uv->callback[type]->fci, &uv->callback[type]->fcc TSRMLS_CC) != SUCCESS) {
1283+
zend_try {
1284+
if (zend_call_function(&uv->callback[type]->fci, &uv->callback[type]->fcc TSRMLS_CC) != SUCCESS) {
1285+
error = -1;
1286+
}
1287+
1288+
if (retval_ptr != NULL) {
1289+
zval_ptr_dtor(retval_ptr);
1290+
}
1291+
} zend_catch {
12661292
error = -1;
1267-
}
1293+
} zend_end_try();
12681294

12691295
{
12701296
zend_op_array *ops = &uv->callback[type]->fcc.function_handler->op_array;
@@ -1275,9 +1301,6 @@ static int php_uv_do_callback3(zval **retval_ptr, php_uv_t *uv, zval ***params,
12751301
}
12761302
}
12771303
}
1278-
if (retval_ptr != NULL) {
1279-
zval_ptr_dtor(retval_ptr);
1280-
}
12811304

12821305
php_request_shutdown(TSRMLS_C);
12831306
tsrm_set_interpreter_context(old);
@@ -2215,6 +2238,31 @@ static void php_uv_timer_cb(uv_timer_t *handle, int status)
22152238
zval_ptr_dtor(&client);
22162239
}
22172240

2241+
static void php_uv_signal_cb(uv_signal_t *handle, int sig_num)
2242+
{
2243+
zval *retval_ptr, *zsig, *client= NULL;
2244+
zval **params[2];
2245+
php_uv_t *uv = (php_uv_t*)handle->data;
2246+
TSRMLS_FETCH_FROM_CTX(uv->thread_ctx);
2247+
2248+
MAKE_STD_ZVAL(zsig);
2249+
ZVAL_LONG(zsig, sig_num);
2250+
MAKE_STD_ZVAL(client);
2251+
ZVAL_RESOURCE(client, uv->resource_id);
2252+
zend_list_addref(uv->resource_id);
2253+
2254+
params[0] = &client;
2255+
params[1] = &zsig;
2256+
2257+
php_uv_do_callback2(&retval_ptr, uv, params, 2, PHP_UV_SIGNAL_CB TSRMLS_CC);
2258+
2259+
if (retval_ptr != NULL) {
2260+
zval_ptr_dtor(&retval_ptr);
2261+
}
2262+
zval_ptr_dtor(&zsig);
2263+
zval_ptr_dtor(&client);
2264+
}
2265+
22182266
static inline uv_stream_t* php_uv_get_current_stream(php_uv_t *uv)
22192267
{
22202268
uv_stream_t *stream;
@@ -2688,6 +2736,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_run, 0, 0, 1)
26882736
ZEND_ARG_INFO(0, loop)
26892737
ZEND_END_ARG_INFO()
26902738

2739+
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_stop, 0, 0, 1)
2740+
ZEND_ARG_INFO(0, loop)
2741+
ZEND_END_ARG_INFO()
2742+
26912743
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_loop_delete, 0, 0, 1)
26922744
ZEND_ARG_INFO(0, loop)
26932745
ZEND_END_ARG_INFO()
@@ -3337,6 +3389,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_poll_stop, 0, 0, 1)
33373389
ZEND_ARG_INFO(0, handle)
33383390
ZEND_END_ARG_INFO()
33393391

3392+
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_signal_init, 0, 0, 1)
3393+
ZEND_ARG_INFO(0, loop)
3394+
ZEND_END_ARG_INFO()
3395+
3396+
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_signal_start, 0, 0, 3)
3397+
ZEND_ARG_INFO(0, sig_handle)
3398+
ZEND_ARG_INFO(0, sig_callback)
3399+
ZEND_ARG_INFO(0, sig_num)
3400+
ZEND_END_ARG_INFO()
3401+
3402+
ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_signal_stop, 0, 0, 1)
3403+
ZEND_ARG_INFO(0, sig_handle)
3404+
ZEND_END_ARG_INFO()
3405+
33403406
/* PHP Functions */
33413407

33423408
/* {{{ proto void uv_unref(resource $uv_t)
@@ -3483,6 +3549,104 @@ PHP_FUNCTION(uv_run)
34833549
}
34843550
/* }}} */
34853551

3552+
/* {{{ proto void uv_stop([resource $uv_loop])
3553+
*/
3554+
PHP_FUNCTION(uv_stop)
3555+
{
3556+
zval *zloop = NULL;
3557+
uv_loop_t *loop;
3558+
3559+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
3560+
"|z",&zloop) == FAILURE) {
3561+
return;
3562+
}
3563+
PHP_UV_FETCH_UV_DEFAULT_LOOP(loop, zloop);
3564+
uv_stop(loop);
3565+
}
3566+
/* }}} */
3567+
3568+
/* {{{ proto resource uv_signal_init([resource $uv_loop])
3569+
*/
3570+
PHP_FUNCTION(uv_signal_init)
3571+
{
3572+
zval *zloop = NULL;
3573+
uv_loop_t *loop;
3574+
php_uv_t *uv;
3575+
3576+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
3577+
"|z",&zloop) == FAILURE) {
3578+
return;
3579+
}
3580+
3581+
PHP_UV_FETCH_UV_DEFAULT_LOOP(loop, zloop);
3582+
PHP_UV_INIT_SIGNAL(uv, IS_UV_SIGNAL)
3583+
3584+
uv->uv.signal.data = uv;
3585+
3586+
ZVAL_RESOURCE(return_value, uv->resource_id);
3587+
}
3588+
/* }}} */
3589+
3590+
/* {{{ proto void uv_signal_start(resource $sig_handle, callable $sig_callback, int $sig_num)
3591+
*/
3592+
PHP_FUNCTION(uv_signal_start)
3593+
{
3594+
zval *sig_handle;
3595+
long sig_num;
3596+
php_uv_t *uv;
3597+
zend_fcall_info fci = empty_fcall_info;
3598+
zend_fcall_info_cache fcc = empty_fcall_info_cache;
3599+
php_uv_cb_t *cb;
3600+
3601+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
3602+
"rfl", &sig_handle, &fci, &fcc, &sig_num) == FAILURE) {
3603+
return;
3604+
}
3605+
3606+
ZEND_FETCH_RESOURCE(uv, php_uv_t *, &sig_handle, -1, PHP_UV_RESOURCE_NAME, uv_resource_handle);
3607+
3608+
PHP_UV_TYPE_CHECK(uv, IS_UV_SIGNAL);
3609+
3610+
if (uv_is_active((uv_handle_t*)&uv->uv.signal)) {
3611+
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "passed uv signal resource has been started. you don't have to call this method");
3612+
RETURN_FALSE;
3613+
}
3614+
3615+
zend_list_addref(uv->resource_id);
3616+
php_uv_cb_init(&cb, uv, &fci, &fcc, PHP_UV_SIGNAL_CB);
3617+
3618+
uv_signal_start((uv_signal_t*)&uv->uv.signal, php_uv_signal_cb, sig_num);
3619+
}
3620+
/* }}} */
3621+
3622+
/* {{{ proto int uv_signal_stop(resource $sig_handle)
3623+
*/
3624+
PHP_FUNCTION(uv_signal_stop)
3625+
{
3626+
zval *sig_handle;
3627+
php_uv_t *uv;
3628+
int r = 0;
3629+
3630+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
3631+
"r", &sig_handle) == FAILURE) {
3632+
return;
3633+
}
3634+
3635+
ZEND_FETCH_RESOURCE(uv, php_uv_t *, &sig_handle, -1, PHP_UV_RESOURCE_NAME, uv_resource_handle);
3636+
3637+
PHP_UV_TYPE_CHECK(uv, IS_UV_SIGNAL);
3638+
3639+
if (!uv_is_active((uv_handle_t*)&uv->uv.signal)) {
3640+
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "passed uv signal resource has been stopped. you don't have to call this method");
3641+
RETURN_FALSE;
3642+
}
3643+
3644+
r = uv_signal_stop((uv_signal_t*)&uv->uv.signal);
3645+
3646+
RETURN_LONG(r);
3647+
}
3648+
/* }}} */
3649+
34863650
/* {{{ proto long uv_run_once([resource $uv_loop])
34873651
*/
34883652
PHP_FUNCTION(uv_run_once)
@@ -6439,6 +6603,7 @@ static zend_function_entry uv_functions[] = {
64396603
PHP_FE(uv_unref, arginfo_uv_unref)
64406604
PHP_FE(uv_loop_new, NULL)
64416605
PHP_FE(uv_default_loop, NULL)
6606+
PHP_FE(uv_stop, arginfo_uv_stop)
64426607
PHP_FE(uv_run, arginfo_uv_run)
64436608
PHP_FE(uv_run_once, arginfo_uv_run_once)
64446609
PHP_FE(uv_ip4_addr, arginfo_uv_ip4_addr)
@@ -6601,6 +6766,10 @@ static zend_function_entry uv_functions[] = {
66016766
PHP_FE(uv_cwd, NULL)
66026767
PHP_FE(uv_chdir, arginfo_uv_chdir)
66036768
PHP_FE(uv_resident_set_memory, NULL)
6769+
/* signal handling */
6770+
PHP_FE(uv_signal_init, arginfo_uv_signal_init)
6771+
PHP_FE(uv_signal_start, arginfo_uv_signal_start)
6772+
PHP_FE(uv_signal_stop, arginfo_uv_signal_stop)
66046773
/* http parser */
66056774
PHP_FE(uv_http_parser_init, arginfo_uv_http_parser_init)
66066775
PHP_FE(uv_http_parser_execute, arginfo_uv_http_parser_execute)

php_uv.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ enum php_uv_resource_type{
8989
IS_UV_TTY = 16,
9090
IS_UV_FS_POLL = 17,
9191
IS_UV_POLL = 18,
92-
IS_UV_MAX = 19
92+
IS_UV_SIGNAL = 19,
93+
IS_UV_MAX = 20
9394
};
9495

9596
enum php_uv_callback_type{
@@ -116,7 +117,8 @@ enum php_uv_callback_type{
116117
PHP_UV_FS_EVENT_CB = 20,
117118
PHP_UV_FS_POLL_CB = 21,
118119
PHP_UV_POLL_CB = 22,
119-
PHP_UV_CB_MAX = 23
120+
PHP_UV_SIGNAL_CB = 23,
121+
PHP_UV_CB_MAX = 24
120122
};
121123

122124
typedef struct {
@@ -152,6 +154,7 @@ typedef struct {
152154
uv_tty_t tty;
153155
uv_fs_poll_t fs_poll;
154156
uv_poll_t poll;
157+
uv_signal_t signal;
155158
} uv;
156159
char *buffer;
157160
zval *address;

tests/100-uv_stop.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Test uv_stop ends loop execution
3+
--FILE--
4+
<?php
5+
$loop = uv_default_loop();
6+
$timer = uv_timer_init();
7+
8+
$i = 0;
9+
uv_timer_start($timer, 10, 10, function($timer) use (&$i, $loop) {
10+
echo "count: {$i}" . PHP_EOL;
11+
$i++;
12+
13+
if ($i > 3) {
14+
uv_stop($loop);
15+
}
16+
});
17+
18+
uv_run();
19+
20+
echo "finished" . PHP_EOL;
21+
--EXPECT--
22+
count: 0
23+
count: 1
24+
count: 2
25+
count: 3
26+
finished

uv.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,67 @@ static int php_uv_class_init(TSRMLS_D)
6666
zend_declare_class_constant_long(uv_class_entry, "S_IROTH", sizeof("S_IROTH")-1, S_IROTH TSRMLS_CC);
6767
zend_declare_class_constant_long(uv_class_entry, "S_IWOTH", sizeof("S_IWOTH")-1, S_IWOTH TSRMLS_CC);
6868
zend_declare_class_constant_long(uv_class_entry, "S_IXOTH", sizeof("S_IXOTH")-1, S_IXOTH TSRMLS_CC);
69+
70+
/* Non-windows Signal Constants */
71+
zend_declare_class_constant_long(uv_class_entry, "SIG_IGN", sizeof("SIG_IGN")-1, (long) SIG_IGN TSRMLS_CC);
72+
zend_declare_class_constant_long(uv_class_entry, "SIG_DFL", sizeof("SIG_DFL")-1, (long) SIG_DFL TSRMLS_CC);
73+
zend_declare_class_constant_long(uv_class_entry, "SIG_ERR", sizeof("SIG_ERR")-1, (long) SIG_ERR TSRMLS_CC);
74+
zend_declare_class_constant_long(uv_class_entry, "SIGHUP", sizeof("SIGHUP")-1, (long) SIGHUP TSRMLS_CC);
75+
zend_declare_class_constant_long(uv_class_entry, "SIGINT", sizeof("SIGINT")-1, (long) SIGINT TSRMLS_CC);
76+
zend_declare_class_constant_long(uv_class_entry, "SIGQUIT", sizeof("SIGQUIT")-1, (long) SIGQUIT TSRMLS_CC);
77+
zend_declare_class_constant_long(uv_class_entry, "SIGILL", sizeof("SIGILL")-1, (long) SIGILL TSRMLS_CC);
78+
zend_declare_class_constant_long(uv_class_entry, "SIGTRAP", sizeof("SIGTRAP")-1, (long) SIGTRAP TSRMLS_CC);
79+
zend_declare_class_constant_long(uv_class_entry, "SIGABRT", sizeof("SIGABRT")-1, (long) SIGABRT TSRMLS_CC);
80+
#ifdef SIGIOT
81+
zend_declare_class_constant_long(uv_class_entry, "SIGIOT", sizeof("SIGIOT")-1, (long) SIGIOT TSRMLS_CC);
82+
#endif
83+
zend_declare_class_constant_long(uv_class_entry, "SIGBUS", sizeof("SIGBUS")-1, (long) SIGBUS TSRMLS_CC);
84+
zend_declare_class_constant_long(uv_class_entry, "SIGFPE", sizeof("SIGFPE")-1, (long) SIGFPE TSRMLS_CC);
85+
zend_declare_class_constant_long(uv_class_entry, "SIGKILL", sizeof("SIGKILL")-1, (long) SIGKILL TSRMLS_CC);
86+
zend_declare_class_constant_long(uv_class_entry, "SIGUSR1", sizeof("SIGUSR1")-1, (long) SIGUSR1 TSRMLS_CC);
87+
zend_declare_class_constant_long(uv_class_entry, "SIGSEGV", sizeof("SIGSEGV")-1, (long) SIGSEGV TSRMLS_CC);
88+
zend_declare_class_constant_long(uv_class_entry, "SIGUSR2", sizeof("SIGUSR2")-1, (long) SIGUSR2 TSRMLS_CC);
89+
zend_declare_class_constant_long(uv_class_entry, "SIGPIPE", sizeof("SIGPIPE")-1, (long) SIGPIPE TSRMLS_CC);
90+
zend_declare_class_constant_long(uv_class_entry, "SIGALRM", sizeof("SIGALRM")-1, (long) SIGALRM TSRMLS_CC);
91+
zend_declare_class_constant_long(uv_class_entry, "SIGTERM", sizeof("SIGTERM")-1, (long) SIGTERM TSRMLS_CC);
92+
#ifdef SIGSTKFLT
93+
zend_declare_class_constant_long(uv_class_entry, "SIGSTKFLT",sizeof("SIGSTKFLT")-1, (long) SIGSTKFLT TSRMLS_CC);
94+
#endif
95+
#ifdef SIGCLD
96+
zend_declare_class_constant_long(uv_class_entry, "SIGCLD", sizeof("SIGCLD")-1, (long) SIGCLD TSRMLS_CC);
97+
#endif
98+
#ifdef SIGCHLD
99+
zend_declare_class_constant_long(uv_class_entry, "SIGCHLD", sizeof("SIGCHLD")-1, (long) SIGCHLD TSRMLS_CC);
100+
#endif
101+
zend_declare_class_constant_long(uv_class_entry, "SIGCONT", sizeof("SIGCONT")-1, (long) SIGCONT TSRMLS_CC);
102+
zend_declare_class_constant_long(uv_class_entry, "SIGSTOP", sizeof("SIGSTOP")-1, (long) SIGSTOP TSRMLS_CC);
103+
zend_declare_class_constant_long(uv_class_entry, "SIGTSTP", sizeof("SIGTSTP")-1, (long) SIGTSTP TSRMLS_CC);
104+
zend_declare_class_constant_long(uv_class_entry, "SIGTTIN", sizeof("SIGTTIN")-1, (long) SIGTTIN TSRMLS_CC);
105+
zend_declare_class_constant_long(uv_class_entry, "SIGTTOU", sizeof("SIGTTOU")-1, (long) SIGTTOU TSRMLS_CC);
106+
zend_declare_class_constant_long(uv_class_entry, "SIGURG", sizeof("SIGURG")-1, (long) SIGURG TSRMLS_CC);
107+
zend_declare_class_constant_long(uv_class_entry, "SIGXCPU", sizeof("SIGXCPU")-1, (long) SIGXCPU TSRMLS_CC);
108+
zend_declare_class_constant_long(uv_class_entry, "SIGXFSZ", sizeof("SIGXFSZ")-1, (long) SIGXFSZ TSRMLS_CC);
109+
zend_declare_class_constant_long(uv_class_entry, "SIGVTALRM",sizeof("SIGVTALRM")-1, (long) SIGVTALRM TSRMLS_CC);
110+
zend_declare_class_constant_long(uv_class_entry, "SIGPROF", sizeof("SIGPROF")-1, (long) SIGPROF TSRMLS_CC);
111+
zend_declare_class_constant_long(uv_class_entry, "SIGWINCH", sizeof("SIGWINCH")-1, (long) SIGWINCH TSRMLS_CC);
112+
#ifdef SIGPOLL
113+
zend_declare_class_constant_long(uv_class_entry, "SIGPOLL", sizeof("SIGPOLL")-1, (long) SIGPOLL TSRMLS_CC);
114+
#endif
115+
zend_declare_class_constant_long(uv_class_entry, "SIGIO", sizeof("SIGIO")-1, (long) SIGIO TSRMLS_CC);
116+
#ifdef SIGPWR
117+
zend_declare_class_constant_long(uv_class_entry, "SIGPWR", sizeof("SIGPWR")-1, (long) SIGPWR TSRMLS_CC);
118+
#endif
119+
#ifdef SIGSYS
120+
zend_declare_class_constant_long(uv_class_entry, "SIGSYS", sizeof("SIGSYS")-1, (long) SIGSYS TSRMLS_CC);
121+
zend_declare_class_constant_long(uv_class_entry, "SIGBABY", sizeof("SIGBABY")-1, (long) SIGSYS TSRMLS_CC);
122+
#endif
123+
124+
#else
125+
/* Windows Signal Constants */
126+
zend_declare_class_constant_long(uv_class_entry, "SIGBREAK", sizeof("SIGBREAK")-1, (long) SIGBREAK TSRMLS_CC);
127+
zend_declare_class_constant_long(uv_class_entry, "SIGINT", sizeof("SIGINT")-1, (long) SIGINT TSRMLS_CC);
128+
zend_declare_class_constant_long(uv_class_entry, "SIGHUP", sizeof("SIGHUP")-1, (long) SIGHUP TSRMLS_CC);
129+
zend_declare_class_constant_long(uv_class_entry, "SIGWINCH", sizeof("SIGWINCH")-1, (long) SIGWINCH TSRMLS_CC);
69130
#endif
70131

71132
zend_declare_class_constant_long(uv_class_entry, "AF_INET", sizeof("AF_INET")-1, AF_INET TSRMLS_CC);

0 commit comments

Comments
 (0)