]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/posix-fdtab: Handle fdtab duplication on clone
authorAndrei Tatar <andrei@unikraft.io>
Tue, 23 Jan 2024 18:44:06 +0000 (19:44 +0100)
committerUnikraft Bot <monkey@unikraft.io>
Sun, 23 Feb 2025 10:29:25 +0000 (10:29 +0000)
This change adds logic to handle fdtab references on clone:
- if  CLONE_FILES: child inherits a reference to parent's tab
- if !CLONE_FILES: child allocates new fdtab duplicate of parent's,
  populated with new references to the same open file descriptions hosted
  by the parent fdtab.

The initial duplication logic is rudimentary and does not provide any
ordering guarantees w.r.t. syscalls modifying the original table (open,
dup, close), under the assumption that it won't trigger race conditions
in the wild. Please revisit if this turns out to be overly optimistic.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Approved-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
GitHub-Closes: #1278

lib/posix-fdtab/Config.uk
lib/posix-fdtab/fdtab.c

index 4f18491f2f06ddf454631723a684ce2c1bcf21f7..12116f7ddec5473a47796f0c2190f57f4d4b6fa7 100644 (file)
@@ -12,6 +12,7 @@ if LIBPOSIX_FDTAB
        # Hidden, will autoselect when required
        config LIBPOSIX_FDTAB_MULTITAB
        bool
+       default y if LIBPOSIX_PROCESS_CLONE
        select LIBUKSCHED
 
        # Hidden, selected by core components when needed
index 39bbcb50cbeebdf1523848d02af249641c023ded..c7f04f88a0e876ec0c8637cb0608481892e6b710 100644 (file)
 #include <uk/posix-fdtab-legacy.h>
 #endif /* CONFIG_LIBPOSIX_FDTAB_LEGACY_SHIM */
 
+#if CONFIG_LIBPOSIX_PROCESS_CLONE
+#include <uk/process.h>
+#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
+
 #if CONFIG_LIBPOSIX_PROCESS_EXECVE
 #include <uk/event.h>
 #include <uk/prio.h>
@@ -503,6 +507,38 @@ static void fdtab_thread_term(struct uk_thread *child)
 
 UK_THREAD_INIT(fdtab_thread_init, fdtab_thread_term);
 
+#if CONFIG_LIBPOSIX_PROCESS_CLONE
+static int fdtab_clone(const struct clone_args *cl_args,
+                      size_t cl_args_len __unused,
+                      struct uk_thread *child,
+                      struct uk_thread *parent)
+{
+       struct uk_fdtab *tab = uk_thread_uktls_var(parent, active_fdtab);
+       struct uk_fdtab *newtab;
+
+       UK_ASSERT(tab); /* Do not call clone from raw threads */
+       if (cl_args->flags & CLONE_FILES) {
+               /* Inherit parent's fdtab */
+               /* As a compat stop-gap, the raw thread already inherited the
+                * parent's fdtab ref; we don't need to do anything.
+                *
+                * TODO: move inheritance here once stopgap is removed.
+                */
+               UK_ASSERT(uk_thread_uktls_var(child, active_fdtab) == tab);
+               return 0;
+       } else {
+               /* Duplicate parent's fdtab */
+               newtab = fdtab_duplicate(tab);
+               if (unlikely(!newtab))
+                       return -ENOMEM;
+       }
+       uk_thread_uktls_var(child, active_fdtab) = newtab;
+       return 0;
+}
+
+UK_POSIX_CLONE_HANDLER(CLONE_FILES, 0, fdtab_clone, 0);
+
+#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */
 #endif /* CONFIG_LIBPOSIX_FDTAB_MULTITAB */
 
 /* Init fdtab as early as possible, to enable functions that rely on fds */