@@ -1330,7 +1330,6 @@ static void exec_on_exit(uv_process_t* process, const int64_t exit_status, int t
13301330 if (exec -> event .terminated != true) {
13311331 exec -> event .terminated = true;
13321332 ZEND_ASYNC_DECREASE_EVENT_COUNT ;
1333-
13341333 ZEND_ASYNC_CALLBACKS_NOTIFY (& exec -> event .base , NULL , NULL );
13351334 }
13361335}
@@ -1413,6 +1412,8 @@ static void exec_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf
14131412 }
14141413
14151414 uv_read_stop (stream );
1415+ // For libuv_close_handle_cb to work correctly.
1416+ stream -> data = stream ;
14161417 uv_close ((uv_handle_t * )stream , libuv_close_handle_cb );
14171418
14181419 if (exec -> terminated != true) {
@@ -1453,6 +1454,7 @@ static void exec_std_err_read_cb(uv_stream_t *stream, ssize_t nread, const uv_bu
14531454 event -> stderr_pipe = NULL ;
14541455
14551456 uv_read_stop (stream );
1457+ stream -> data = stream ;
14561458 uv_close ((uv_handle_t * )stream , libuv_close_handle_cb );
14571459 }
14581460
@@ -1483,10 +1485,6 @@ static void libuv_exec_stop(zend_async_event_t *event)
14831485
14841486 async_exec_event_t * exec = (async_exec_event_t * )(event );
14851487
1486- if (exec -> process == NULL ) {
1487- return ;
1488- }
1489-
14901488 event -> loop_ref_count = 0 ;
14911489 ZEND_ASYNC_DECREASE_EVENT_COUNT ;
14921490
@@ -1521,20 +1519,27 @@ static void libuv_exec_dispose(zend_async_event_t *event)
15211519
15221520 if (exec -> process != NULL && !uv_is_closing ((uv_handle_t * )exec -> process )) {
15231521 uv_process_kill (exec -> process , ZEND_ASYNC_SIGTERM );
1524- uv_close ((uv_handle_t * )exec -> process , libuv_close_handle_cb );
1525- exec -> process = NULL ;
1522+ uv_handle_t * handle = (uv_handle_t * ) exec -> process ;
1523+ exec -> process = NULL ;
1524+ // For libuv_close_handle_cb to work correctly.
1525+ handle -> data = handle ;
1526+ uv_close (handle , libuv_close_handle_cb );
15261527 }
15271528
15281529 if (exec -> stdout_pipe != NULL && !uv_is_closing ((uv_handle_t * )exec -> stdout_pipe )) {
15291530 uv_read_stop ((uv_stream_t * )exec -> stdout_pipe );
1530- uv_close ((uv_handle_t * )exec -> stdout_pipe , libuv_close_handle_cb );
1531- exec -> stdout_pipe = NULL ;
1531+ uv_handle_t * handle = (uv_handle_t * ) exec -> stdout_pipe ;
1532+ exec -> stdout_pipe -> data = NULL ;
1533+ handle -> data = handle ;
1534+ uv_close (handle , libuv_close_handle_cb );
15321535 }
15331536
15341537 if (exec -> stderr_pipe != NULL && !uv_is_closing ((uv_handle_t * )exec -> stderr_pipe )) {
15351538 uv_read_stop ((uv_stream_t * )exec -> stderr_pipe );
1536- uv_close ((uv_handle_t * )exec -> stderr_pipe , libuv_close_handle_cb );
1537- exec -> stderr_pipe = NULL ;
1539+ uv_handle_t * handle = (uv_handle_t * ) exec -> stderr_pipe ;
1540+ exec -> stderr_pipe -> data = NULL ;
1541+ handle -> data = handle ;
1542+ uv_close (handle , libuv_close_handle_cb );
15381543 }
15391544
15401545#ifdef PHP_WIN32
@@ -1543,6 +1548,9 @@ static void libuv_exec_dispose(zend_async_event_t *event)
15431548 exec -> quoted_cmd = NULL ;
15441549 }
15451550#endif
1551+
1552+ // Free the event itself
1553+ pefree (event , 0 );
15461554}
15471555/* }}} */
15481556
@@ -1664,6 +1672,17 @@ static int libuv_exec(
16641672 ZVAL_UNDEF (& tmp_return_value );
16651673 ZVAL_UNDEF (& tmp_return_buffer );
16661674
1675+ if (return_value != NULL ) {
1676+ ZVAL_BOOL (return_value , false);
1677+ }
1678+
1679+ zend_coroutine_t * coroutine = ZEND_ASYNC_CURRENT_COROUTINE ;
1680+
1681+ if (UNEXPECTED (coroutine == NULL )) {
1682+ zend_throw_error (NULL , "Cannot call async_exec() outside of an async context" );
1683+ return -1 ;
1684+ }
1685+
16671686 zend_async_exec_event_t * exec_event = ZEND_ASYNC_NEW_EXEC_EVENT (
16681687 exec_mode ,
16691688 cmd ,
@@ -1674,6 +1693,27 @@ static int libuv_exec(
16741693 env
16751694 );
16761695
1696+ if (UNEXPECTED (EG (exception ))) {
1697+ return -1 ;
1698+ }
1699+
1700+ zend_async_waker_new (coroutine );
1701+ if (UNEXPECTED (EG (exception ))) {
1702+ return -1 ;
1703+ }
1704+
1705+ zend_async_resume_when (coroutine , & exec_event -> base , true, zend_async_waker_callback_resolve , NULL );
1706+ if (UNEXPECTED (EG (exception ))) {
1707+ return -1 ;
1708+ }
1709+
1710+ ZEND_ASYNC_SUSPEND ();
1711+ zend_async_waker_destroy (coroutine );
1712+
1713+ if (UNEXPECTED (EG (exception ))) {
1714+ return -1 ;
1715+ }
1716+
16771717 zval_ptr_dtor (& tmp_return_value );
16781718 zval_ptr_dtor (& tmp_return_buffer );
16791719
0 commit comments