pub unsafe fn clone3(args: &CloneArgs) -> Result<CloneResult, Errno>Expand description
Crée un nouveau processus via le syscall clone3(2).
Cf. docs/specs/layer-0/family-process.md section clone3. La fonction
retourne deux fois en cas de succès : une fois côté parent (avec le
PID enfant, et un PidFd si [CloneFlags::PIDFD] était positionné),
une fois côté enfant (avec [CloneResult::Child]). Le match sur le
résultat est le seul moyen sûr de discriminer.
§Périmètre
clone3 est dédié à la création de processus style fork ; la création
de thread passe par clone_thread (modèle de retour distinct, cf. sa
doc et la note d’implémentation au-dessus de clone_thread) :
args.flagspeut contenir tous les bits hors [CloneFlags::VM] / [CloneFlags::THREAD] / [CloneFlags::SIGHAND] : ces drapeaux de création de thread sont refusés ici avec [Errno::EINVAL] (leur retourCloneResult::Childserait unsound sur une pile neuve — voirclone_thread).args.stackdoit êtreNone(refusé sinon avec [Errno::EINVAL] ; une pile dédiée n’a de sens que pour un thread →clone_thread).args.exit_signalest typiquementSome(Signal::SIGCHLD).
§Safety
clone3 peut créer un thread partageant la mémoire avec le parent
(CLONE_VM), situation que Rust ne peut pas vérifier. L’appelant doit
donc garantir, selon le scénario :
-
Fork classique (sans
CLONE_VM) — aucune précondition particulière sur la mémoire. L’enfant possède une copie CoW de l’espace d’adressage du parent ; tous les invariants Rust restent valables des deux côtés. -
Création de thread (
CLONE_VM | CLONE_THREAD | CLONE_SIGHAND) — non géré parclone3; l’appel échoue avec [Errno::EINVAL]. Utiliserclone_thread, qui exécute le thread via un trampoline assembleur (pas de retour Rust sur pile neuve) et expose le join parCLONE_CHILD_CLEARTID. -
Namespaces (
CLONE_NEWUSER,CLONE_NEWNS,CLONE_NEWPID, …) — l’appelant doit posséder les capabilities nécessaires (typiquementCAP_SYS_ADMIN) ; à défaut, le syscall retourne [Errno::EPERM]. Sur Ubuntu 24.04, les user namespaces non privilégiés sont restreints par AppArmor (kernel.apparmor_restrict_unprivileged_userns=1) et l’appel échoue avec [Errno::EPERM] même côté unprivileged. -
« Retourne deux fois » — après succès, le syscall est exécuté côté parent et côté enfant ; les deux retours apparaissent ici comme
Ok(_)distincts. L’enfant doit terminer son travail (typiquement parstd::process::exitou un futurexit_groupwrapper) ; revenir « plus loin » dans le code appelant produit généralement un comportement surprenant pour l’utilisateur.
§Errors
- [
Errno::EINVAL] : combinaison de flags refusée par cette PR (création de thread) ou par le kernel (configuration invalide). - [
Errno::EPERM] : capabilities insuffisantes (NEWUSER refusé, AppArmor, …). EAGAIN(constante non encore définie dans le stub partielErrno) : limites système atteintes (nombre de processus).ENOMEM(idem) : mémoire kernel insuffisante.EUSERS(idem) : trop de namespaces utilisateurs créés.ENOSYS(idem) : kernel antérieur à 5.3 (clone3indisponible).
Les constantes nommées en prose ci-dessus seront promues en
pub const au fil des PRs qui les rencontrent réellement
(cf. note « stub partiel » en tête du module errno).