int release_main_loop() { int returnValue = 0; SOL_DBG("Entering with state %s", RESOLVE_MAINLOOP_STATE(mainloopState)); if (mainloopState == MAINLOOP_RELEASED || mainloopState == MAINLOOP_RELEASING_STARTED) { return returnValue; } SOL_DBG("Stopping token handle"); returnValue = uv_prepare_stop(&uv_token_handle); if (returnValue) { return returnValue; } // hijack_main_loop() was called, but the idler has not run yet if (mainloopState == MAINLOOP_HIJACKING_STARTED) { SOL_DBG("idler has not run yet, so stopping it"); returnValue = uv_idle_stop(&uv_idle); if (!returnValue) { mainloopState = MAINLOOP_RELEASED; } } else { SOL_DBG("quitting main loop"); mainloopState = MAINLOOP_RELEASING_STARTED; sol_quit(); } return returnValue; }
static void * sol_worker_thread_do(void *data) { struct sol_worker_thread_posix *thread = data; struct sol_worker_thread_config *config = &thread->config; SOL_DBG("worker thread %p started", thread); if (config->setup) { if (!config->setup((void *)config->data)) goto end; } while (!sol_worker_thread_impl_cancel_check(thread)) { if (!config->iterate((void *)config->data)) break; } if (config->cleanup) config->cleanup((void *)config->data); end: if (sol_worker_thread_lock(thread)) { if (thread->idler) sol_idle_del(thread->idler); thread->idler = sol_idle_add(sol_worker_thread_finished, thread); sol_worker_thread_unlock(thread); } SOL_DBG("worker thread %p stopped", thread); return thread; }
SOL_API void sol_oic_payload_debug(struct sol_coap_packet *pkt) { SOL_NULL_CHECK(pkt); #ifdef HAVE_STDOUT struct sol_buffer *buf; CborParser parser; CborValue root; CborError err; size_t offset; if (!sol_oic_pkt_has_cbor_content(pkt) || !sol_coap_packet_has_payload(pkt)) { return; } if (sol_coap_packet_get_payload(pkt, &buf, &offset) < 0) { SOL_DBG("Failed to get packet payload"); return; } err = cbor_parser_init(sol_buffer_at(buf, offset), buf->used - offset, 0, &parser, &root); if (err != CborNoError) { SOL_DBG("Failed to get cbor payload"); return; } cbor_value_to_pretty(stdout, &root); fprintf(stdout, "\n"); #else SOL_DBG("Failed to log oic payload: stdout not available"); #endif }
static void watchdog_show_info(void) { if (SOL_LOG_LEVEL_POSSIBLE(SOL_LOG_LEVEL_DEBUG)) { struct watchdog_info ident; uint32_t options = 0, flags = 0; int err; err = ioctl(watchdog_fd, WDIOC_GETSUPPORT, &ident); if (err == 0) { SOL_DBG("watchdog identity '%.32s' firmware_version=%u options=%#x", ident.identity, ident.firmware_version, ident.options); options = ident.options; } err = ioctl(watchdog_fd, WDIOC_GETSTATUS, &flags); if (err == 0) watchdog_show_info_flags("Current", flags, options); err = ioctl(watchdog_fd, WDIOC_GETBOOTSTATUS, &flags); if (err == 0) watchdog_show_info_flags("Last Reboot", flags, options); err = ioctl(watchdog_fd, WDIOC_GETTEMP, &flags); if (err == 0) SOL_DBG("Temperature %d fahrenheit", flags); } }
static gpointer sol_worker_thread_do(gpointer data) { struct sol_worker_thread_glib *thread = data; struct sol_worker_thread_config *config = &thread->config; SOL_DBG("worker thread %p started", thread); if (config->setup) { if (!config->setup((void *)config->data)) goto end; } while (!sol_worker_thread_impl_cancel_check(thread)) { if (!config->iterate((void *)config->data)) break; } if (config->cleanup) config->cleanup((void *)config->data); end: g_mutex_lock(&thread->lock); if (thread->idler) sol_idle_del(thread->idler); thread->idler = sol_idle_add(sol_worker_thread_finished, thread); g_mutex_unlock(&thread->lock); SOL_DBG("worker thread %p stopped", thread); return thread; }
static int resolver_conffile_get_strv(const char *id, struct sol_flow_node_type const **node_type, char const ***opts_as_string) { const char *type_name; if (sol_conffile_resolve(id, &type_name, opts_as_string) < 0) { SOL_DBG("could not resolve a type name for id='%s'", id); return -EINVAL; } *node_type = resolve_module_type_by_component (type_name, sol_flow_foreach_builtin_node_type); if (!*node_type) { *node_type = _resolver_conffile_get_module(type_name); if (!*node_type) { SOL_DBG("could not resolve a node module for Type='%s'", type_name); return -EINVAL; } } return 0; }
static int rgb_parse(const char *value, struct sol_flow_node_named_options_member *m) { char *buf; int field_cnt = 0; bool keys_schema = false; char *red, *green, *blue, *red_max, *green_max, *blue_max; struct sol_rgb *ret = &m->rgb; uint32_t *store_vals[] = { &ret->red, &ret->green, &ret->blue, &ret->red_max, &ret->green_max, &ret->blue_max }; buf = strdup(value); ASSIGN_KEY_VAL(int32_t, red, STRTOL_DECIMAL, true, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, green, STRTOL_DECIMAL, true, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, blue, STRTOL_DECIMAL, true, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, red_max, STRTOL_DECIMAL, true, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, green_max, STRTOL_DECIMAL, true, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, blue_max, STRTOL_DECIMAL, true, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_LINEAR_VALUES(STRTOL_DECIMAL, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); SOL_DBG("rgb opt ends up as red=%" PRIu32 ", green=%" PRIu32 ", blue=%" PRIu32 " red_max=%" PRIu32 ", green_max=%" PRIu32 ", blue_max=%" PRIu32 "\n", ret->red, ret->green, ret->blue, ret->red_max, ret->green_max, ret->blue_max); free(buf); return 0; err: SOL_DBG("Invalid rgb value for option name=\"%s\": \"%s\"." " Please use the formats" " \"<red_value>|<green_value>|<blue_value>|" "<red_max_value>|<green_max_value>|<blue_max_value>\"," " in that order, or \"<key>:<value>|<...>\", for keys in " "[red, green, blue, red_max, green_max, blue_max], in any order. " "Values may be the special strings INT32_MAX. All of them must be " "not negative int values.", m->name, value); free(buf); return -EINVAL; }
static int drange_parse(const struct sol_flow_node_options_member_description *member, const char *value, struct sol_drange *ret) { char *buf; int field_cnt = 0; bool keys_schema = false; char *min, *max, *step, *val; bool min_done = false, max_done = false, step_done = false, val_done = false; static const char DBL_MAX_STR[] = "DBL_MAX"; static const char DBL_MIN_STR[] = "-DBL_MAX"; static const size_t DBL_MAX_STR_LEN = sizeof(DBL_MAX_STR) - 1; static const size_t DBL_MIN_STR_LEN = sizeof(DBL_MIN_STR) - 1; double *store_vals[] = { &ret->val, &ret->min, &ret->max, &ret->step }; buf = strdup(value); ASSIGN_KEY_VAL(double, min, strtod, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, max, strtod, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, step, strtod, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, val, strtod, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); KEY_VALUES_RECAP(DBL_MAX, -DBL_MAX); ASSIGN_LINEAR_VALUES(strtod, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); LINEAR_VALUES_RECAP(DBL_MAX, -DBL_MAX); SOL_DBG("drange opt ends up as min=%lf, max=%lf, step=%lf, val=%lf\n", ret->min, ret->max, ret->step, ret->val); free(buf); return 0; err: SOL_DBG("Invalid drange value for option name=\"%s\": \"%s\"." " Please use the formats" " \"<val_value>|<min_value>|<max_value>|<step_value>\"," " in that order, or \"<key>:<value>|<...>\", for keys in " "[val, min, max, step], in any order. Values may be the " "special strings DBL_MAX and -DBL_MAX. Don't use commas " "on the numbers", member->name, value); free(buf); return -EINVAL; }
static int irange_parse(const struct sol_flow_node_options_member_description *member, const char *value, struct sol_irange *ret) { char *buf; int field_cnt = 0; bool keys_schema = false; char *min, *max, *step, *val; bool min_done = false, max_done = false, step_done = false, val_done = false; static const char INT_MAX_STR[] = "INT32_MAX"; static const char INT_MIN_STR[] = "INT32_MIN"; static const size_t INT_LIMIT_STR_LEN = sizeof(INT_MAX_STR) - 1; int32_t *store_vals[] = { &ret->val, &ret->min, &ret->max, &ret->step }; buf = strdup(value); ASSIGN_KEY_VAL(int32_t, min, STRTOL_DECIMAL, false, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, max, STRTOL_DECIMAL, false, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, step, STRTOL_DECIMAL, false, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); ASSIGN_KEY_VAL(int32_t, val, STRTOL_DECIMAL, false, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); KEY_VALUES_RECAP(INT32_MAX, INT32_MIN); ASSIGN_LINEAR_VALUES(STRTOL_DECIMAL, INT32_MAX, INT_MAX_STR, INT_LIMIT_STR_LEN, INT32_MIN, INT_MIN_STR, INT_LIMIT_STR_LEN); LINEAR_VALUES_RECAP(INT32_MAX, INT32_MIN); SOL_DBG("irange opt ends up as min=%d, max=%d, step=%d, val=%d\n", ret->min, ret->max, ret->step, ret->val); free(buf); return 0; err: SOL_DBG("Invalid irange value for option name=\"%s\": \"%s\"." " Please use the formats" " \"<val_value>|<min_value>|<max_value>|<step_value>\"," " in that order, or \"<key>:<value>|<...>\", for keys in " "[val, min, max, step], in any order. Values may be the " "special strings INT32_MAX and INT32_MIN.", member->name, value); free(buf); return -EINVAL; }
static void _manager_properties_changed(void *data, uint64_t mask) { struct ctx *ctx = data; SOL_DBG("mask=%" PRIu64, mask); if (mask & (1 << MANAGER_PROPERTY_SYSTEM_STATE)) { SOL_DBG("New system state: [%d]", ctx->properties.system_state); sol_platform_inform_state_monitors(ctx->properties.system_state); } }
static int direction_vector_parse(const char *value, struct sol_flow_node_named_options_member *m) { char *buf; int field_cnt = 0; bool keys_schema = false; char *min, *max, *x, *y, *z; struct sol_direction_vector *ret = &m->direction_vector; double *store_vals[] = { &ret->x, &ret->y, &ret->z, &ret->min, &ret->max }; buf = strdup(value); ASSIGN_KEY_VAL(double, x, strtod_no_locale, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, y, strtod_no_locale, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, z, strtod_no_locale, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, min, strtod_no_locale, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_KEY_VAL(double, max, strtod_no_locale, false, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); ASSIGN_LINEAR_VALUES(strtod_no_locale, DBL_MAX, DBL_MAX_STR, DBL_MAX_STR_LEN, -DBL_MAX, DBL_MIN_STR, DBL_MIN_STR_LEN); SOL_DBG("direction_vector opt ends up as " "x=%lf, y=%lf, z=%lf, min=%lf, max=%lf\n", ret->x, ret->y, ret->z, ret->min, ret->max); free(buf); return 0; err: SOL_DBG("Invalid direction_vector value for option name=\"%s\": \"%s\"." " Please use the formats" " \"<x_value>|<y_value>|<z_value>|<min_value>|<max_value>\"," " in that order, or \"<key>:<value>|<...>\", for keys in " "[x, y, z, min, max], in any order. Values may be the " "special strings DBL_MAX and -DBL_MAX. Don't use commas " "on the numbers", m->name, value); free(buf); return -EINVAL; }
SOL_API int sol_json_token_get_uint64(const struct sol_json_token *token, uint64_t *value) { SOL_NULL_CHECK(token, -EINVAL); SOL_NULL_CHECK(value, -EINVAL); *value = 0; if (token->start >= token->end) { SOL_WRN("invalid token: start=%p, end=%p", token->start, token->end); return -EINVAL; } if (sol_json_token_get_type(token) != SOL_JSON_TYPE_NUMBER) { SOL_WRN("expected number, got token type '%c' for token \"%.*s\"", sol_json_token_get_type(token), (int)sol_json_token_get_size(token), token->start); return -EINVAL; } if (*token->start == '-') { SOL_DBG("%.*s: negative number where unsigned is expected", (int)sol_json_token_get_size(token), token->start); return -ERANGE; } return token_get_uint64(token, value); }
static gboolean on_signal(gpointer ptr) { SOL_DBG("got signal, quit main loop..."); sol_quit(); return true; }
static void adapter_property_changed(void *data, const char *path, uint64_t mask) { struct context *ctx = data; if (!ctx->adapter_path) return; if (mask & (1 << ADAPTER_PROPERTY_POWERED)) { struct sol_bt_session *s; uint16_t i; bool powered; powered = ctx->current_state == ADAPTER_STATE_ON; SOL_DBG("Adapter %s powered %s", ctx->adapter_path, powered ? "on" : "off"); SOL_PTR_VECTOR_FOREACH_IDX (&ctx->sessions, s, i) s->enabled((void *)s->user_data, powered); /* Also notify about current devices */ if (powered) { struct device_info *d; SOL_PTR_VECTOR_FOREACH_IDX (&ctx->devices, d, i) notify_scan_device(ctx, d); } } }
SOL_API void sol_shutdown(void) { if (_init_count == 0) { SOL_CRI("sol_init() was not called"); return; } _init_count--; if (_init_count > 0) return; SOL_DBG("shutdown"); sol_ipm_shutdown(); sol_update_shutdown(); sol_comms_shutdown(); sol_flow_shutdown(); sol_crypto_shutdown(); sol_blob_shutdown(); sol_pin_mux_shutdown(); sol_platform_shutdown(); mainloop_impl->shutdown(); sol_modules_clear_cache(); sol_log_shutdown(); }
static int engine_state_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { int r; bool engine_is_on; struct sml_garden_data *sdata = data; time_t now = time(NULL); r = sol_flow_packet_get_boolean(packet, &engine_is_on); SOL_INT_CHECK(r, < 0, r); if (engine_is_on) sdata->btn_pressed_timestamp = now; else if (sdata->btn_pressed_timestamp) { now -= sdata->btn_pressed_timestamp; SOL_DBG("Pressed for:%ld seconds", now); if (sdata->last_engine_on_duration + now > ENGINE_DURATION_MAX_VAL) sdata->last_engine_on_duration = ENGINE_DURATION_MAX_VAL; else sdata->last_engine_on_duration += now; sdata->btn_pressed_timestamp = 0; r = send_packet_if_needed(node, sdata); SOL_INT_CHECK(r, < 0, r); }
static char * get_first_module_on_dir(const char *dir_name) { char *result = NULL; char path[PATH_MAX], install_rootdir[PATH_MAX]; struct stat st; int r; r = sol_util_get_rootdir(install_rootdir, sizeof(install_rootdir)); SOL_INT_CHECK(r, >= (int)sizeof(install_rootdir), NULL); SOL_INT_CHECK(r, < 0, NULL); r = snprintf(path, sizeof(path), "%s%s", install_rootdir, dir_name); SOL_INT_CHECK(r, >= (int)sizeof(path), NULL); SOL_INT_CHECK(r, < 0, NULL); if (stat(path, &st) || !S_ISDIR(st.st_mode)) { SOL_DBG("Invalid update module dir: %s", path); return NULL; } if (!sol_util_iterate_dir(path, iterate_dir_cb, &result)) return NULL; return result; }
static bool uv_loop_fd_changed(void *data, int fd, uint32_t active_flags) { SOL_DBG("Running one uv loop iteration"); uv_run(data, UV_RUN_NOWAIT); return true; }
static void watchdog_show_info_flags(const char *msg, uint32_t flags, uint32_t options) { if (SOL_LOG_LEVEL_POSSIBLE(SOL_LOG_LEVEL_DEBUG)) { static const struct watchdog_flag_map { uint32_t flag; const char *desc; } *itr, *itr_end, map[] = { { WDIOF_OVERHEAT, "Reset due to CPU overheat" }, { WDIOF_FANFAULT, "Fan failed" }, { WDIOF_EXTERN1, "External relay 1" }, { WDIOF_EXTERN2, "External relay 2" }, { WDIOF_POWERUNDER, "Power bad/power fault" }, { WDIOF_CARDRESET, "Card previously reset the CPU" }, { WDIOF_POWEROVER, "Power over voltage" }, }; SOL_DBG("watchdog status %s: flags=%#x, options=%#x", msg, flags, options); itr = map; itr_end = itr + sol_util_array_size(map); for (; itr < itr_end; itr++) { if (itr->flag & options) { if (itr->flag & flags) SOL_WRN("%s: %s", msg, itr->desc); } } } }
static int common_get_progress(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct update_data *mdata = data; struct update_node_type *type; struct sol_irange irange = { .step = 1, .min = 0, .max = 100 }; type = (struct update_node_type *)sol_flow_node_get_type(node); if (mdata->handle) { irange.val = sol_update_get_progress(mdata->handle); if (irange.val >= 0 && irange.val <= 100) sol_flow_send_irange_packet(node, type->progress_port, &irange); else sol_flow_send_error_packet(node, EINVAL, "Could not get progress of task"); } else { SOL_DBG("No current operation in process, ignoring request to get progress"); } return 0; }
SOL_API int sol_json_token_get_double(const struct sol_json_token *token, double *value) { char *endptr; int r; /* NOTE: Using a copy to ensure trailing \0 and strtod() so we * properly parse numbers with large precision. * * Splitting the integer, fractional and exponent parts and doing * the math using double numbers will result in rounding errors * when parsing DBL_MAX using "%.64g" formatting. * * Since parsing it is complex (ie: * http://www.netlib.org/fp/dtoa.c), we take the short path to * call our helper around libc's strtod() that limits the amount * of bytes. */ SOL_NULL_CHECK(token, -EINVAL); SOL_NULL_CHECK(value, -EINVAL); *value = sol_util_strtod_n(token->start, &endptr, sol_json_token_get_size(token), false); r = -errno; if (endptr == token->start) r = -EINVAL; else if (isinf(*value)) { SOL_DBG("token '%.*s' is infinite", (int)sol_json_token_get_size(token), token->start); if (*value < 0) *value = -DBL_MAX; else *value = DBL_MAX; r = -ERANGE; } else if (isnan(*value)) { SOL_DBG("token '%.*s' is not a number", (int)sol_json_token_get_size(token), token->start); *value = 0; r = -EINVAL; } else if (fpclassify(*value) == FP_SUBNORMAL) { r = 0; } return r; }
static gboolean on_fd(gint fd, GIOCondition cond, gpointer data) { did_fd = true; SOL_DBG("did fd=%d, cond=%#x", fd, cond); check_done(); return false; }
static gboolean on_timeout(gpointer data) { did_timeout = true; SOL_DBG("did timeout"); check_done(); return false; }
static gboolean on_idle(gpointer data) { did_idle = true; SOL_DBG("did idle"); check_done(); return false; }
SOL_API void sol_quit_with_code(int return_code) { if (_init_count == 0) { SOL_CRI("sol_init() was not called"); return; } if (!mainloop_running) { SOL_DBG("Mainloop was not running"); return; } SOL_DBG("quit with code %d", return_code); mainloop_return_code = return_code; mainloop_running = false; mainloop_impl->quit(); }
static void sol_mavlink_statustext_handler(mavlink_message_t *msg) { char text[50]; mavlink_msg_statustext_get_text(msg, text); SOL_DBG("%s", text); }
static int send_predict_packet(struct sol_flow_node *node, struct sml_garden_data *sdata) { SOL_DBG("Sending predict packet to SML"); return send_sml_garden_packet(node, SOL_FLOW_NODE_TYPE_SML_GARDEN_MESSAGE_CONSTRUCTOR__OUT__OUT_PREDICT, 0, &sdata->last_water, &sdata->cur_timeblock); }
static void on_state_changed(void *data, enum sol_platform_state state) { struct platform_data *mdata = data; SOL_DBG("state changed %d -> %d", mdata->state, state); mdata->state = state; state_dispatch(mdata); }
static void on_service_state_changed(void *data, const char *service, enum sol_platform_service_state state) { struct platform_service_data *mdata = data; SOL_DBG("service %s state changed %d -> %d", service, mdata->state, state); mdata->state = state; service_state_dispatch(mdata); }
static void uv_idle_callback() { SOL_DBG("Entering with state %s", RESOLVE_MAINLOOP_STATE(mainloopState)); if (mainloopState == MAINLOOP_HIJACKING_STARTED) { SOL_DBG("running sol_run()"); mainloopState = MAINLOOP_HIJACKED; sol_run(); SOL_DBG("sol_run() has returned. state is %s", RESOLVE_MAINLOOP_STATE(mainloopState)); if (mainloopState == MAINLOOP_RELEASING_STARTED) { mainloopState = MAINLOOP_RELEASED; } } else if ( mainloopState == MAINLOOP_HIJACKED) { SOL_DBG("main loop already hijacked. Stopping idler"); uv_idle_stop(&uv_idle); } }