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