You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

707 lines
18 KiB

27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2000 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 0.92 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.zend.com/license/0_92.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@zend.com> |
  16. | Zeev Suraski <zeev@zend.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #include <stdio.h>
  20. #include <signal.h>
  21. #include "zend.h"
  22. #include "zend_compile.h"
  23. #include "zend_execute.h"
  24. #include "zend_API.h"
  25. #include "zend_ptr_stack.h"
  26. #include "zend_constants.h"
  27. #include "zend_extensions.h"
  28. #include "zend_execute_locks.h"
  29. #if HAVE_SYS_TIME_H
  30. #include <sys/time.h>
  31. #endif
  32. ZEND_API void (*zend_execute)(zend_op_array *op_array ELS_DC);
  33. #ifdef ZEND_WIN32
  34. #include <process.h>
  35. /* true global */
  36. static WNDCLASS wc;
  37. static HWND timeout_window;
  38. static HANDLE timeout_thread_event;
  39. static DWORD timeout_thread_id;
  40. static int timeout_thread_initialized=0;
  41. #endif
  42. #if ZEND_DEBUG
  43. static void (*original_sigsegv_handler)(int);
  44. static void zend_handle_sigsegv(int dummy)
  45. {
  46. fflush(stdout);
  47. fflush(stderr);
  48. if (original_sigsegv_handler==zend_handle_sigsegv) {
  49. signal(SIGSEGV, original_sigsegv_handler);
  50. } else {
  51. signal(SIGSEGV, SIG_DFL);
  52. }
  53. {
  54. ELS_FETCH();
  55. fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
  56. active_opline->opcode,
  57. active_opline-EG(active_op_array)->opcodes,
  58. get_active_function_name(),
  59. zend_get_executed_filename(ELS_C),
  60. zend_get_executed_lineno(ELS_C));
  61. }
  62. if (original_sigsegv_handler!=zend_handle_sigsegv) {
  63. original_sigsegv_handler(dummy);
  64. }
  65. }
  66. #endif
  67. static void zend_extension_activator(zend_extension *extension)
  68. {
  69. if (extension->activate) {
  70. extension->activate();
  71. }
  72. }
  73. static void zend_extension_deactivator(zend_extension *extension)
  74. {
  75. if (extension->deactivate) {
  76. extension->deactivate();
  77. }
  78. }
  79. static int is_not_internal_function(zend_function *function)
  80. {
  81. return(function->type != ZEND_INTERNAL_FUNCTION);
  82. }
  83. static int is_not_internal_class(zend_class_entry *ce)
  84. {
  85. return(ce->type != ZEND_INTERNAL_CLASS);
  86. }
  87. void init_executor(CLS_D ELS_DC)
  88. {
  89. INIT_ZVAL(EG(uninitialized_zval));
  90. INIT_ZVAL(EG(error_zval));
  91. EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);
  92. EG(error_zval_ptr)=&EG(error_zval);
  93. zend_ptr_stack_init(&EG(arg_types_stack));
  94. /* destroys stack frame, therefore makes core dumps worthless */
  95. #if 0&&ZEND_DEBUG
  96. original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
  97. #endif
  98. EG(return_value_ptr_ptr) = &EG(global_return_value_ptr);
  99. EG(global_return_value_ptr) = NULL;
  100. EG(symtable_cache_ptr) = EG(symtable_cache)-1;
  101. EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1;
  102. EG(no_extensions)=0;
  103. EG(function_table) = CG(function_table);
  104. EG(class_table) = CG(class_table);
  105. EG(in_execution) = 0;
  106. zend_ptr_stack_init(&EG(argument_stack));
  107. zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
  108. EG(active_symbol_table) = &EG(symbol_table);
  109. zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_activator);
  110. EG(opline_ptr) = NULL;
  111. EG(garbage_ptr) = 0;
  112. zend_hash_init(&EG(included_files), 5, NULL, NULL, 0);
  113. EG(ticks_count) = 0;
  114. EG(user_error_handler) = NULL;
  115. zend_ptr_stack_init(&EG(user_error_handlers));
  116. EG(orig_error_reporting) = EG(error_reporting);
  117. #ifdef ZEND_WIN32
  118. EG(timed_out) = 0;
  119. #endif
  120. }
  121. void shutdown_executor(ELS_D)
  122. {
  123. zend_ptr_stack_destroy(&EG(arg_types_stack));
  124. while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
  125. zend_hash_destroy(*EG(symtable_cache_ptr));
  126. efree(*EG(symtable_cache_ptr));
  127. EG(symtable_cache_ptr)--;
  128. }
  129. zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_deactivator);
  130. zend_hash_destroy(&EG(symbol_table));
  131. while (EG(garbage_ptr)--) {
  132. if (EG(garbage)[EG(garbage_ptr)]->refcount==1) {
  133. zval_ptr_dtor(&EG(garbage)[EG(garbage_ptr)]);
  134. }
  135. }
  136. zend_ptr_stack_destroy(&EG(argument_stack));
  137. /* Destroy all op arrays */
  138. zend_hash_apply(EG(function_table), (int (*)(void *)) is_not_internal_function);
  139. zend_hash_apply(EG(class_table), (int (*)(void *)) is_not_internal_class);
  140. zend_destroy_rsrc_list(ELS_C); /* must be destroyed after the main symbol table and
  141. * op arrays are destroyed.
  142. */
  143. clean_non_persistent_constants();
  144. #if ZEND_DEBUG
  145. signal(SIGSEGV, original_sigsegv_handler);
  146. #endif
  147. zend_hash_destroy(&EG(included_files));
  148. if (EG(user_error_handler)) {
  149. zval_dtor(EG(user_error_handler));
  150. FREE_ZVAL(EG(user_error_handler));
  151. }
  152. zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
  153. zend_ptr_stack_destroy(&EG(user_error_handlers));
  154. EG(error_reporting) = EG(orig_error_reporting);
  155. }
  156. ZEND_API char *get_active_function_name()
  157. {
  158. ELS_FETCH();
  159. switch(EG(function_state_ptr)->function->type) {
  160. case ZEND_USER_FUNCTION: {
  161. char *function_name = ((zend_op_array *) EG(function_state_ptr)->function)->function_name;
  162. if (function_name) {
  163. return function_name;
  164. } else {
  165. return "main";
  166. }
  167. }
  168. break;
  169. case ZEND_INTERNAL_FUNCTION:
  170. return ((zend_internal_function *) EG(function_state_ptr)->function)->function_name;
  171. break;
  172. default:
  173. return NULL;
  174. }
  175. }
  176. ZEND_API char *zend_get_executed_filename(ELS_D)
  177. {
  178. if (EG(active_op_array)) {
  179. return EG(active_op_array)->filename;
  180. } else {
  181. return "[no active file]";
  182. }
  183. }
  184. ZEND_API uint zend_get_executed_lineno(ELS_D)
  185. {
  186. if (EG(opline_ptr)) {
  187. return active_opline->lineno;
  188. } else {
  189. return 0;
  190. }
  191. }
  192. ZEND_API zend_bool zend_is_executing()
  193. {
  194. ELS_FETCH();
  195. return EG(in_execution);
  196. }
  197. ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC)
  198. {
  199. #if DEBUG_ZEND>=2
  200. printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, (*zval_ptr)->refcount, (*zval_ptr)->refcount-1);
  201. #endif
  202. (*zval_ptr)->refcount--;
  203. if ((*zval_ptr)->refcount==0) {
  204. zval_dtor(*zval_ptr);
  205. safe_free_zval_ptr(*zval_ptr);
  206. } else if (((*zval_ptr)->refcount == 1) && ((*zval_ptr)->type != IS_OBJECT)) {
  207. (*zval_ptr)->is_ref = 0;
  208. }
  209. }
  210. ZEND_API int zend_is_true(zval *op)
  211. {
  212. return i_zend_is_true(op);
  213. }
  214. ZEND_API int zval_update_constant(zval **pp, void *arg)
  215. {
  216. zval *p = *pp;
  217. zend_bool inline_change = (zend_bool) (unsigned long) arg;
  218. if (p->type == IS_CONSTANT) {
  219. zval c;
  220. int refcount;
  221. SEPARATE_ZVAL(pp);
  222. p = *pp;
  223. refcount = p->refcount;
  224. if (!zend_get_constant(p->value.str.val, p->value.str.len, &c)) {
  225. zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
  226. p->value.str.val,
  227. p->value.str.val);
  228. p->type = IS_STRING;
  229. if (!inline_change) {
  230. zval_copy_ctor(p);
  231. }
  232. } else {
  233. if (inline_change) {
  234. STR_FREE(p->value.str.val);
  235. }
  236. *p = c;
  237. }
  238. INIT_PZVAL(p);
  239. p->refcount = refcount;
  240. } else if (p->type == IS_CONSTANT_ARRAY) {
  241. SEPARATE_ZVAL(pp);
  242. p = *pp;
  243. p->type = IS_ARRAY;
  244. zend_hash_apply_with_argument(p->value.ht, (int (*)(void *,void *)) zval_update_constant, (void *) 1);
  245. }
  246. return 0;
  247. }
  248. int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, int param_count, zval *params[])
  249. {
  250. zval ***params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
  251. int i;
  252. int ex_retval;
  253. zval *local_retval_ptr;
  254. for (i=0; i<param_count; i++) {
  255. params_array[i] = &params[i];
  256. }
  257. ex_retval = call_user_function_ex(function_table, object, function_name, &local_retval_ptr, param_count, params_array, 1, NULL);
  258. if (local_retval_ptr) {
  259. COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
  260. } else {
  261. INIT_ZVAL(*retval_ptr);
  262. }
  263. efree(params_array);
  264. return ex_retval;
  265. }
  266. int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table)
  267. {
  268. int i;
  269. zval **original_return_value;
  270. HashTable *calling_symbol_table;
  271. zend_function_state function_state;
  272. zend_function_state *original_function_state_ptr;
  273. zend_op_array *original_op_array;
  274. zend_op **original_opline_ptr;
  275. ELS_FETCH();
  276. *retval_ptr_ptr = NULL;
  277. if (function_name->type==IS_ARRAY) { /* assume array($obj, $name) couple */
  278. zval **tmp_object_ptr, **tmp_real_function_name;
  279. if (zend_hash_index_find(function_name->value.ht, 0, (void **) &tmp_object_ptr)==FAILURE) {
  280. return FAILURE;
  281. }
  282. if (zend_hash_index_find(function_name->value.ht, 1, (void **) &tmp_real_function_name)==FAILURE) {
  283. return FAILURE;
  284. }
  285. function_name = *tmp_real_function_name;
  286. SEPARATE_ZVAL_IF_NOT_REF(tmp_object_ptr);
  287. object = *tmp_object_ptr;
  288. object->is_ref = 1;
  289. }
  290. if (object) {
  291. if (object->type != IS_OBJECT) {
  292. return FAILURE;
  293. }
  294. function_table = &object->value.obj.ce->function_table;
  295. }
  296. if (function_name->type!=IS_STRING) {
  297. return FAILURE;
  298. }
  299. original_function_state_ptr = EG(function_state_ptr);
  300. zend_str_tolower(function_name->value.str.val, function_name->value.str.len);
  301. if (zend_hash_find(function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function_state.function)==FAILURE) {
  302. return FAILURE;
  303. }
  304. for (i=0; i<param_count; i++) {
  305. zval *param;
  306. if (function_state.function->common.arg_types
  307. && i<function_state.function->common.arg_types[0]
  308. && function_state.function->common.arg_types[i+1]==BYREF_FORCE
  309. && !PZVAL_IS_REF(*params[i])) {
  310. if ((*params[i])->refcount>1) {
  311. zval *new_zval;
  312. if (no_separation) {
  313. return FAILURE;
  314. }
  315. ALLOC_ZVAL(new_zval);
  316. *new_zval = **params[i];
  317. zval_copy_ctor(new_zval);
  318. new_zval->refcount = 1;
  319. (*params[i])->refcount--;
  320. *params[i] = new_zval;
  321. }
  322. (*params[i])->refcount++;
  323. (*params[i])->is_ref = 1;
  324. param = *params[i];
  325. } else if (*params[i] != &EG(uninitialized_zval)) {
  326. (*params[i])->refcount++;
  327. param = *params[i];
  328. } else {
  329. ALLOC_ZVAL(param);
  330. *param = **(params[i]);
  331. INIT_PZVAL(param);
  332. }
  333. zend_ptr_stack_push(&EG(argument_stack), param);
  334. }
  335. zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL);
  336. if (function_state.function->type == ZEND_USER_FUNCTION) {
  337. calling_symbol_table = EG(active_symbol_table);
  338. if (symbol_table) {
  339. EG(active_symbol_table) = symbol_table;
  340. } else {
  341. ALLOC_HASHTABLE(EG(active_symbol_table));
  342. zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
  343. }
  344. if (object) {
  345. zval *dummy, **this_ptr;
  346. ALLOC_ZVAL(dummy);
  347. INIT_ZVAL(*dummy);
  348. zend_hash_update(EG(active_symbol_table), "this", sizeof("this"), &dummy, sizeof(zval *), (void **) &this_ptr);
  349. zend_assign_to_variable_reference(NULL, this_ptr, &object, NULL ELS_CC);
  350. }
  351. original_return_value = EG(return_value_ptr_ptr);
  352. original_op_array = EG(active_op_array);
  353. EG(return_value_ptr_ptr) = retval_ptr_ptr;
  354. EG(active_op_array) = (zend_op_array *) function_state.function;
  355. original_opline_ptr = EG(opline_ptr);
  356. zend_execute(EG(active_op_array) ELS_CC);
  357. if (!symbol_table) {
  358. zend_hash_destroy(EG(active_symbol_table));
  359. FREE_HASHTABLE(EG(active_symbol_table));
  360. }
  361. EG(active_symbol_table) = calling_symbol_table;
  362. EG(active_op_array) = original_op_array;
  363. EG(return_value_ptr_ptr)=original_return_value;
  364. EG(opline_ptr) = original_opline_ptr;
  365. } else {
  366. ALLOC_INIT_ZVAL(*retval_ptr_ptr);
  367. ((zend_internal_function *) function_state.function)->handler(param_count, *retval_ptr_ptr, object, 1 ELS_CC);
  368. INIT_PZVAL(*retval_ptr_ptr);
  369. }
  370. zend_ptr_stack_clear_multiple(ELS_C);
  371. EG(function_state_ptr) = original_function_state_ptr;
  372. return SUCCESS;
  373. }
  374. ZEND_API int zend_eval_string(char *str, zval *retval_ptr CLS_DC ELS_DC)
  375. {
  376. zval pv;
  377. zend_op_array *new_op_array;
  378. zend_op_array *original_active_op_array = EG(active_op_array);
  379. zend_function_state *original_function_state_ptr = EG(function_state_ptr);
  380. int original_handle_op_arrays;
  381. int retval;
  382. if (retval_ptr) {
  383. pv.value.str.len = strlen(str)+sizeof("return ;")-1;
  384. pv.value.str.val = emalloc(pv.value.str.len+1);
  385. strcpy(pv.value.str.val, "return ");
  386. strcat(pv.value.str.val, str);
  387. strcat(pv.value.str.val, " ;");
  388. } else {
  389. pv.value.str.len = strlen(str);
  390. pv.value.str.val = estrndup(str, pv.value.str.len);
  391. }
  392. pv.type = IS_STRING;
  393. /*printf("Evaluating '%s'\n", pv.value.str.val);*/
  394. original_handle_op_arrays = CG(handle_op_arrays);
  395. CG(handle_op_arrays) = 0;
  396. new_op_array = compile_string(&pv CLS_CC);
  397. CG(handle_op_arrays) = original_handle_op_arrays;
  398. if (new_op_array) {
  399. zval *local_retval_ptr=NULL;
  400. zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
  401. zend_op **original_opline_ptr = EG(opline_ptr);
  402. EG(return_value_ptr_ptr) = &local_retval_ptr;
  403. EG(active_op_array) = new_op_array;
  404. EG(no_extensions)=1;
  405. zend_execute(new_op_array ELS_CC);
  406. if (local_retval_ptr) {
  407. if (retval_ptr) {
  408. COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
  409. } else {
  410. zval_ptr_dtor(&local_retval_ptr);
  411. }
  412. } else {
  413. if (retval_ptr) {
  414. INIT_ZVAL(*retval_ptr);
  415. }
  416. }
  417. EG(no_extensions)=0;
  418. EG(opline_ptr) = original_opline_ptr;
  419. EG(active_op_array) = original_active_op_array;
  420. EG(function_state_ptr) = original_function_state_ptr;
  421. destroy_op_array(new_op_array);
  422. efree(new_op_array);
  423. EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
  424. retval = SUCCESS;
  425. } else {
  426. retval = FAILURE;
  427. }
  428. zval_dtor(&pv);
  429. return retval;
  430. }
  431. #if SUPPORT_INTERACTIVE
  432. void execute_new_code(CLS_D)
  433. {
  434. ELS_FETCH();
  435. if (!EG(interactive)
  436. || CG(active_op_array)->backpatch_count>0
  437. || CG(active_op_array)->function_name
  438. || CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
  439. return;
  440. }
  441. CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number;
  442. CG(active_op_array)->end_op_number = CG(active_op_array)->last;
  443. EG(active_op_array) = CG(active_op_array);
  444. zend_execute(CG(active_op_array) ELS_CC);
  445. CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number;
  446. }
  447. #endif
  448. ZEND_API void zend_timeout(int dummy)
  449. {
  450. ELS_FETCH();
  451. /* is there any point in this? we're terminating the request anyway...
  452. PLS_FETCH();
  453. PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
  454. */
  455. zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded",
  456. EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
  457. }
  458. #ifdef ZEND_WIN32
  459. static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  460. {
  461. switch (message) {
  462. case WM_DESTROY:
  463. PostQuitMessage(0);
  464. break;
  465. case WM_REGISTER_ZEND_TIMEOUT:
  466. /* wParam is the thread id pointer, lParam is the timeout amount in seconds */
  467. if (lParam==0) {
  468. KillTimer(timeout_window, wParam);
  469. } else {
  470. SetTimer(timeout_window, wParam, lParam*1000, NULL);
  471. }
  472. break;
  473. case WM_UNREGISTER_ZEND_TIMEOUT:
  474. /* wParam is the thread id pointer */
  475. KillTimer(timeout_window, wParam);
  476. break;
  477. case WM_TIMER: {
  478. #ifdef ZTS
  479. zend_executor_globals *executor_globals;
  480. executor_globals = ts_resource_ex(executor_globals_id, &wParam);
  481. if (!executor_globals) {
  482. /* Thread died before receiving its timeout? */
  483. break;
  484. }
  485. #endif
  486. KillTimer(timeout_window, wParam);
  487. EG(timed_out) = 1;
  488. }
  489. break;
  490. default:
  491. return DefWindowProc(hWnd,message,wParam,lParam);
  492. }
  493. return 0;
  494. }
  495. static unsigned __stdcall timeout_thread_proc(void *pArgs)
  496. {
  497. MSG message;
  498. wc.style=0;
  499. wc.lpfnWndProc = zend_timeout_WndProc;
  500. wc.cbClsExtra=0;
  501. wc.cbWndExtra=0;
  502. wc.hInstance=NULL;
  503. wc.hIcon=NULL;
  504. wc.hCursor=NULL;
  505. wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5);
  506. wc.lpszMenuName=NULL;
  507. wc.lpszClassName = "Zend Timeout Window";
  508. if(!RegisterClass(&wc)) {
  509. return -1;
  510. }
  511. timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
  512. SetEvent(timeout_thread_event);
  513. while (GetMessage(&message, NULL, 0, 0)) {
  514. SendMessage(timeout_window, message.message, message.wParam, message.lParam);
  515. if (message.message == WM_QUIT) {
  516. break;
  517. }
  518. }
  519. DestroyWindow(timeout_window);
  520. UnregisterClass(wc.lpszClassName, NULL);
  521. return 0;
  522. }
  523. void zend_init_timeout_thread()
  524. {
  525. timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  526. _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id);
  527. WaitForSingleObject(timeout_thread_event, INFINITE);
  528. }
  529. void zend_shutdown_timeout_thread()
  530. {
  531. if (!timeout_thread_initialized) {
  532. return;
  533. }
  534. PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0);
  535. }
  536. #endif
  537. /* This one doesn't exists on QNX */
  538. #ifndef SIGPROF
  539. #define SIGPROF 27
  540. #endif
  541. void zend_set_timeout(long seconds)
  542. {
  543. ELS_FETCH();
  544. EG(timeout_seconds) = seconds;
  545. #ifdef ZEND_WIN32
  546. if (timeout_thread_initialized==0 && InterlockedIncrement(&timeout_thread_initialized)==1) {
  547. /* We start up this process-wide thread here and not in zend_startup(), because if Zend
  548. * is initialized inside a DllMain(), you're not supposed to start threads from it.
  549. */
  550. zend_init_timeout_thread();
  551. }
  552. PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds);
  553. #else
  554. # ifdef HAVE_SETITIMER
  555. {
  556. struct itimerval t_r; /* timeout requested */
  557. sigset_t sigset;
  558. t_r.it_value.tv_sec = seconds;
  559. t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
  560. setitimer(ITIMER_PROF, &t_r, NULL);
  561. signal(SIGPROF, zend_timeout);
  562. sigemptyset(&sigset);
  563. sigaddset(&sigset, SIGPROF);
  564. sigprocmask(SIG_UNBLOCK,&sigset,NULL);
  565. }
  566. # endif
  567. #endif
  568. }
  569. void zend_unset_timeout(void)
  570. {
  571. ELS_FETCH();
  572. #ifdef ZEND_WIN32
  573. PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);
  574. #else
  575. # ifdef HAVE_SETITIMER
  576. {
  577. struct itimerval no_timeout;
  578. no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
  579. setitimer(ITIMER_PROF, &no_timeout, NULL);
  580. }
  581. # endif
  582. #endif
  583. }