Skip to content

Commit e4f4a85

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 e4f4a85

File tree

2 files changed

+137
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)