32
32
#define php_v8_debug_execution (format, ...)
33
33
#endif
34
34
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
+
35
56
static void php_v8_isolate_limits_interrupt_handler (v8::Isolate *isolate, void *data) {
36
57
php_v8_isolate_t *php_v8_isolate = static_cast <php_v8_isolate_t *>(data);
37
58
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) {
81
102
limits->mutex ->lock ();
82
103
83
104
if (limits->active && limits->time_limit > 0 ) {
105
+
84
106
now = std::chrono::high_resolution_clock::now ();
85
107
86
108
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 ;
87
114
limits->active = false ;
88
115
php_v8_isolate->isolate ->TerminateExecution ();
89
- limits->time_limit_hit = true ;
90
116
}
91
117
}
92
118
@@ -103,6 +129,8 @@ void php_v8_isolate_limits_thread(php_v8_isolate_t *php_v8_isolate) {
103
129
limits->mutex ->unlock ();
104
130
105
131
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 );
106
134
return ;
107
135
}
108
136
@@ -113,6 +141,8 @@ void php_v8_isolate_limits_thread(php_v8_isolate_t *php_v8_isolate) {
113
141
void php_v8_isolate_limits_maybe_start_timer (php_v8_isolate_t *php_v8_isolate) {
114
142
php_v8_isolate_limits_t *limits = &php_v8_isolate->limits ;
115
143
144
+ php_v8_debug_execution (" Maybe start timer: %d, %s, %s\n " , limits->depth , has (limits->mutex , " mutex" ), has (limits->thread , " thread" ));
145
+
116
146
assert (limits->depth < UINT32_MAX);
117
147
118
148
if (!limits->mutex ) {
@@ -124,10 +154,14 @@ void php_v8_isolate_limits_maybe_start_timer(php_v8_isolate_t *php_v8_isolate) {
124
154
limits->depth ++;
125
155
126
156
if (limits->active && !limits->thread ) {
157
+ php_v8_isolate_limits_update_time_point (limits);
158
+
159
+ php_v8_debug_execution (" start timer\n " );
127
160
limits->thread = new std::thread (php_v8_isolate_limits_thread, php_v8_isolate);
128
161
}
129
162
}
130
163
164
+
131
165
void php_v8_isolate_limits_maybe_stop_timer (php_v8_isolate_t *php_v8_isolate) {
132
166
php_v8_isolate_limits_t *limits = &php_v8_isolate->limits ;
133
167
@@ -172,6 +206,8 @@ void php_v8_isolate_limits_free(php_v8_isolate_t *php_v8_isolate) {
172
206
if (limits->mutex ) {
173
207
delete limits->mutex ;
174
208
}
209
+
210
+ limits->time_point .~time_point ();
175
211
}
176
212
177
213
void 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) {
180
216
limits->thread = NULL ;
181
217
limits->mutex = NULL ;
182
218
limits->depth = 0 ;
219
+
220
+ new (&limits->time_point ) std::chrono::time_point<std::chrono::high_resolution_clock>();
183
221
}
184
222
185
223
void php_v8_isolate_limits_set_time_limit (php_v8_isolate_t *php_v8_isolate, double time_limit_in_seconds) {
186
224
PHP_V8_DECLARE_ISOLATE (php_v8_isolate);
187
225
PHP_V8_DECLARE_LIMITS (php_v8_isolate);
188
226
189
- assert (time_limit_in_seconds >=0 );
227
+ assert (time_limit_in_seconds >= 0 );
190
228
191
229
v8::Locker locker (isolate);
192
230
@@ -196,28 +234,30 @@ void php_v8_isolate_limits_set_time_limit(php_v8_isolate_t *php_v8_isolate, doub
196
234
197
235
limits->mutex ->lock ();
198
236
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 ));
202
238
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
+ }
205
249
206
250
limits->active = (limits->time_limit > 0 || limits->memory_limit > 0 )
207
251
&& !limits->time_limit_hit
208
252
&& !limits->memory_limit_hit ;
209
253
210
254
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" ));
211
256
limits->thread = new std::thread (php_v8_isolate_limits_thread, php_v8_isolate);
212
257
}
213
258
214
259
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);
221
261
}
222
262
223
263
void 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
232
272
233
273
limits->mutex ->lock ();
234
274
275
+ php_v8_debug_execution (" Updating memory limits, memory_limit_hit: %s\n " , is (limits->memory_limit_hit ));
235
276
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
+ }
237
286
238
287
limits->active = (limits->time_limit > 0 || limits->memory_limit > 0 )
239
288
&& !limits->time_limit_hit
240
289
&& !limits->memory_limit_hit ;
241
290
242
291
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" ));
243
293
limits->thread = new std::thread (php_v8_isolate_limits_thread, php_v8_isolate);
244
294
}
245
295
246
296
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);
253
298
}
0 commit comments