The event loop blocking while an exception is thrown in the callback.

Issue #43 resolved
Former user created an issue

if no exception

$timer = new \EvTimer(1, 1, function () {
    var_dump("invoke timer.");
});

output: string(13) "invoke timer." string(13) "invoke timer." string(13) "invoke timer." ....

If repeat is 0:

$timer = new \EvTimer(1, 0, function () {
    var_dump("invoke timer.");
});

The exception information will be output in console.

BUT if repeat is not 0

$timer = new \EvTimer(1, 0, function () {
    throw new Exception("throw new exception.");
});

The event loop or process will be blocked.

Comments (3)

  1. Ruslan Osmanov repo owner

    The problem is here in the watcher callback:

            zend_exception_save();
            if (retval) {
                zval_ptr_dtor(retval);
                retval = NULL;
            }
            zend_exception_restore();
    

    We should probably stop the loop if there is an exception, e.g.

            if (EG(exception)) {
                /* TODO: Maybe throw an exception like EvLoopStoppedException? */
                php_error_docref(NULL, E_ERROR, "Stopping the loop because of exception");
    
                PHP_EV_EXIT_LOOP(EV_A);
                /* TODO: stop non-default loops as well */
            }
    

    🤔

  2. Ruslan Osmanov repo owner

    Ah, it should be enough to stop the watcher 🙂

    diff --git a/php7/watcher.c b/php7/watcher.c
    index 0cb4f15..ec03f9b 100644
    --- a/php7/watcher.c
    +++ b/php7/watcher.c
    @@ -58,6 +58,15 @@ void php_ev_watcher_callback(EV_P_ ev_watcher *watcher, int revents)
                            retval = NULL;
                    }
                    zend_exception_restore();
    +
    +               if (EG(exception)) {
    +                       php_error_docref(NULL, E_ERROR,
    +                                       "Stopping %s watcher because of uncaught exception",
    +                                       ZSTR_VAL(Z_OBJCE_P(&php_ev_watcher_self(watcher))->name));
    +                       php_ev_stop_watcher(watcher);
    +
    +                       zend_exception_error(EG(exception), E_ERROR);
    +               }
            }
     }
     /* }}} */
    

    I’ll test it and upload a new package. In the meantime, you can test it yourself, dear reporter.

    It would be better if you filed the bug as a user. I think I’ll disable anonymous bugs.

  3. Log in to comment