https://www.mediawiki.org/wiki/Special:Code/MediaWiki/115070

Revision: 115070
Author:   tstarling
Date:     2012-04-27 01:24:20 +0000 (Fri, 27 Apr 2012)
Log Message:
-----------
* Aggregate CPU usage for limit measurement across all calls against a given 
sandbox object, instead of limiting per-call. Some interface changes were 
required. Now the timer is stored in the sandbox object instead of the stack, 
and it keeps track of its own limit settings.
* Provide LuaSandbox::getCPUUsage(), based on a separate timer so that it can 
run after the limits have expired, or if there are no limits set.
* Adjusted pcall.phpt to make new sandbox objects after a timeout

Modified Paths:
--------------
    trunk/php/luasandbox/luasandbox.c
    trunk/php/luasandbox/luasandbox_timer.h
    trunk/php/luasandbox/php_luasandbox.h
    trunk/php/luasandbox/tests/pcall.phpt
    trunk/php/luasandbox/timer.c

Modified: trunk/php/luasandbox/luasandbox.c
===================================================================
--- trunk/php/luasandbox/luasandbox.c   2012-04-26 23:50:06 UTC (rev 115069)
+++ trunk/php/luasandbox/luasandbox.c   2012-04-27 01:24:20 UTC (rev 115070)
@@ -85,6 +85,9 @@
        ZEND_ARG_INFO(0, emergency_limit)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO(arginfo_luasandbox_getCPUUsage, 0)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO(arginfo_luasandbox_callFunction, 0)
        ZEND_ARG_INFO(0, name)
        ZEND_ARG_INFO(0, ...)
@@ -118,6 +121,7 @@
        PHP_ME(LuaSandbox, setMemoryLimit, arginfo_luasandbox_setMemoryLimit, 0)
        PHP_ME(LuaSandbox, getMemoryUsage, arginfo_luasandbox_getMemoryUsage, 0)
        PHP_ME(LuaSandbox, setCPULimit, arginfo_luasandbox_setCPULimit, 0)
+       PHP_ME(LuaSandbox, getCPUUsage, arginfo_luasandbox_getCPUUsage, 0)
        PHP_ME(LuaSandbox, callFunction, arginfo_luasandbox_callFunction, 0)
        PHP_ME(LuaSandbox, registerLibrary, arginfo_luasandbox_registerLibrary, 
0)
        {NULL, NULL, NULL}
@@ -262,21 +266,24 @@
  */
 static zend_object_value luasandbox_new(zend_class_entry *ce TSRMLS_DC)
 {
-       php_luasandbox_obj * intern;
+       php_luasandbox_obj * sandbox;
        zend_object_value retval;
 
        // Create the internal object
-       intern = emalloc(sizeof(php_luasandbox_obj));
-       memset(intern, 0, sizeof(php_luasandbox_obj));
-       zend_object_std_init(&intern->std, ce TSRMLS_CC);
-       intern->alloc.memory_limit = (size_t)-1;
+       sandbox = emalloc(sizeof(php_luasandbox_obj));
+       memset(sandbox, 0, sizeof(php_luasandbox_obj));
+       zend_object_std_init(&sandbox->std, ce TSRMLS_CC);
+       sandbox->alloc.memory_limit = (size_t)-1;
 
        // Initialise the Lua state
-       intern->state = luasandbox_newstate(intern);
+       sandbox->state = luasandbox_newstate(sandbox);
 
+       // Initialise the timer
+       luasandbox_timer_create(&sandbox->timer, sandbox);
+
        // Put the object into the store
        retval.handle = zend_objects_store_put(
-               intern,
+               sandbox,
                (zend_objects_store_dtor_t)zend_objects_destroy_object, 
                (zend_objects_free_object_storage_t)luasandbox_free_storage, 
                NULL TSRMLS_CC);
@@ -325,15 +332,14 @@
  */
 static void luasandbox_free_storage(void *object TSRMLS_DC)
 {
-       php_luasandbox_obj * intern = (php_luasandbox_obj*)object;
+       php_luasandbox_obj * sandbox = (php_luasandbox_obj*)object;
 
-       if (intern->state) {
-               luasandbox_alloc_delete_state(&intern->alloc, intern->state);
-               intern->state = NULL;
-               
-               intern->state = NULL;
+       luasandbox_timer_stop(&sandbox->timer);
+       if (sandbox->state) {
+               luasandbox_alloc_delete_state(&sandbox->alloc, sandbox->state);
+               sandbox->state = NULL;
        }
-       zend_object_std_dtor(&intern->std);
+       zend_object_std_dtor(&sandbox->std);
        efree(object);
 }
 /* }}} */
@@ -657,9 +663,9 @@
 
 /** {{{ proto void LuaSandbox::setCPULimit(mixed normal_limit, mixed 
emergency_limit = false)
  *
- * Set the limit of CPU time (user+system) for LuaSandboxFunction::call()
- * calls. There are two time limits, which are both specified in seconds. Set
- * a time limit to false to disable it.
+ * Set the limit of CPU time (user+system) for all LuaSandboxFunction::call()
+ * calls against this LuaSandbox instance. There are two time limits, which 
+ * are both specified in seconds. Set a time limit to false to disable it.
  *
  * When the "normal" time limit expires, a flag will be set which causes 
  * a LuaSandboxError exception to be thrown when the currently-running Lua 
@@ -671,6 +677,9 @@
  * running, the Lua state is destroyed and then recreated with an empty state. 
  * Any LuaSandboxFunction objects which referred to the old state will stop 
  * working. A LuaSandboxEmergencyTimeout exception is thrown.
+ *
+ * Setting the time limit from a callback while Lua is running causes the timer
+ * to be reset, or started if it was not already running.
  */
 PHP_METHOD(LuaSandbox, setCPULimit)
 {
@@ -679,6 +688,9 @@
        php_luasandbox_obj * sandbox = (php_luasandbox_obj*) 
                zend_object_store_get_object(getThis() TSRMLS_CC);
 
+       struct timespec normal = {0, 0};
+       struct timespec emergency = {0, 0};
+
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z",
                &zpp_normal, &zpp_emergency) == FAILURE)
        {
@@ -696,7 +708,7 @@
                        convert_to_double_ex(zpp_normal);
                }
                if (Z_TYPE_PP(zpp_normal) == IS_DOUBLE) {
-                       luasandbox_set_timespec(&sandbox->cpu_normal_limit, 
Z_DVAL_PP(zpp_normal));
+                       luasandbox_set_timespec(&normal, Z_DVAL_PP(zpp_normal));
                        sandbox->is_cpu_limited = 1;
                } else {
                        sandbox->is_cpu_limited = 0;
@@ -707,20 +719,18 @@
                || (Z_TYPE_PP(zpp_emergency) == IS_BOOL && 
Z_BVAL_PP(zpp_emergency) == 0))
        {
                // No emergency limit
-               sandbox->cpu_emergency_limit.tv_sec = 0;
-               sandbox->cpu_emergency_limit.tv_nsec = 0;
        } else {
                convert_scalar_to_number_ex(zpp_emergency);
                if (Z_TYPE_PP(zpp_emergency) == IS_LONG) {
                        convert_to_double_ex(zpp_emergency);
                }
                if (Z_TYPE_PP(zpp_normal) == IS_DOUBLE) {
-                       luasandbox_set_timespec(&sandbox->cpu_emergency_limit, 
Z_DVAL_PP(zpp_emergency));
-               } else {
-                       sandbox->cpu_emergency_limit.tv_sec = 0;
-                       sandbox->cpu_emergency_limit.tv_nsec = 0;
+                       luasandbox_set_timespec(&emergency, 
Z_DVAL_PP(zpp_emergency));
                }
        }
+
+       // Set the timer
+       luasandbox_timer_set_limits(&sandbox->timer, &normal, &emergency);
 }
 /* }}} */
 
@@ -747,6 +757,26 @@
 
 /* }}} */
 
+/** {{{ proto float LuaSandbox::getCPUUsage()
+ *
+ * Get the amount of CPU used by this LuaSandbox instance, including any PHP 
+ * functions called by Lua.
+ */
+PHP_METHOD(LuaSandbox, getCPUUsage)
+{
+       struct timespec ts;
+       php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
+               zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       luasandbox_timer_get_usage(&sandbox->timer, &ts);
+       RETURN_DOUBLE(ts.tv_sec + 1e-9 * ts.tv_nsec);
+}
+/* }}} */
+
 /** {{{ LuaSandbox::getMemoryUsage */
 PHP_METHOD(LuaSandbox, getMemoryUsage)
 {
@@ -915,8 +945,7 @@
        // Keep track of the stack index where the return values will appear
        int retIndex = origTop + 2;
        int status;
-       int cpu_limited = 0;
-       luasandbox_timer_set t;
+       int timer_started = 0;
        int i, numResults;
        zval * old_zval;
 
@@ -945,13 +974,17 @@
        }
 
        // Initialise the CPU limit timer
-       if (!sandbox->in_lua && sandbox->is_cpu_limited) {
-               cpu_limited = 1;
+       if (!sandbox->in_lua) {
+               if (luasandbox_timer_is_expired(&sandbox->timer)) {
+                       zend_throw_exception(luasandboxtimeouterror_ce, 
luasandbox_timeout_message, LUA_ERRRUN);
+                       lua_settop(L, origTop - 1);
+                       RETURN_FALSE;
+               }
+               timer_started = 1;
                if (!LUASANDBOX_G(signal_handler_installed)) {
                        
luasandbox_timer_install_handler(&LUASANDBOX_G(old_handler));
                }
-               luasandbox_timer_start(&t, sandbox, &sandbox->cpu_normal_limit, 
-                       &sandbox->cpu_emergency_limit);
+               luasandbox_timer_start(&sandbox->timer);
        }
 
        // Save the current zval for later use in luasandbox_call_php. Restore 
it 
@@ -966,8 +999,8 @@
        sandbox->current_zval = old_zval;
 
        // Stop the timer
-       if (cpu_limited) {
-               luasandbox_timer_stop(&t);
+       if (timer_started) {
+               luasandbox_timer_stop(&sandbox->timer);
        }
        if (sandbox->emergency_timed_out) {
                luasandbox_handle_emergency_timeout(sandbox);

Modified: trunk/php/luasandbox/luasandbox_timer.h
===================================================================
--- trunk/php/luasandbox/luasandbox_timer.h     2012-04-26 23:50:06 UTC (rev 
115069)
+++ trunk/php/luasandbox/luasandbox_timer.h     2012-04-27 01:24:20 UTC (rev 
115070)
@@ -15,9 +15,11 @@
 #define LUASANDBOX_SIGNAL SIGUSR2
 #endif
 
+struct _php_luasandbox_obj;
+
 typedef struct {
        int emergency;
-       php_luasandbox_obj * sandbox;
+       struct _php_luasandbox_obj * sandbox;
 } luasandbox_timer_callback_data;
 
 typedef struct {
@@ -28,30 +30,35 @@
 typedef struct {
        luasandbox_timer normal_timer;
        luasandbox_timer emergency_timer;
-       int use_emergency;
-       php_luasandbox_obj * sandbox;
+       struct timespec normal_limit, normal_remaining;
+       struct timespec emergency_limit, emergency_remaining;
+       struct timespec usage_start, usage;
+       struct _php_luasandbox_obj * sandbox;
+       int is_running;
+       int normal_running;
+       int emergency_running;
 } luasandbox_timer_set;
 
 
-#else
+#else /*CLOCK_REALTIME*/
 
 #define LUASANDBOX_NO_CLOCK
 
 typedef struct {} luasandbox_timer;
 typedef struct {} luasandbox_timer_set;
-void timer_settime();
-void timer_delete();
-void timer_create();
 
-#endif
+#endif /*CLOCK_REALTIME*/
 
 void luasandbox_timer_install_handler(struct sigaction * oldact);
 void luasandbox_timer_remove_handler(struct sigaction * oldact);
-void luasandbox_timer_start(luasandbox_timer_set * lts, 
-               php_luasandbox_obj * sandbox,
-               struct timespec * normal_timeout,
+void luasandbox_timer_create(luasandbox_timer_set * lts, struct 
_php_luasandbox_obj * sandbox);
+void luasandbox_timer_set_limits(luasandbox_timer_set * lts,
+               struct timespec * normal_timeout, 
                struct timespec * emergency_timeout);
+void luasandbox_timer_start(luasandbox_timer_set * lts);
 void luasandbox_timer_stop(luasandbox_timer_set * lts);
+void luasandbox_timer_get_usage(luasandbox_timer_set * lts, struct timespec * 
ts);
+void luasandbox_timer_timeout_error(lua_State *L);
+int luasandbox_timer_is_expired(luasandbox_timer_set * lts);
 
-
-#endif
+#endif /*LUASANDBOX_TIMER_H*/

Modified: trunk/php/luasandbox/php_luasandbox.h
===================================================================
--- trunk/php/luasandbox/php_luasandbox.h       2012-04-26 23:50:06 UTC (rev 
115069)
+++ trunk/php/luasandbox/php_luasandbox.h       2012-04-27 01:24:20 UTC (rev 
115070)
@@ -4,6 +4,7 @@
 
 #include <lua.h>
 #include <signal.h>
+#include "luasandbox_timer.h"
 
 /* alloc.c */
 
@@ -47,6 +48,7 @@
 PHP_METHOD(LuaSandbox, setMemoryLimit);
 PHP_METHOD(LuaSandbox, getMemoryUsage);
 PHP_METHOD(LuaSandbox, setCPULimit);
+PHP_METHOD(LuaSandbox, getCPUUsage);
 PHP_METHOD(LuaSandbox, callFunction);
 PHP_METHOD(LuaSandbox, registerLibrary);
 
@@ -76,8 +78,7 @@
        volatile int timed_out;
        volatile int emergency_timed_out;
        int is_cpu_limited;
-       struct timespec cpu_normal_limit;
-       struct timespec cpu_emergency_limit;
+       luasandbox_timer_set timer;
        int function_index;
        unsigned int random_seed;
 };
@@ -92,7 +93,6 @@
 
 
 php_luasandbox_obj * luasandbox_get_php_obj(lua_State * L);
-void luasandbox_timer_timeout_error(lua_State *L);
 
 /** {{{ luasandbox_enter_php
  *

Modified: trunk/php/luasandbox/tests/pcall.phpt
===================================================================
--- trunk/php/luasandbox/tests/pcall.phpt       2012-04-26 23:50:06 UTC (rev 
115069)
+++ trunk/php/luasandbox/tests/pcall.phpt       2012-04-27 01:24:20 UTC (rev 
115070)
@@ -2,7 +2,6 @@
 pcall() catching various errors
 --FILE--
 <?php
-$sandbox = new LuaSandbox;
 $lua = <<<LUA
        function pcall_test(f)
                local status, msg
@@ -24,12 +23,13 @@
        'Out of memory' => 'string.rep("x", 1000000)'
 );
                
-$sandbox->loadString( $lua )->call();
-$sandbox->setCPULimit( 0.25 );
-$sandbox->setMemoryLimit( 100000 );
 
 foreach ( $tests as $desc => $code ) {
        echo "$desc: ";
+       $sandbox = new LuaSandbox;
+       $sandbox->loadString( $lua )->call();
+       $sandbox->setCPULimit( 0.25 );
+       $sandbox->setMemoryLimit( 100000 );
        try {
                print implode("\n", 
                        $sandbox->callFunction( 'pcall_test', 
$sandbox->loadString( $code ) ) ) . "\n";

Modified: trunk/php/luasandbox/timer.c
===================================================================
--- trunk/php/luasandbox/timer.c        2012-04-26 23:50:06 UTC (rev 115069)
+++ trunk/php/luasandbox/timer.c        2012-04-27 01:24:20 UTC (rev 115070)
@@ -11,28 +11,72 @@
 #include "php_luasandbox.h"
 #include "luasandbox_timer.h"
 
+char luasandbox_timeout_message[] = "The maximum execution time for this 
script was exceeded";
+
 #ifdef LUASANDBOX_NO_CLOCK
 
 void luasandbox_timer_install_handler(struct sigaction * oldact) {}
 void luasandbox_timer_remove_handler(struct sigaction * oldact) {}
-void luasandbox_timer_start(luasandbox_timer_set * lts,
-               php_luasandbox_obj * sandbox,
-               struct timespec * normal_timeout,
+void luasandbox_timer_create(luasandbox_timer_set * lts,
+               php_luasandbox_obj * sandbox) {}
+void luasandbox_timer_set_limits(luasandbox_timer_set * lts,
+               struct timespec * normal_timeout, 
                struct timespec * emergency_timeout) {}
+void luasandbox_timer_start(luasandbox_timer_set * lts) {}
 void luasandbox_timer_stop(luasandbox_timer_set * lts) {}
+
+void luasandbox_timer_get_usage(luasandbox_timer_set * lts, struct timespec * 
ts) {
+       ts->tv_sec = ts->tv_nsec = 0;
+}
 void luasandbox_timer_timeout_error(lua_State *L) {}
-char luasandbox_timeout_message[];
+int luasandbox_is_expired(luasandbox_timer_set * lts) {
+       return 0;
+}
 
+
 #else
 
 static void luasandbox_timer_handle(int signo, siginfo_t * info, void * 
context);
-static void luasandbox_timer_create(luasandbox_timer * lt, php_luasandbox_obj 
* sandbox, 
+static void luasandbox_timer_create_one(luasandbox_timer * lt, 
php_luasandbox_obj * sandbox, 
                int emergency);
 static void luasandbox_timer_timeout_hook(lua_State *L, lua_Debug *ar);
-static void luasandbox_timer_settime(luasandbox_timer * lt, struct timespec * 
ts);
+static void luasandbox_timer_set_one_time(luasandbox_timer * lt, struct 
timespec * ts);
+static void luasandbox_timer_stop_one(luasandbox_timer * lt, struct timespec * 
remaining);
+static void luasandbox_update_usage(luasandbox_timer_set * lts);
 
-char luasandbox_timeout_message[] = "The maximum execution time for this 
script was exceeded";
+static inline void luasandbox_timer_zero(struct timespec * ts)
+{
+       ts->tv_sec = ts->tv_nsec = 0;
+}
 
+static inline int luasandbox_timer_is_zero(struct timespec * ts)
+{
+       return ts->tv_sec == 0 && ts->tv_nsec == 0;
+}
+
+static inline void luasandbox_timer_subtract(
+               struct timespec * a, const struct timespec * b)
+{
+       a->tv_sec -= b->tv_sec;
+       if (a->tv_nsec < b->tv_nsec) {
+               a->tv_sec--;
+               a->tv_nsec += 1000000000L - b->tv_nsec;
+       } else {
+               a->tv_nsec -= b->tv_nsec;
+       }
+}
+
+static inline void luasandbox_timer_add(
+               struct timespec * a, const struct timespec * b)
+{
+       a->tv_sec += b->tv_sec;
+       a->tv_nsec += b->tv_nsec;
+       if (a->tv_nsec > 1000000000L) {
+               a->tv_nsec -= 1000000000L;
+               a->tv_sec++;
+       }
+}
+
 void luasandbox_timer_install_handler(struct sigaction * oldact)
 {
        struct sigaction newact;
@@ -100,26 +144,64 @@
        lua_error(L);
 }
 
-void luasandbox_timer_start(luasandbox_timer_set * lts, 
-               php_luasandbox_obj * sandbox,
-               struct timespec * normal_timeout,
+void luasandbox_timer_create(luasandbox_timer_set * lts, php_luasandbox_obj * 
sandbox)
+{
+       luasandbox_timer_zero(&lts->usage);
+       luasandbox_timer_zero(&lts->normal_limit);
+       luasandbox_timer_zero(&lts->normal_remaining);
+       luasandbox_timer_zero(&lts->emergency_limit);
+       luasandbox_timer_zero(&lts->emergency_remaining);
+       lts->is_running = 0;
+       lts->normal_running = 0;
+       lts->emergency_running = 0;
+       lts->sandbox = sandbox;
+}
+
+void luasandbox_timer_set_limits(luasandbox_timer_set * lts,
+               struct timespec * normal_timeout, 
                struct timespec * emergency_timeout)
 {
-       // Create normal timer
-       luasandbox_timer_create(&lts->normal_timer, sandbox, 0);
-       luasandbox_timer_settime(&lts->normal_timer, normal_timeout);
+       int was_running = 0;
+       if (lts->is_running) {
+               was_running = 1;
+               lusandbox_timer_stop(lts);
+       }
+       lts->normal_remaining = lts->normal_limit = *normal_timeout;
+       lts->emergency_remaining = lts->emergency_limit = *emergency_timeout;
+       if (was_running) {
+               luasandbox_timer_start(lts);
+       }
+}
 
+void luasandbox_timer_start(luasandbox_timer_set * lts)
+{
+       if (lts->is_running) {
+               // Already running
+               return;
+       }
+       lts->is_running = 1;
+       // Initialise usage timer
+       clock_gettime(LUASANDBOX_CLOCK_ID, &lts->usage_start);
+
+       // Create normal timer if requested
+       if (!luasandbox_timer_is_zero(&lts->normal_remaining)) {
+               lts->normal_running = 1;
+               luasandbox_timer_create_one(&lts->normal_timer, lts->sandbox, 
0);
+               luasandbox_timer_set_one_time(&lts->normal_timer, 
&lts->normal_remaining);
+       } else {
+               lts->normal_running = 0;
+       }
        // Create emergency timer if requested
-       if (emergency_timeout->tv_sec || emergency_timeout->tv_nsec) {
-               lts->use_emergency = 1;
-               luasandbox_timer_create(&lts->emergency_timer, sandbox, 1);
-               luasandbox_timer_settime(&lts->emergency_timer, 
emergency_timeout);
+       if (!luasandbox_timer_is_zero(&lts->emergency_remaining)) {
+               lts->emergency_running = 1;
+               luasandbox_timer_create_one(&lts->emergency_timer, 
lts->sandbox, 1);
+               luasandbox_timer_set_one_time(&lts->emergency_timer, 
&lts->emergency_remaining);
        } else {
-               lts->use_emergency = 0;
+               lts->emergency_running = 0;
        }
 }
 
-static void luasandbox_timer_create(luasandbox_timer * lt, php_luasandbox_obj 
* sandbox, 
+static void luasandbox_timer_create_one(luasandbox_timer * lt, 
php_luasandbox_obj * sandbox, 
                int emergency)
 {
        struct sigevent ev;
@@ -134,25 +216,84 @@
        timer_create(LUASANDBOX_CLOCK_ID, &ev, &lt->timer);
 }
 
-static void luasandbox_timer_settime(luasandbox_timer * lt, struct timespec * 
ts)
+static void luasandbox_timer_set_one_time(luasandbox_timer * lt, struct 
timespec * ts)
 {
        struct itimerspec its;
-       its.it_interval.tv_sec = 0;
-       its.it_interval.tv_nsec = 0;
+       luasandbox_timer_zero(&its.it_interval);
        its.it_value = *ts;
        timer_settime(lt->timer, 0, &its, NULL);
 }
 
+
 void luasandbox_timer_stop(luasandbox_timer_set * lts)
 {
-       struct timespec zero = {0, 0};
-       if (lts->use_emergency) {
-               luasandbox_timer_settime(&lts->emergency_timer, &zero);
-               timer_delete(lts->emergency_timer.timer);
+       struct timespec usage;
+
+       if (lts->is_running) {
+               lts->is_running = 0;
+       } else {
+               return;
        }
 
-       luasandbox_timer_settime(&lts->normal_timer, &zero);
-       timer_delete(lts->normal_timer.timer);
+       // Stop the interval timers and save the time remaining
+       if (lts->emergency_running) {
+               luasandbox_timer_stop_one(&lts->emergency_timer, 
&lts->emergency_remaining);
+               lts->emergency_running = 0;
+       }
+       if (lts->normal_running) {
+               luasandbox_timer_stop_one(&lts->normal_timer, 
&lts->normal_remaining);
+               lts->normal_running = 0;
+       }
+
+       // Update the usage
+       luasandbox_update_usage(lts);
+       clock_gettime(LUASANDBOX_CLOCK_ID, &usage);
+       luasandbox_timer_subtract(&usage, &lts->usage_start);
+       luasandbox_timer_add(&lts->usage, &usage);
 }
 
+
+static void luasandbox_timer_stop_one(luasandbox_timer * lt, struct timespec * 
remaining)
+{
+       static struct timespec zero = {0, 0};
+       struct itimerspec its;
+       timer_gettime(lt->timer, &its);
+       remaining->tv_sec = its.it_value.tv_sec;
+       remaining->tv_nsec = its.it_value.tv_nsec;
+       luasandbox_timer_set_one_time(lt, &zero);
+       timer_delete(lt->timer);
+}
+
+void luasandbox_timer_get_usage(luasandbox_timer_set * lts, struct timespec * 
ts)
+{
+       if (lts->is_running) {
+               luasandbox_update_usage(lts);
+       }
+       *ts = lts->usage;
+}
+
+int luasandbox_timer_is_expired(luasandbox_timer_set * lts)
+{
+       if (!luasandbox_timer_is_zero(&lts->normal_limit)) {
+               if (luasandbox_timer_is_zero(&lts->normal_remaining)) {
+                       return 1;
+               }
+       }
+       if (!luasandbox_timer_is_zero(&lts->emergency_limit)) {
+               if (luasandbox_timer_is_zero(&lts->emergency_remaining)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void luasandbox_update_usage(luasandbox_timer_set * lts)
+{
+       struct timespec current, usage;
+       clock_gettime(LUASANDBOX_CLOCK_ID, &current);
+       usage = current;
+       luasandbox_timer_subtract(&usage, &lts->usage_start);
+       luasandbox_timer_add(&lts->usage, &usage);
+       lts->usage_start = current;
+}
 #endif


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to