authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2024-04-12 22:51:52+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-01-29 11:54:08+01:00
log8a8da49b5212030d603000d699a8ca9ed92e24cd
treeabf67276ce063f3509372888c823bc4a2fc1e5c3
parent3f4c43b0aac48903b52c7d44b3f89f83064c7d19
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Re-add lazy preopen changes


5 files changed, 109 insertions(+), 10 deletions(-)

lib/libc/include/wasm-wasi-musl/wasi/libc.h+4
...@@ -17,6 +17,10 @@ struct timespec;...@@ -17,6 +17,10 @@ struct timespec;
17/// afterward, you should call this before doing so.17/// afterward, you should call this before doing so.
18void __wasilibc_populate_preopens(void);18void __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.
22void __wasilibc_reset_preopens(void);
23
20/// Register the given pre-opened file descriptor under the given path.24/// Register the given pre-opened file descriptor under the given path.
21///25///
22/// This function does not take ownership of `prefix` (it makes its own copy).26/// 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 deleted
lib/libc/wasi/libc-bottom-half/sources/__wasilibc_fd_renumber.c+3
...@@ -4,6 +4,9 @@...@@ -4,6 +4,9 @@
4#include <unistd.h>4#include <unistd.h>
55
6int __wasilibc_fd_renumber(int fd, int newfd) {6int __wasilibc_fd_renumber(int fd, int newfd) {
7 // Scan the preopen fds before making any changes.
8 __wasilibc_populate_preopens();
9
7 __wasi_errno_t error = __wasi_fd_renumber(fd, newfd);10 __wasi_errno_t error = __wasi_fd_renumber(fd, newfd);
8 if (error != 0) {11 if (error != 0) {
9 errno = error;12 errno = error;
lib/libc/wasi/libc-bottom-half/sources/preopens.c+102-9
...@@ -25,6 +25,7 @@ typedef struct preopen {...@@ -25,6 +25,7 @@ typedef struct preopen {
25} preopen;25} preopen;
2626
27/// A simple growable array of `preopen`.27/// A simple growable array of `preopen`.
28static _Atomic _Bool preopens_populated = false;
28static preopen *preopens;29static preopen *preopens;
29static size_t num_preopens;30static size_t num_preopens;
30static size_t preopen_capacity;31static size_t preopen_capacity;
...@@ -100,12 +101,9 @@ static const char *strip_prefixes(const char *path) {...@@ -100,12 +101,9 @@ static const char *strip_prefixes(const char *path) {
100 return path;101 return path;
101}102}
102103
103/// Register the given preopened file descriptor under the given path.104/// Similar to `internal_register_preopened_fd_unlocked` but does not
104///105/// take a lock.
105/// This function takes ownership of `prefix`.106static int internal_register_preopened_fd_unlocked(__wasi_fd_t fd, const char *relprefix) {
106static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
107 LOCK(lock);
108
109 // Check preconditions.107 // Check preconditions.
110 assert_invariants();108 assert_invariants();
111 assert(fd != AT_FDCWD);109 assert(fd != AT_FDCWD);
...@@ -113,22 +111,32 @@ static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix)...@@ -113,22 +111,32 @@ static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix)
113 assert(relprefix != NULL);111 assert(relprefix != NULL);
114112
115 if (num_preopens == preopen_capacity && resize() != 0) {113 if (num_preopens == preopen_capacity && resize() != 0) {
116 UNLOCK(lock);
117 return -1;114 return -1;
118 }115 }
119116
120 char *prefix = strdup(strip_prefixes(relprefix));117 char *prefix = strdup(strip_prefixes(relprefix));
121 if (prefix == NULL) {118 if (prefix == NULL) {
122 UNLOCK(lock);
123 return -1;119 return -1;
124 }120 }
125 preopens[num_preopens++] = (preopen) { prefix, fd, };121 preopens[num_preopens++] = (preopen) { prefix, fd, };
126122
127 assert_invariants();123 assert_invariants();
128 UNLOCK(lock);
129 return 0;124 return 0;
130}125}
131126
127/// Register the given preopened file descriptor under the given path.
128///
129/// This function takes ownership of `prefix`.
130static 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
132/// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`?140/// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`?
133static bool prefix_matches(const char *prefix, size_t prefix_len, const char *path) {141static bool prefix_matches(const char *prefix, size_t prefix_len, const char *path) {
134 // Allow an empty string as a prefix of any relative path.142 // 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...@@ -152,6 +160,8 @@ static bool prefix_matches(const char *prefix, size_t prefix_len, const char *pa
152160
153// See the documentation in libc.h161// See the documentation in libc.h
154int __wasilibc_register_preopened_fd(int fd, const char *prefix) {162int __wasilibc_register_preopened_fd(int fd, const char *prefix) {
163 __wasilibc_populate_preopens();
164
155 return internal_register_preopened_fd((__wasi_fd_t)fd, prefix);165 return internal_register_preopened_fd((__wasi_fd_t)fd, prefix);
156}166}
157167
...@@ -172,6 +182,8 @@ int __wasilibc_find_relpath(const char *path,...@@ -172,6 +182,8 @@ int __wasilibc_find_relpath(const char *path,
172int __wasilibc_find_abspath(const char *path,182int __wasilibc_find_abspath(const char *path,
173 const char **abs_prefix,183 const char **abs_prefix,
174 const char **relative_path) {184 const char **relative_path) {
185 __wasilibc_populate_preopens();
186
175 // Strip leading `/` characters, the prefixes we're mataching won't have187 // Strip leading `/` characters, the prefixes we're mataching won't have
176 // them.188 // them.
177 while (*path == '/')189 while (*path == '/')
...@@ -218,3 +230,84 @@ int __wasilibc_find_abspath(const char *path,...@@ -218,3 +230,84 @@ int __wasilibc_find_abspath(const char *path,
218 *relative_path = computed;230 *relative_path = computed;
219 return fd;231 return fd;
220}232}
233
234__attribute__((constructor(51)))
235void __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;
289oserr:
290 _Exit(EX_OSERR);
291software:
292 _Exit(EX_SOFTWARE);
293}
294
295void __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-1
...@@ -463,7 +463,6 @@ const libc_bottom_half_src_files = [_][]const u8{...@@ -463,7 +463,6 @@ const libc_bottom_half_src_files = [_][]const u8{
463 "wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c",463 "wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c",
464 "wasi/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c",464 "wasi/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c",
465 "wasi/libc-bottom-half/cloudlibc/src/libc/time/time.c",465 "wasi/libc-bottom-half/cloudlibc/src/libc/time/time.c",
466 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/close.c",
467 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c",466 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c",
468 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c",467 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c",
469 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c",468 "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c",