mirror of
https://github.com/danog/ext-uv.git
synced 2024-11-26 20:14:47 +01:00
Fix #43 - Add handling for uv pipes within UVStdio objects
Also some refcounting issues within uv_async* and uv_udp*
This commit is contained in:
parent
a2ab5c8296
commit
836c0c68f5
81
php_uv.c
81
php_uv.c
@ -559,7 +559,7 @@ static void php_uv_lock_init(enum php_uv_lock_type lock_type, INTERNAL_FUNCTION_
|
||||
}
|
||||
|
||||
PHP_UV_INIT_LOCK(lock, IS_UV_SEMAPHORE);
|
||||
error = uv_sem_init(PHP_UV_LOCK_SEM_P(lock), val);
|
||||
error = uv_sem_init(PHP_UV_LOCK_SEM_P(lock), (int) val);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1513,8 +1513,10 @@ static void php_uv_udp_send_cb(uv_udp_send_t* req, int status)
|
||||
|
||||
php_uv_do_callback2(&retval, uv, params, 2, PHP_UV_SEND_CB TSRMLS_CC);
|
||||
|
||||
if (!uv_is_closing(&uv->uv.handle)) { /* send_cb is invoked *before* the handle is marked as inactive - uv_close() will thus *not* increment the refcount and we must then not delete the refcount here */
|
||||
PHP_UV_DEBUG_OBJ_DEL_REFCOUNT(uv_udp_send_cb, uv);
|
||||
zval_ptr_dtor(¶ms[0]);
|
||||
}
|
||||
zval_ptr_dtor(¶ms[1]);
|
||||
|
||||
zval_ptr_dtor(&retval);
|
||||
@ -1732,7 +1734,7 @@ static void php_uv_after_work_cb(uv_work_t* req, int status)
|
||||
|
||||
/* as uv_cancel inside destruct_uv will return EBUSY here as were still in the work callback, but freeing is safe here */
|
||||
clean_uv_handle(uv); /* this avoids a cancel */
|
||||
OBJ_RELEASE(uv);
|
||||
OBJ_RELEASE(&uv->std);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2057,7 +2059,7 @@ static void php_uv_close_cb(uv_handle_t *handle)
|
||||
static inline zend_bool php_uv_is_handle_referenced(php_uv_t *uv) {
|
||||
zend_class_entry *ce = uv->std.ce;
|
||||
|
||||
return (ce == uv_signal_ce || ce == uv_timer_ce || ce == uv_idle_ce || ce == uv_udp_ce || ce == uv_tcp_ce || ce == uv_tty_ce || ce == uv_pipe_ce || ce == uv_prepare_ce || ce == uv_check_ce || ce == uv_poll_ce || ce == uv_fs_poll_ce) ? uv_is_active(&uv->uv.handle) : (ce == uv_async_ce);
|
||||
return (ce == uv_signal_ce || ce == uv_timer_ce || ce == uv_idle_ce || ce == uv_udp_ce || ce == uv_tcp_ce || ce == uv_tty_ce || ce == uv_pipe_ce || ce == uv_prepare_ce || ce == uv_check_ce || ce == uv_poll_ce || ce == uv_fs_poll_ce) && uv_is_active(&uv->uv.handle);
|
||||
}
|
||||
|
||||
/* uv handle must not be cleaned or closed before called */
|
||||
@ -2188,9 +2190,7 @@ void static destruct_uv_stdio(zend_object *obj)
|
||||
{
|
||||
php_uv_stdio_t *stdio = (php_uv_stdio_t *) obj;
|
||||
|
||||
if (stdio->stream != NULL) {
|
||||
zend_list_delete(stdio->stream);
|
||||
}
|
||||
zval_ptr_dtor(&stdio->stream);
|
||||
}
|
||||
|
||||
|
||||
@ -2334,6 +2334,7 @@ static void php_uv_udp_send(int type, INTERNAL_FUNCTION_PARAMETERS)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
GC_REFCOUNT(&uv->std)++;
|
||||
PHP_UV_DEBUG_OBJ_ADD_REFCOUNT(uv_udp_send, uv);
|
||||
|
||||
PHP_UV_INIT_SEND_REQ(w, uv, data->val, data->len);
|
||||
php_uv_cb_init(&cb, uv, &fci, &fcc, PHP_UV_SEND_CB);
|
||||
@ -2362,6 +2363,7 @@ static void php_uv_tcp_connect(enum php_uv_socket_type type, INTERNAL_FUNCTION_P
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
GC_REFCOUNT(&uv->std)++;
|
||||
PHP_UV_DEBUG_OBJ_ADD_REFCOUNT(uv_tcp_connect, uv);
|
||||
|
||||
PHP_UV_INIT_CONNECT(req, uv)
|
||||
php_uv_cb_init(&cb, uv, &fci, &fcc, PHP_UV_CONNECT_CB);
|
||||
@ -2449,6 +2451,15 @@ static HashTable *php_uv_loop_get_gc(zval *object, zval **table, int *n) {
|
||||
return loop->std.properties;
|
||||
}
|
||||
|
||||
static HashTable *php_uv_stdio_get_gc(zval *object, zval **table, int *n) {
|
||||
php_uv_stdio_t *stdio = (php_uv_stdio_t *) Z_OBJ_P(object);
|
||||
|
||||
*n = 1;
|
||||
*table = &stdio->stream;
|
||||
|
||||
return stdio->std.properties;
|
||||
}
|
||||
|
||||
static zend_object *php_uv_create_uv(zend_class_entry *ce) {
|
||||
php_uv_t *uv = emalloc(sizeof(php_uv_t));
|
||||
zend_object_std_init(&uv->std, ce);
|
||||
@ -2499,7 +2510,7 @@ static zend_object *php_uv_create_uv_stdio(zend_class_entry *ce) {
|
||||
stdio->std.handlers = &uv_stdio_handlers;
|
||||
|
||||
stdio->flags = 0;
|
||||
stdio->stream = NULL;
|
||||
ZVAL_UNDEF(&stdio->stream);
|
||||
|
||||
return &stdio->std;
|
||||
}
|
||||
@ -2590,6 +2601,7 @@ PHP_MINIT_FUNCTION(uv)
|
||||
uv_stdio_ce->create_object = php_uv_create_uv_stdio;
|
||||
memcpy(&uv_stdio_handlers, &uv_default_handlers, sizeof(zend_object_handlers));
|
||||
uv_stdio_handlers.dtor_obj = destruct_uv_stdio;
|
||||
uv_stdio_handlers.get_gc = php_uv_stdio_get_gc;
|
||||
|
||||
#if !defined(PHP_WIN32) && !(defined(HAVE_SOCKETS) && !defined(COMPILE_DL_SOCKETS))
|
||||
{
|
||||
@ -3731,6 +3743,7 @@ PHP_FUNCTION(uv_read_start)
|
||||
zend_fcall_info_cache fcc = empty_fcall_info_cache;
|
||||
php_uv_cb_t *cb;
|
||||
int r;
|
||||
uv_os_fd_t fd;
|
||||
|
||||
PHP_UV_DEBUG_PRINT("uv_read_start\n");
|
||||
|
||||
@ -3739,6 +3752,11 @@ PHP_FUNCTION(uv_read_start)
|
||||
Z_PARAM_FUNC(fci, fcc)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (uv_fileno(&uv->uv.handle, &fd) != 0) {
|
||||
php_error_docref(NULL, E_WARNING, "passed UV handle is not initialized yet");
|
||||
return;
|
||||
}
|
||||
|
||||
GC_REFCOUNT(&uv->std)++;
|
||||
PHP_UV_DEBUG_OBJ_ADD_REFCOUNT(uv_read_start, uv);
|
||||
|
||||
@ -4644,34 +4662,56 @@ PHP_FUNCTION(uv_stdio_new)
|
||||
php_stream *stream;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(),
|
||||
"r|l", &handle, &flags) == FAILURE) {
|
||||
"z|l", &handle, &flags) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(handle) == IS_LONG) {
|
||||
fd = Z_LVAL_P(handle);
|
||||
if (flags & (UV_CREATE_PIPE | UV_INHERIT_STREAM)) {
|
||||
php_error_docref(NULL, E_WARNING, "flags must not be UV::CREATE_PIPE or UV::INHERIT_STREAM for resources");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
flags |= UV_INHERIT_FD;
|
||||
} else if (Z_TYPE_P(handle) == IS_RESOURCE) {
|
||||
if ((stream = (php_stream *) zend_fetch_resource_ex(handle, NULL, php_file_le_stream()))) {
|
||||
if (php_stream_cast(stream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 1) != SUCCESS || fd < 0) {
|
||||
fd = -1;
|
||||
if (php_stream_cast(stream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL, (void *) &fd, 1) != SUCCESS || fd < 0) {
|
||||
php_error_docref(NULL, E_WARNING, "passed resource without file descriptor");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
#if !defined(PHP_WIN32) || defined(HAVE_SOCKET)
|
||||
} else if ((socket = (php_socket *) zend_fetch_resource_ex(handle, NULL, php_sockets_le_socket()))) {
|
||||
fd = socket->bsd_socket;
|
||||
#endif
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "passed unexpected resource");
|
||||
php_error_docref(NULL, E_WARNING, "passed unexpected resource, expected file or socket");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (flags & (UV_CREATE_PIPE | UV_INHERIT_STREAM)) {
|
||||
php_error_docref(NULL, E_WARNING, "flags must not be UV::CREATE_PIPE or UV::INHERIT_STREAM for resources");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
flags |= UV_INHERIT_FD;
|
||||
} else if (Z_TYPE_P(handle) == IS_OBJECT && instanceof_function(Z_OBJCE_P(handle), uv_ce)) {
|
||||
if (flags & UV_INHERIT_FD) {
|
||||
php_error_docref(NULL, E_WARNING, "flags must not be UV::INHERIT_FD for UV handles");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if ((flags & (UV_CREATE_PIPE | UV_INHERIT_STREAM)) == (UV_CREATE_PIPE | UV_INHERIT_STREAM) || !(flags & (UV_CREATE_PIPE | UV_INHERIT_STREAM))) {
|
||||
php_error_docref(NULL, E_WARNING, "flags must be exactly one of UV::INHERIT_STREAM or UV::CREATE_PIPE for UV handles");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "passed unexpected value, expected instance of UV, file resource or socket resource");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
PHP_UV_INIT_GENERIC(stdio, php_uv_stdio_t, uv_stdio_ce);
|
||||
stdio->flags = flags;
|
||||
stdio->fd = fd;
|
||||
|
||||
if (Z_TYPE_P(handle) == IS_RESOURCE) {
|
||||
stdio->stream = Z_RES_P(handle);
|
||||
Z_ADDREF_P(handle);
|
||||
if (Z_TYPE_P(handle) == IS_RESOURCE || Z_TYPE_P(handle) == IS_OBJECT) {
|
||||
ZVAL_COPY(&stdio->stream, handle);
|
||||
}
|
||||
|
||||
RETURN_OBJ(&stdio->std);
|
||||
@ -4914,7 +4954,7 @@ PHP_FUNCTION(uv_spawn)
|
||||
php_uv_stdio_t *stdio_tmp;
|
||||
|
||||
if (Z_TYPE_P(value) != IS_OBJECT || Z_OBJCE_P(value) != uv_stdio_ce) {
|
||||
php_error_docref(NULL, E_ERROR, "must be uv_stdio resource");
|
||||
php_error_docref(NULL, E_ERROR, "must be instance of UVStdio");
|
||||
}
|
||||
|
||||
stdio_tmp = (php_uv_stdio_t *) Z_OBJ_P(value);
|
||||
@ -4923,15 +4963,9 @@ PHP_FUNCTION(uv_spawn)
|
||||
|
||||
if (stdio_tmp->flags & UV_INHERIT_FD) {
|
||||
stdio[x].data.fd = stdio_tmp->fd;
|
||||
#if 0
|
||||
} else if (stdio_tmp->flags & (UV_CREATE_PIPE | UV_INHERIT_STREAM)) {
|
||||
php_uv_t* uv_pipe;
|
||||
zval passed_id;
|
||||
ZVAL_RES(&passed_id, stdio_tmp->stream);
|
||||
|
||||
uv_pipe = (php_uv_t *) zend_fetch_resource_ex(&passed_id, PHP_UV_RESOURCE_NAME, uv_resource_handle);
|
||||
stdio[x].data.stream = (uv_stream_t*)&uv_pipe->uv.pipe;
|
||||
#endif
|
||||
php_uv_t *uv_pipe = (php_uv_t *) Z_OBJ(stdio_tmp->stream);
|
||||
stdio[x].data.stream = &uv_pipe->uv.stream;
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "passes unexpected stdio flags");
|
||||
RETURN_FALSE;
|
||||
@ -5416,7 +5450,6 @@ PHP_FUNCTION(uv_async_send)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
uv_async_send(&uv->uv.async);
|
||||
GC_REFCOUNT(&uv->std)++;
|
||||
PHP_UV_DEBUG_OBJ_ADD_REFCOUNT(uv_async_send, uv);
|
||||
}
|
||||
/* }}} */
|
||||
|
2
php_uv.h
2
php_uv.h
@ -193,7 +193,7 @@ typedef struct {
|
||||
zend_object std;
|
||||
|
||||
int fd;
|
||||
zend_resource *stream;
|
||||
zval stream;
|
||||
int flags;
|
||||
} php_uv_stdio_t;
|
||||
|
||||
|
@ -6,4 +6,4 @@ Test uv_spawn doesn't cause segfault #56
|
||||
$ioRead = uv_stdio_new(null, Uv::CREATE_PIPE | Uv::INHERIT_STREAM);
|
||||
|
||||
--EXPECTF--
|
||||
Warning: uv_stdio_new() expects parameter 1 to be resource, null given in %s on line %d
|
||||
Warning: uv_stdio_new(): passed unexpected value, expected instance of UV, file resource or socket resource in %s on line %d
|
||||
|
Loading…
Reference in New Issue
Block a user