Пример #1
0
static int coro_exit_handler(zend_execute_data *execute_data)
{
    zval ex;
    zend_object *obj;
    zend_long flags = 0;
    if (sw_get_current_cid() != -1)
    {
        flags |= SW_EXIT_IN_COROUTINE;
    }
    if (SwooleG.serv && SwooleG.serv->gs->start)
    {
        flags |= SW_EXIT_IN_SERVER;
    }
    if (flags)
    {
        const zend_op *opline = EX(opline);
        zval _exit_status;
        zval *exit_status = NULL;

        if (opline->op1_type != IS_UNUSED)
        {
            if (opline->op1_type == IS_CONST)
            {
                // see: https://github.com/php/php-src/commit/e70618aff6f447a298605d07648f2ce9e5a284f5
#ifdef EX_CONSTANT
                exit_status = EX_CONSTANT(opline->op1);
#else
                exit_status = RT_CONSTANT(opline, opline->op1);
#endif
            }
            else
            {
                exit_status = EX_VAR(opline->op1.var);
            }
            if (Z_ISREF_P(exit_status))
            {
                exit_status = Z_REFVAL_P(exit_status);
            }
        }
        else
        {
            exit_status = &_exit_status;
            ZVAL_NULL(exit_status);
        }
        obj = zend_throw_error_exception(swoole_exit_exception_class_entry_ptr, "swoole exit.", 0, E_ERROR TSRMLS_CC);
        ZVAL_OBJ(&ex, obj);
        zend_update_property_long(swoole_exit_exception_class_entry_ptr, &ex, ZEND_STRL("flags"), flags);
        Z_TRY_ADDREF_P(exit_status);
        zend_update_property(swoole_exit_exception_class_entry_ptr, &ex, ZEND_STRL("status"), exit_status);
    }

    return ZEND_USER_OPCODE_DISPATCH;
}
Пример #2
0
void 
ngx_php_error_cb(int type, 
    const char *error_filename, const uint error_lineno, const char *format, va_list args)
{
    TSRMLS_FETCH();
    char *buffer;
    int buffer_len, display;

    buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args);
    
    /* check for repeated errors to be ignored */
    if (PG(ignore_repeated_errors) && PG(last_error_message)) {
        /* no check for PG(last_error_file) is needed since it cannot
         * be NULL if PG(last_error_message) is not NULL */
        if (strcmp(PG(last_error_message), buffer)
            || (!PG(ignore_repeated_source)
                && ((PG(last_error_lineno) != (int)error_lineno)
                    || strcmp(PG(last_error_file), error_filename)))) {
            display = 1;
        } else {
            display = 0;
        }
    } else {
        display = 1;
    }

    /* store the error if it has changed */
    if (display) {
        if (PG(last_error_message)) {
            free(PG(last_error_message));
            PG(last_error_message) = NULL;
        }
        if (PG(last_error_file)) {
            free(PG(last_error_file));
            PG(last_error_file) = NULL;
        }
        if (!error_filename) {
            error_filename = "Unknown";
        }
        PG(last_error_type) = type;
        PG(last_error_message) = strdup(buffer);
        PG(last_error_file) = strdup(error_filename);
        PG(last_error_lineno) = error_lineno;
    }

    /* according to error handling mode, suppress error, throw exception or show it */
    if (EG(error_handling) != EH_NORMAL) {
        switch (type) {
            case E_ERROR:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
            case E_PARSE:
                /* fatal errors are real errors and cannot be made exceptions */
                break;
            case E_STRICT:
            case E_DEPRECATED:
            case E_USER_DEPRECATED:
                /* for the sake of BC to old damaged code */
                break;
            case E_NOTICE:
            case E_USER_NOTICE:
                /* notices are no errors and are not treated as such like E_WARNINGS */
                break;
            default:
                /* throw an exception if we are in EH_THROW mode
                 * but DO NOT overwrite a pending exception
                 */
                if (EG(error_handling) == EH_THROW && !EG(exception)) {
                    zend_throw_error_exception(EG(exception_class), buffer, 0, type TSRMLS_CC);
                }
                efree(buffer);
                return;
        }
    }

    /* display/log the error if necessary */
    if (display && (EG(error_reporting) & type || (type & E_CORE))
        && (PG(log_errors) || PG(display_errors) ) ) {

        char *error_type_str;

        switch (type) {
            case E_ERROR:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
                error_type_str = "Fatal error";
                break;
            case E_RECOVERABLE_ERROR:
                error_type_str = "Catchable fatal error";
                break;
            case E_WARNING:
            case E_CORE_WARNING:
            case E_COMPILE_WARNING:
            case E_USER_WARNING:
                error_type_str = "Warning";
                break;
            case E_PARSE:
                error_type_str = "Parse error";
                break;
            case E_NOTICE:
            case E_USER_NOTICE:
                error_type_str = "Notice";
                break;
            case E_STRICT:
                error_type_str = "Strict Standards";
                break;
            case E_DEPRECATED:
            case E_USER_DEPRECATED:
                error_type_str = "Deprecated";
                break;
            default:
                error_type_str = "Unknown error";
                break;
        }
        buffer_len = spprintf(&buffer, 0, "%s: %s in %s on line %d", error_type_str, buffer, error_filename, error_lineno);

        ngx_buf_t *b;
        ngx_http_php_rputs_chain_list_t *chain;
        ngx_http_php_ctx_t *ctx;
        ngx_http_request_t *r;
        u_char *u_str;
        ngx_str_t ns;

        r = ngx_php_request;
        ctx = ngx_http_get_module_ctx(r, ngx_http_php_module);

        if ( ctx == NULL ) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s", buffer);

            ngx_php_debug("ngx_php error handler, ctx is nil.");

            efree(buffer);
            zend_bailout();

            ngx_http_php_zend_uthread_exit(r);
            return ;
        }

        ns.data = (u_char *)buffer;
        ns.len = buffer_len;

        if (ctx->rputs_chain == NULL){
            chain = ngx_pcalloc(r->pool, sizeof(ngx_http_php_rputs_chain_list_t));
            chain->out = ngx_alloc_chain_link(r->pool);
            chain->last = &chain->out;
        }else {
            chain = ctx->rputs_chain;
            (*chain->last)->next = ngx_alloc_chain_link(r->pool);
            chain->last = &(*chain->last)->next;
        }

        b = ngx_calloc_buf(r->pool);
        (*chain->last)->buf = b;
        (*chain->last)->next = NULL;

        u_str = ngx_pstrdup(r->pool, &ns);
        //u_str[ns.len] = '\0';
        (*chain->last)->buf->pos = u_str;
        (*chain->last)->buf->last = u_str + ns.len;
        (*chain->last)->buf->memory = 1;
        ctx->rputs_chain = chain;
        ngx_http_set_ctx(r, ctx, ngx_http_php_module);

        if (r->headers_out.content_length_n == -1){
            r->headers_out.content_length_n += ns.len + 1;
        }else {
            r->headers_out.content_length_n += ns.len;
        }

        if (!r->headers_out.status) {
            r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s", buffer);

        ngx_php_debug("ngx_php error handler.");

        efree(buffer);
        zend_bailout();

        ngx_http_php_zend_uthread_exit(r);
        return ;
    }

    /* Log if necessary */
    if (!display) {
        efree(buffer);
        return;
    }

    efree(buffer);
}