1 /*
2 * Copyright (c) 2025 GARDENA GmbH
3 * Copyright (c) 2025 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stdbool.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <nsi_main.h>
13 #include <nsi_tasks.h>
14 #include <nsi_tracing.h>
15 #include <nsi_cmdline.h>
16
17 static const char module[] = "native_sim_reboot";
18
close_open_fds(void)19 static long close_open_fds(void)
20 {
21 /* close all open file descriptors except 0-2 */
22 errno = 0;
23
24 long max_fd = sysconf(_SC_OPEN_MAX);
25
26 if (max_fd < 0) {
27 if (errno != 0) {
28 nsi_print_error_and_exit("%s: %s\n", module, strerror(errno));
29 } else {
30 nsi_print_warning("%s: Cannot determine maximum number of file descriptors"
31 "\n",
32 module);
33 }
34 return max_fd;
35 }
36 for (int fd = 3; fd < max_fd; fd++) {
37 (void)close(fd);
38 }
39 return 0;
40 }
41
42 static bool reboot_on_exit;
43
native_set_reboot_on_exit(void)44 void native_set_reboot_on_exit(void)
45 {
46 reboot_on_exit = true;
47 }
48
maybe_reboot(void)49 void maybe_reboot(void)
50 {
51 char **argv;
52 int argc;
53
54 if (!reboot_on_exit) {
55 return;
56 }
57
58 reboot_on_exit = false; /* If we reenter it means we failed to reboot */
59
60 nsi_get_cmd_line_args(&argc, &argv);
61
62 if (close_open_fds() < 0) {
63 nsi_exit(1);
64 }
65
66 nsi_print_warning("%s: Restarting process.\n", module);
67
68 (void)execv("/proc/self/exe", argv);
69
70 nsi_print_error_and_exit("%s: Failed to restart process, exiting (%s)\n", module,
71 strerror(errno));
72 }
73
74 NSI_TASK(maybe_reboot, ON_EXIT_POST, 999);
75