diff --git a/libbbfdm-api/dmubus.c b/libbbfdm-api/dmubus.c index 3dc037fd..21b34e72 100644 --- a/libbbfdm-api/dmubus.c +++ b/libbbfdm-api/dmubus.c @@ -161,11 +161,11 @@ static void _bbfdm_task_callback(struct uloop_timeout *t) BBF_ERR("Failed to decode task"); return; } - task->callback(task->arg1, task->arg2); + task->taskcb(task->arg1, task->arg2); free(task); } -int bbfdm_task_add(bbfdm_task_callback_t callback, const void *arg1, const void *arg2, int timeout_sec) { +int bbfdm_task_schedule(bbfdm_task_callback_t callback, const void *arg1, const void *arg2, int timeout_sec) { bbfdm_task_data_t *task; @@ -182,7 +182,7 @@ int bbfdm_task_add(bbfdm_task_callback_t callback, const void *arg1, const void } - task->callback = callback; + task->taskcb = callback; task->arg1 = arg1; task->arg2 = arg2; @@ -194,7 +194,68 @@ int bbfdm_task_add(bbfdm_task_callback_t callback, const void *arg1, const void return ret; } +static void _bbfdm_task_finish_callback(struct uloop_process *p, int ret) +{ + struct bbfdm_task_data *task = container_of(p, struct bbfdm_task_data, process); + if (task == NULL) { + BBF_ERR("Failed to decode forked task"); + return; + } + if (task->finishcb) { + task->finishcb(task->arg1, task->arg2); + } + free(task); +} + + +int bbfdm_task_fork(bbfdm_task_callback_t taskcb, bbfdm_task_callback_t finishcb, const void *arg1, const void *arg2) +{ + pid_t child; + bbfdm_task_data_t *task; + + // do not use dmalloc here, as this needs to persists beyond session + task = (bbfdm_task_data_t *)calloc(sizeof(bbfdm_task_data_t), 1); + if (task == NULL) { + BBF_ERR("Failed to allocate memory"); + return -1; + } + + task->arg1 = arg1; + task->arg2 = arg2; + + child = fork(); + if (child == -1) { + BBF_ERR("Failed to fork a child for task"); + goto err_out; + } else if (child == 0) { + /* free fd's and memory inherited from parent */ + uloop_done(); + fclose(stdin); + fclose(stdout); + fclose(stderr); + + BBF_INFO("{fork} Calling from subprocess"); + taskcb(task->arg1, task->arg2); + + /* write result and exit */ + exit(EXIT_SUCCESS); + } + + // monitor the process if finish callback is defined + if (finishcb) { + task->finishcb = finishcb; + task->process.pid = child; + task->process.cb = _bbfdm_task_finish_callback; + uloop_process_add(&task->process); + } else { + FREE(task); + } + return 0; + +err_out: + return -1; +} /******************************************************************************* ** ** dmubus_wait_for_event diff --git a/libbbfdm-api/dmubus.h b/libbbfdm-api/dmubus.h index 9e77bba9..2003c848 100644 --- a/libbbfdm-api/dmubus.h +++ b/libbbfdm-api/dmubus.h @@ -34,13 +34,17 @@ struct dmubus_ev_subtask { typedef void (*bbfdm_task_callback_t)(const void *arg1, const void *arg2); typedef struct bbfdm_task_data { + struct uloop_process process; // Used for forked task struct uloop_timeout timeout; - bbfdm_task_callback_t callback; + bbfdm_task_callback_t taskcb; + bbfdm_task_callback_t finishcb; // Used for forked task const void *arg1; const void *arg2; } bbfdm_task_data_t; -int bbfdm_task_add(bbfdm_task_callback_t callback, const void *arg1, const void *arg2, int timeout); +int bbfdm_task_schedule(bbfdm_task_callback_t callback, const void *arg1, const void *arg2, int timeout); + +int bbfdm_task_fork(bbfdm_task_callback_t taskcb, bbfdm_task_callback_t finishcb, const void *arg1, const void *arg2); typedef void (*CB_FUNC_PTR)(struct ubus_context *ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg); diff --git a/libbbfdm/device.c b/libbbfdm/device.c index db71a54b..43cfcfa1 100644 --- a/libbbfdm/device.c +++ b/libbbfdm/device.c @@ -26,19 +26,30 @@ static int get_Device_RootDataModelVersion(char *refparam, struct dmctx *ctx, vo return 0; } +static void _exec_factoryreset(const void *arg1, const void *arg2) +{ + sleep(2); + dmubus_call_set("rpc-sys", "factory", UBUS_ARGS{0}, 0); + sleep(5); // Wait for reboot to happen + BBF_ERR("FactoryReset via rpc-sys failed, trying defaultreset"); + dmcmd_no_wait("/sbin/defaultreset", 0); + sleep(5); // Wait for reboot to happen + BBF_ERR("FactoryReset call failed!!!"); +} + /************************************************************* * OPERATE COMMANDS *************************************************************/ static int operate_Device_Reboot(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { - int res = dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0); + int res = bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); if (res) bbfdm_set_fault_message(ctx, "Reboot: ubus 'system reboot' method doesn't exist"); return !res ? 0 : USP_FAULT_COMMAND_FAILURE; } static int operate_Device_FactoryReset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { - int res = dmcmd_no_wait("/sbin/defaultreset", 0); + int res = bbfdm_task_fork(_exec_factoryreset, NULL, NULL, NULL); if (res) bbfdm_set_fault_message(ctx, "FactoryReset: '/sbin/defaultreset' command doesn't exist"); return !res ? 0 : USP_FAULT_COMMAND_FAILURE; } diff --git a/libbbfdm/deviceinfo.c b/libbbfdm/deviceinfo.c index b58c94bc..c28f2d73 100644 --- a/libbbfdm/deviceinfo.c +++ b/libbbfdm/deviceinfo.c @@ -731,15 +731,9 @@ static int bbf_fw_image_download(const char *url, const char *auto_activate, con goto end; } - // Reboot the device if auto activation is true + // Schedule a device Reboot, if auto activation is true if (activate) { - // Send the transfer complete after image applied - send_transfer_complete_event(command, obj_path, url, fault_msg, start_time, complete_time, commandKey, "Download"); - - sleep(5); // added additional buffer for TransferComplete! event - if (dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0) != 0) - res = -1; - sleep(10); // Wait for reboot to take action + bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); } end: @@ -1698,6 +1692,17 @@ static int get_operate_args_DeviceInfoFirmwareImage_Activate(char *refparam, str return 0; } +void _exec_reboot(const void *arg1, const void *arg2) +{ + sleep(3); // Wait for reboot to happen + dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0); + sleep(5); // Wait for reboot to happen + BBF_ERR("Reboot call failed with rpc-sys, trying again with system"); + dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0); + sleep(5); // Wait for reboot + BBF_ERR("Reboot call failed!!!"); +} + static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { #define CRONTABS_ROOT "/etc/crontabs/root" @@ -1799,8 +1804,7 @@ static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx if (strcasecmp(status, "true") != 0) return USP_FAULT_COMMAND_FAILURE; - res = dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0); - sleep(10); // Wait for reboot to happen + bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); } return res ? USP_FAULT_COMMAND_FAILURE : 0; diff --git a/libbbfdm/deviceinfo.h b/libbbfdm/deviceinfo.h index 2233988b..c2e39d2d 100644 --- a/libbbfdm/deviceinfo.h +++ b/libbbfdm/deviceinfo.h @@ -26,4 +26,5 @@ extern DMLEAF tDeviceInfoProcessorParams[]; extern DMLEAF tDeviceInfoSupportedDataModelParams[]; extern DMLEAF tDeviceInfoFirmwareImageParams[]; +void _exec_reboot(const void *arg1, const void *arg2); #endif