diff options
Diffstat (limited to 'src/libs/zbxembed/zabbix.c')
-rw-r--r-- | src/libs/zbxembed/zabbix.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/src/libs/zbxembed/zabbix.c b/src/libs/zbxembed/zabbix.c index 1daaa58bcaa..c9477bdda1f 100644 --- a/src/libs/zbxembed/zabbix.c +++ b/src/libs/zbxembed/zabbix.c @@ -110,9 +110,81 @@ out: return 0; } +/****************************************************************************** + * * + * Function: es_zabbix_sleep * + * * + * Purpose: sleep for given duration in milliseconds * + * * + * Parameters: ctx - [IN] pointer to duk_context * + * * + * Comments: Throws an error: * + * - if the top value at ctx value stack cannot be converted to * + * unsigned integer * + * - if the sleep duration is longer than timeout * + * - if the sleep duration is longer than time left for JS * + * execution before timeout occurs * + * * + ******************************************************************************/ +static duk_ret_t es_zabbix_sleep(duk_context *ctx) +{ + zbx_es_env_t *env; + duk_memory_functions out_funcs; + struct timespec ts_sleep; + zbx_uint64_t timeout, duration; + unsigned int sleep_ms; + double sleep_dbl; + duk_idx_t err_idx = -1; + + /* use duk_to_number() instead of duk_to_uint() to distinguish between zero value and error */ + sleep_dbl = duk_to_number(ctx, 0); + + if (0 != DUK_ISNAN((float)sleep_dbl) || 0.0 > sleep_dbl) + return duk_error(ctx, DUK_ERR_EVAL_ERROR, "invalid Zabbix.sleep() duration"); + + if (DUK_UINT_MAX < sleep_dbl) + sleep_ms = DUK_UINT_MAX; + else + sleep_ms = (unsigned int)sleep_dbl; + + duk_get_memory_functions(ctx, &out_funcs); + env = (zbx_es_env_t *)out_funcs.udata; + timeout = (unsigned int)env->timeout * 1000; + + if (sleep_ms > timeout) + { + return duk_error(ctx, DUK_ERR_EVAL_ERROR, + "Zabbix.sleep(%u) duration is longer than JS execution timeout(" ZBX_FS_UI64 ")", + sleep_ms, timeout); + } + + duration = zbx_get_duration_ms(&env->start_time); + + if (timeout < duration) + return duk_error(ctx, DUK_ERR_RANGE_ERROR, "execution timeout"); + + timeout -= duration; + + if (sleep_ms > timeout) + { + err_idx = duk_push_error_object(ctx, DUK_ERR_RANGE_ERROR, "execution timeout"); + sleep_ms = (unsigned int)timeout; + } + + ts_sleep.tv_sec = sleep_ms / 1000; + ts_sleep.tv_nsec = sleep_ms % 1000 * 1000000; + nanosleep(&ts_sleep, NULL); + + if (-1 != err_idx) + return duk_throw(ctx); + + return 0; +} + static const duk_function_list_entry zabbix_methods[] = { - {"Log", es_zabbix_log, 2}, - {"log", es_zabbix_log, 2}, + {"Log", es_zabbix_log, 2}, + {"log", es_zabbix_log, 2}, + {"sleep", es_zabbix_sleep, 1}, {NULL, NULL, 0} }; |