Skip to content

Commit c2e3845

Browse files
committed
boards: native_sim: add reboot for native sim
Add a reboot implementation for the native sim which restarts the current executable keeping the command line arguments after closing all open file descriptors. Signed-off-by: Adrian Friedli <[email protected]>
1 parent c3646a3 commit c2e3845

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

boards/native/native_sim/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ zephyr_library_sources(
1313
posix_arch_if.c
1414
)
1515

16+
if(CONFIG_REBOOT)
17+
zephyr_library_sources_ifndef(CONFIG_POSIX_API reboot.c)
18+
endif()
19+
1620
zephyr_include_directories(
1721
${NSI_DIR}/common/src/include
1822
${NSI_DIR}/native/src/include

boards/native/native_sim/reboot.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (c) 2025 GARDENA GmbH
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "posix_board_if.h"
8+
9+
#include <errno.h>
10+
#include <stdio.h>
11+
#include <string.h>
12+
13+
#include <zephyr/kernel.h>
14+
15+
#include <fcntl.h>
16+
#include <unistd.h>
17+
18+
/* arbitrary sizes */
19+
#define CMDLINE_BUF_SIZE 4096
20+
#define ARGV_BUF_SIZE 1024
21+
22+
static const char module[] = "native_sim_reboot";
23+
24+
static ssize_t read_cmdline(char cmdline[], size_t *len)
25+
{
26+
int fd = open("/proc/self/cmdline", O_RDONLY);
27+
28+
if (fd < 0) {
29+
perror(module);
30+
return fd;
31+
}
32+
33+
*len = 0;
34+
for (ssize_t read_len = -1; read_len != 0;) {
35+
if (*len >= CMDLINE_BUF_SIZE) {
36+
fprintf(stderr, "%s: Command line is too long.\n", module);
37+
close(fd);
38+
return -1;
39+
}
40+
/* the last byte in cmdline is not used */
41+
read_len = read(fd, cmdline + *len, CMDLINE_BUF_SIZE - *len);
42+
if (read_len < 0) {
43+
perror(module);
44+
close(fd);
45+
return read_len;
46+
}
47+
*len += read_len;
48+
}
49+
50+
close(fd);
51+
52+
/* ensure null termination, in case 0 bytes were read */
53+
cmdline[*len] = '\0';
54+
return 0;
55+
}
56+
57+
static int get_args(char cmdline[], size_t len, char *argv[])
58+
{
59+
char *p = cmdline;
60+
size_t i = 0;
61+
62+
while (p < cmdline + len) {
63+
if (i + 1 >= ARGV_BUF_SIZE) {
64+
fprintf(stderr, "%s: Command line has too many arguments.\n", module);
65+
return -1;
66+
}
67+
argv[i] = p;
68+
p += strlen(p) + 1;
69+
i++;
70+
}
71+
argv[i] = NULL;
72+
return 0;
73+
}
74+
75+
static long close_open_fds(void)
76+
{
77+
/* close all open file descriptors except 0-2 */
78+
errno = 0;
79+
80+
long max_fd = sysconf(_SC_OPEN_MAX);
81+
82+
if (max_fd < 0) {
83+
if (errno != 0) {
84+
perror(module);
85+
} else {
86+
fprintf(stderr,
87+
"%s: Cannot determine maximum number of file descriptors.\n",
88+
module);
89+
}
90+
return max_fd;
91+
}
92+
for (int fd = 3; fd < max_fd; fd++) {
93+
close(fd);
94+
}
95+
return 0;
96+
}
97+
98+
/* overriding a weak function */
99+
void sys_arch_reboot(int type)
100+
{
101+
char cmdline[CMDLINE_BUF_SIZE];
102+
size_t len = 0;
103+
104+
if (read_cmdline(cmdline, &len) < 0) {
105+
posix_exit(1);
106+
}
107+
108+
char *argv[ARGV_BUF_SIZE];
109+
110+
if (get_args(cmdline, len, argv) < 0) {
111+
posix_exit(1);
112+
}
113+
114+
k_sched_lock();
115+
116+
if (close_open_fds() < 0) {
117+
posix_exit(1);
118+
}
119+
120+
fprintf(stderr, "%s: Restarting process.\n", module);
121+
122+
int res = execv("/proc/self/exe", argv);
123+
124+
if (res < 0) {
125+
perror(module);
126+
posix_exit(1);
127+
}
128+
129+
fprintf(stderr, "%s: Failed to restart process, exiting.\n", module);
130+
posix_exit(1);
131+
}

0 commit comments

Comments
 (0)