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;
1717/// afterward, you should call this before doing so.
1818void __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
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 deleted
lib/libc/wasi/libc-bottom-half/sources/__wasilibc_fd_renumber.c+3
......@@ -4,6 +4,9 @@
44#include <unistd.h>
55
66int __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+102-9
......@@ -25,6 +25,7 @@ typedef struct preopen {
2525} preopen;
2626
2727/// A simple growable array of `preopen`.
28static _Atomic _Bool preopens_populated = false;
2829static preopen *preopens;
2930static size_t num_preopens;
3031static size_t preopen_capacity;
......@@ -100,12 +101,9 @@ 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`.
106static 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.
106static int internal_register_preopened_fd_unlocked(__wasi_fd_t fd, const char *relprefix) {
109107 // Check preconditions.
110108 assert_invariants();
111109 assert(fd != AT_FDCWD);
......@@ -113,22 +111,32 @@ static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix)
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`.
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
132140/// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`?
133141static 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
154162int __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,
172182int __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)))
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{
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",