3232#define php_v8_debug_execution (format, ...)
3333#endif
3434
35+ static inline void php_v8_isolate_limits_update_time_point (php_v8_isolate_limits_t *limits) {
36+ php_v8_debug_execution (" Updating time limits\n " );
37+
38+ std::chrono::milliseconds duration (static_cast <int64_t >(limits->time_limit * 1000 ));
39+ std::chrono::time_point<std::chrono::high_resolution_clock> from = std::chrono::high_resolution_clock::now ();
40+
41+ php_v8_debug_execution (" now: %.3f\n " , std::chrono::time_point_cast<std::chrono::milliseconds>(from).time_since_epoch ().count ()/1000.0 );
42+ php_v8_debug_execution (" old time point: %.3f\n " , std::chrono::time_point_cast<std::chrono::milliseconds>(limits->time_point ).time_since_epoch ().count ()/1000.0 );
43+
44+ limits->time_point = from + duration;
45+ php_v8_debug_execution (" new time point: %.3f\n " , std::chrono::time_point_cast<std::chrono::milliseconds>(limits->time_point ).time_since_epoch ().count ()/1000.0 );
46+ }
47+
48+ static inline void php_v8_isolate_limits_maybe_terminate_thread (php_v8_isolate_limits_t *limits) {
49+ if (!limits->active && limits->thread ) {
50+ limits->thread ->join ();
51+ delete limits->thread ;
52+ limits->thread = NULL ;
53+ }
54+ }
55+
3556static void php_v8_isolate_limits_interrupt_handler (v8::Isolate *isolate, void *data) {
3657 php_v8_isolate_t *php_v8_isolate = static_cast <php_v8_isolate_t *>(data);
3758 php_v8_isolate_limits_t *limits = &php_v8_isolate->limits ;
@@ -81,12 +102,17 @@ void php_v8_isolate_limits_thread(php_v8_isolate_t *php_v8_isolate) {
81102 limits->mutex ->lock ();
82103
83104 if (limits->active && limits->time_limit > 0 ) {
105+
84106 now = std::chrono::high_resolution_clock::now ();
85107
86108 if (now > limits->time_point ) {
109+ php_v8_debug_execution (" Time limit reached, terminating\n " );
110+ php_v8_debug_execution (" now: %.3f\n " , std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch ().count ()/1000.0 );
111+ php_v8_debug_execution (" time point: %.3f\n " , std::chrono::time_point_cast<std::chrono::milliseconds>(limits->time_point ).time_since_epoch ().count ()/1000.0 );
112+
113+ limits->time_limit_hit = true ;
87114 limits->active = false ;
88115 php_v8_isolate->isolate ->TerminateExecution ();
89- limits->time_limit_hit = true ;
90116 }
91117 }
92118
@@ -103,6 +129,8 @@ void php_v8_isolate_limits_thread(php_v8_isolate_t *php_v8_isolate) {
103129 limits->mutex ->unlock ();
104130
105131 if (!limits->active ) {
132+ php_v8_debug_execution (" Exit timer loop: %s, %s\n " , has (limits->mutex , " mutex" ), has (limits->thread , " thread" ));
133+ php_v8_debug_execution (" active: %s, depth: %d, time limit hit: %d, memory limit hit: %d\n " , is (limits->active ), limits->depth , limits->time_limit_hit , limits->memory_limit_hit );
106134 return ;
107135 }
108136
@@ -113,6 +141,8 @@ void php_v8_isolate_limits_thread(php_v8_isolate_t *php_v8_isolate) {
113141void php_v8_isolate_limits_maybe_start_timer (php_v8_isolate_t *php_v8_isolate) {
114142 php_v8_isolate_limits_t *limits = &php_v8_isolate->limits ;
115143
144+ php_v8_debug_execution (" Maybe start timer: %d, %s, %s\n " , limits->depth , has (limits->mutex , " mutex" ), has (limits->thread , " thread" ));
145+
116146 assert (limits->depth < UINT32_MAX);
117147
118148 if (!limits->mutex ) {
@@ -124,10 +154,14 @@ void php_v8_isolate_limits_maybe_start_timer(php_v8_isolate_t *php_v8_isolate) {
124154 limits->depth ++;
125155
126156 if (limits->active && !limits->thread ) {
157+ php_v8_isolate_limits_update_time_point (limits);
158+
159+ php_v8_debug_execution (" start timer\n " );
127160 limits->thread = new std::thread (php_v8_isolate_limits_thread, php_v8_isolate);
128161 }
129162}
130163
164+
131165void php_v8_isolate_limits_maybe_stop_timer (php_v8_isolate_t *php_v8_isolate) {
132166 php_v8_isolate_limits_t *limits = &php_v8_isolate->limits ;
133167
@@ -172,6 +206,8 @@ void php_v8_isolate_limits_free(php_v8_isolate_t *php_v8_isolate) {
172206 if (limits->mutex ) {
173207 delete limits->mutex ;
174208 }
209+
210+ limits->time_point .~time_point ();
175211}
176212
177213void php_v8_isolate_limits_ctor (php_v8_isolate_t *php_v8_isolate) {
@@ -180,13 +216,15 @@ void php_v8_isolate_limits_ctor(php_v8_isolate_t *php_v8_isolate) {
180216 limits->thread = NULL ;
181217 limits->mutex = NULL ;
182218 limits->depth = 0 ;
219+
220+ new (&limits->time_point ) std::chrono::time_point<std::chrono::high_resolution_clock>();
183221}
184222
185223void php_v8_isolate_limits_set_time_limit (php_v8_isolate_t *php_v8_isolate, double time_limit_in_seconds) {
186224 PHP_V8_DECLARE_ISOLATE (php_v8_isolate);
187225 PHP_V8_DECLARE_LIMITS (php_v8_isolate);
188226
189- assert (time_limit_in_seconds >=0 );
227+ assert (time_limit_in_seconds >= 0 );
190228
191229 v8::Locker locker (isolate);
192230
@@ -196,28 +234,30 @@ void php_v8_isolate_limits_set_time_limit(php_v8_isolate_t *php_v8_isolate, doub
196234
197235 limits->mutex ->lock ();
198236
199- std::chrono::milliseconds duration (static_cast <int64_t >(time_limit_in_seconds * 1000 ));
200- std::chrono::time_point<std::chrono::high_resolution_clock> from = std::chrono::high_resolution_clock::now ();
201-
237+ php_v8_debug_execution (" Setting time limits, new limit: %f, old limit: %f, time_limit_hit: %s\n " , time_limit_in_seconds, limits->time_limit , is (limits->time_limit_hit ));
202238 limits->time_limit = time_limit_in_seconds;
203- limits->time_point = from + duration;
204- limits->time_limit_hit = false ;
239+ php_v8_isolate_limits_update_time_point (limits);
240+
241+ if (limits->time_limit_hit ) {
242+ php_v8_debug_execution (" trying to recover from time limit hit, active: %s\n " , is (limits->active ));
243+
244+ isolate->CancelTerminateExecution ();
245+
246+ php_v8_isolate_limits_maybe_terminate_thread (limits);
247+ limits->time_limit_hit = false ;
248+ }
205249
206250 limits->active = (limits->time_limit > 0 || limits->memory_limit > 0 )
207251 && !limits->time_limit_hit
208252 && !limits->memory_limit_hit ;
209253
210254 if (limits->active && limits->depth && !limits->thread ) {
255+ php_v8_debug_execution (" Restart timer: %d, %s, %s\n " , limits->depth , has (limits->memory_limit_hit , " memory limit hit" ), has (limits->time_limit_hit , " time limit hit" ));
211256 limits->thread = new std::thread (php_v8_isolate_limits_thread, php_v8_isolate);
212257 }
213258
214259 limits->mutex ->unlock ();
215-
216- if (!limits->active && limits->thread ) {
217- limits->thread ->join ();
218- delete limits->thread ;
219- limits->thread = NULL ;
220- }
260+ php_v8_isolate_limits_maybe_terminate_thread (limits);
221261}
222262
223263void php_v8_isolate_limits_set_memory_limit (php_v8_isolate_t *php_v8_isolate, size_t memory_limit_in_bytes) {
@@ -232,22 +272,27 @@ void php_v8_isolate_limits_set_memory_limit(php_v8_isolate_t *php_v8_isolate, si
232272
233273 limits->mutex ->lock ();
234274
275+ php_v8_debug_execution (" Updating memory limits, memory_limit_hit: %s\n " , is (limits->memory_limit_hit ));
235276 limits->memory_limit = memory_limit_in_bytes;
236- limits->memory_limit_hit = false ;
277+
278+ if (limits->memory_limit_hit ) {
279+ php_v8_debug_execution (" trying to recover from memory limit hit, active: %s\n " , is (limits->active ));
280+
281+ isolate->CancelTerminateExecution ();
282+
283+ php_v8_isolate_limits_maybe_terminate_thread (limits);
284+ limits->memory_limit_hit = false ;
285+ }
237286
238287 limits->active = (limits->time_limit > 0 || limits->memory_limit > 0 )
239288 && !limits->time_limit_hit
240289 && !limits->memory_limit_hit ;
241290
242291 if (limits->active && limits->depth && !limits->thread ) {
292+ php_v8_debug_execution (" Restart timer: %d, %s, %s\n " , limits->depth , has (limits->memory_limit_hit , " memory limit hit" ), has (limits->time_limit_hit , " time limit hit" ));
243293 limits->thread = new std::thread (php_v8_isolate_limits_thread, php_v8_isolate);
244294 }
245295
246296 limits->mutex ->unlock ();
247-
248- if (!limits->active && limits->thread ) {
249- limits->thread ->join ();
250- delete limits->thread ;
251- limits->thread = NULL ;
252- }
297+ php_v8_isolate_limits_maybe_terminate_thread (limits);
253298}
0 commit comments