ZEND_API FILE *(*zend_fopen)(const char *filename, zend_string **opened_path);
ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle);
ZEND_API void (*zend_ticks_function)(int ticks);
+ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data);
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
size_t (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
zend_getenv = utility_functions->getenv_function;
zend_resolve_path = utility_functions->resolve_path_function;
+ zend_interrupt_function = NULL;
+
#if HAVE_DTRACE
/* build with dtrace support */
zend_compile_file = dtrace_compile_file;
extern ZEND_API zend_write_func_t zend_write;
extern ZEND_API FILE *(*zend_fopen)(const char *filename, zend_string **opened_path);
extern ZEND_API void (*zend_ticks_function)(int ticks);
+extern ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data);
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
extern ZEND_API void (*zend_on_timeout)(int seconds);
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle);
}
/* }}} */
-static zend_never_inline ZEND_COLD ZEND_NORETURN void ZEND_FASTCALL zend_interrupt(void) /* {{{ */
-{
- zend_timeout(0);
-}
-/* }}} */
-
#define ZEND_VM_INTERRUPT_CHECK() do { \
- if (UNEXPECTED(EG(timed_out))) { \
- zend_interrupt(); \
+ if (UNEXPECTED(EG(vm_interrupt))) { \
+ ZEND_VM_INTERRUPT(); \
} \
} while (0)
zend_objects_store_init(&EG(objects_store), 1024);
EG(full_tables_cleanup) = 0;
+ EG(vm_interrupt) = 0;
EG(timed_out) = 0;
EG(exception) = NULL;
}
EG(timed_out) = 1;
+ EG(vm_interrupt) = 1;
#ifndef ZTS
if (EG(hard_timeout) > 0) {
#ifdef ZEND_WIN32
VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
{
- zend_bool *php_timed_out;
+ zend_executor_globals *eg;
/* The doc states it'll be always true, however it theoretically
could be FALSE when the thread was signaled. */
return;
}
- php_timed_out = (zend_bool *)arg;
- *php_timed_out = 1;
+ eg = (zend_bool *)arg;
+ eg->timed_out = 1;
+ eg->vm_interrupt = 1;
}
#endif
static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
{
+ zend_execute_data *eg;
#ifdef ZEND_WIN32
if(!seconds) {
}
/* XXX passing NULL means the default timer queue provided by the system is used */
- if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) {
+#ifndef ZTS
+ eg = &execute_data;
+#elif defined(ZEND_ENABLE_STATIC_TSRMLS_CACHE)
+ eg = TSRMG_BULK_STATIC(executor_globals_id, zend_executor_globals *)
+#else
+ eg = TSRMG_BULK(executor_globals_id, zend_executor_globals *)
+#endif
+ if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)eg, seconds*1000, 0, WT_EXECUTEONLYONCE)) {
tq_timer = NULL;
zend_error_noreturn(E_ERROR, "Could not queue new timer");
return;
/* for extended information support */
zend_bool no_extensions;
+ zend_bool vm_interrupt;
zend_bool timed_out;
zend_long hard_timeout;
}
ZEND_VM_DEFINE_OP(137, ZEND_OP_DATA);
+
+ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)
+{
+ EG(vm_interrupt) = 0;
+ if (EG(timed_out)) {
+ zend_timeout(0);
+ } else if (zend_interrupt_function) {
+ SAVE_OPLINE();
+ zend_interrupt_function(execute_data);
+ LOAD_OPLINE();
+ }
+ ZEND_VM_CONTINUE();
+}
# define ZEND_VM_ENTER() return 1
# define ZEND_VM_LEAVE() return 2
#endif
+#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS);
ZEND_API void execute_ex(zend_execute_data *ex)
{
ZEND_VM_LEAVE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
+{
+ EG(vm_interrupt) = 0;
+ if (EG(timed_out)) {
+ zend_timeout(0);
+ } else if (zend_interrupt_function) {
+ SAVE_OPLINE();
+ zend_interrupt_function(execute_data);
+ LOAD_OPLINE();
+ }
+ ZEND_VM_CONTINUE();
+}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
ZEND_VM_NEXT_OPCODE();
}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
ZEND_VM_NEXT_OPCODE();
}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
ZEND_VM_NEXT_OPCODE();
}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
ZEND_VM_NEXT_OPCODE();
}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
out($f,"# define ZEND_VM_ENTER() return 1\n");
out($f,"# define ZEND_VM_LEAVE() return 2\n");
out($f,"#endif\n");
+ out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
out($f,"\n");
+ out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);");
+ out($f,"\n");
break;
case ZEND_VM_KIND_SWITCH:
out($f,"\n");
out($f,"#define ZEND_VM_RETURN() return\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
+ out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n");
out($f,"\n");
break;
out($f,"#define ZEND_VM_RETURN() return\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
+ out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n");
out($f,"\n");
break;
out($f,"#define ZEND_VM_RETURN() return -1\n");
out($f,"#define ZEND_VM_ENTER() return 1\n");
out($f,"#define ZEND_VM_LEAVE() return 2\n");
+ out($f,"#define ZEND_VM_INTERRUPT() return zend_interrupt_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");
out($f,"\n");
}