Skip to content

Commit 8a8da49

Browse files
jedisct1alexrp
authored andcommitted
Re-add lazy preopen changes
1 parent 3f4c43b commit 8a8da49

File tree

5 files changed

+109
-10
lines changed

5 files changed

+109
-10
lines changed

lib/libc/include/wasm-wasi-musl/wasi/libc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ struct timespec;
1717
/// afterward, you should call this before doing so.
1818
void __wasilibc_populate_preopens(void);
1919

20+
/// Reset the preopens table to an uninitialized state, forcing it to be
21+
/// reinitialized next time it is needed.
22+
void __wasilibc_reset_preopens(void);
23+
2024
/// Register the given pre-opened file descriptor under the given path.
2125
///
2226
/// This function does not take ownership of `prefix` (it makes its own copy).

lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/unistd/close.c

Whitespace-only changes.

lib/libc/wasi/libc-bottom-half/sources/__wasilibc_fd_renumber.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#include <unistd.h>
55

66
int __wasilibc_fd_renumber(int fd, int newfd) {
7+
// Scan the preopen fds before making any changes.
8+
__wasilibc_populate_preopens();
9+
710
__wasi_errno_t error = __wasi_fd_renumber(fd, newfd);
811
if (error != 0) {
912
errno = error;

lib/libc/wasi/libc-bottom-half/sources/preopens.c

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef struct preopen {
2525
} preopen;
2626

2727
/// A simple growable array of `preopen`.
28+
static _Atomic _Bool preopens_populated = false;
2829
static preopen *preopens;
2930
static size_t num_preopens;
3031
static size_t preopen_capacity;
@@ -100,35 +101,42 @@ static const char *strip_prefixes(const char *path) {
100101
return path;
101102
}
102103

103-
/// Register the given preopened file descriptor under the given path.
104-
///
105-
/// This function takes ownership of `prefix`.
106-
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
107-
LOCK(lock);
108-
104+
/// Similar to `internal_register_preopened_fd_unlocked` but does not
105+
/// take a lock.
106+
static int internal_register_preopened_fd_unlocked(__wasi_fd_t fd, const char *relprefix) {
109107
// Check preconditions.
110108
assert_invariants();
111109
assert(fd != AT_FDCWD);
112110
assert(fd != -1);
113111
assert(relprefix != NULL);
114112

115113
if (num_preopens == preopen_capacity && resize() != 0) {
116-
UNLOCK(lock);
117114
return -1;
118115
}
119116

120117
char *prefix = strdup(strip_prefixes(relprefix));
121118
if (prefix == NULL) {
122-
UNLOCK(lock);
123119
return -1;
124120
}
125121
preopens[num_preopens++] = (preopen) { prefix, fd, };
126122

127123
assert_invariants();
128-
UNLOCK(lock);
129124
return 0;
130125
}
131126

127+
/// Register the given preopened file descriptor under the given path.
128+
///
129+
/// This function takes ownership of `prefix`.
130+
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
131+
LOCK(lock);
132+
133+
int r = internal_register_preopened_fd_unlocked(fd, relprefix);
134+
135+
UNLOCK(lock);
136+
137+
return r;
138+
}
139+
132140
/// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`?
133141
static bool prefix_matches(const char *prefix, size_t prefix_len, const char *path) {
134142
// Allow an empty string as a prefix of any relative path.
@@ -152,6 +160,8 @@ static bool prefix_matches(const char *prefix, size_t prefix_len, const char *pa
152160

153161
// See the documentation in libc.h
154162
int __wasilibc_register_preopened_fd(int fd, const char *prefix) {
163+
__wasilibc_populate_preopens();
164+
155165
return internal_register_preopened_fd((__wasi_fd_t)fd, prefix);
156166
}
157167

@@ -172,6 +182,8 @@ int __wasilibc_find_relpath(const char *path,
172182
int __wasilibc_find_abspath(const char *path,
173183
const char **abs_prefix,
174184
const char **relative_path) {
185+
__wasilibc_populate_preopens();
186+
175187
// Strip leading `/` characters, the prefixes we're mataching won't have
176188
// them.
177189
while (*path == '/')
@@ -218,3 +230,84 @@ int __wasilibc_find_abspath(const char *path,
218230
*relative_path = computed;
219231
return fd;
220232
}
233+
234+
__attribute__((constructor(51)))
235+
void __wasilibc_populate_preopens(void) {
236+
// Fast path: If the preopens are already initialized, do nothing.
237+
if (preopens_populated) {
238+
return;
239+
}
240+
241+
LOCK(lock);
242+
243+
// Check whether another thread initialized the preopens already.
244+
if (preopens_populated) {
245+
UNLOCK(lock);
246+
return;
247+
}
248+
249+
// Skip stdin, stdout, and stderr, and count up until we reach an invalid
250+
// file descriptor.
251+
for (__wasi_fd_t fd = 3; fd != 0; ++fd) {
252+
__wasi_prestat_t prestat;
253+
__wasi_errno_t ret = __wasi_fd_prestat_get(fd, &prestat);
254+
if (ret == __WASI_ERRNO_BADF)
255+
break;
256+
if (ret != __WASI_ERRNO_SUCCESS)
257+
goto oserr;
258+
switch (prestat.tag) {
259+
case __WASI_PREOPENTYPE_DIR: {
260+
char *prefix = malloc(prestat.u.dir.pr_name_len + 1);
261+
if (prefix == NULL)
262+
goto software;
263+
264+
// TODO: Remove the cast on `prefix` once the witx is updated with
265+
// char8 support.
266+
ret = __wasi_fd_prestat_dir_name(fd, (uint8_t *)prefix,
267+
prestat.u.dir.pr_name_len);
268+
if (ret != __WASI_ERRNO_SUCCESS)
269+
goto oserr;
270+
prefix[prestat.u.dir.pr_name_len] = '\0';
271+
272+
if (internal_register_preopened_fd_unlocked(fd, prefix) != 0)
273+
goto software;
274+
free(prefix);
275+
276+
break;
277+
}
278+
default:
279+
break;
280+
}
281+
}
282+
283+
// Preopens are now initialized.
284+
preopens_populated = true;
285+
286+
UNLOCK(lock);
287+
288+
return;
289+
oserr:
290+
_Exit(EX_OSERR);
291+
software:
292+
_Exit(EX_SOFTWARE);
293+
}
294+
295+
void __wasilibc_reset_preopens(void) {
296+
LOCK(lock);
297+
298+
if (num_preopens) {
299+
for (int i = 0; i < num_preopens; ++i) {
300+
free((void*) preopens[i].prefix);
301+
}
302+
free(preopens);
303+
}
304+
305+
preopens_populated = false;
306+
preopens = NULL;
307+
num_preopens = 0;
308+
preopen_capacity = 0;
309+
310+
assert_invariants();
311+
312+
UNLOCK(lock);
313+
}

src/wasi_libc.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@ const libc_bottom_half_src_files = [_][]const u8{
463463
"wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c",
464464
"wasi/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c",
465465
"wasi/libc-bottom-half/cloudlibc/src/libc/time/time.c",
466-
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/close.c",
467466
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c",
468467
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c",
469468
"wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c",

0 commit comments

Comments
 (0)