Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-045 — Modèle d’erreurs de l’ABI C : AirStatus in-band, sans errno, panic = abort

Statut : Accepté (2026-06-26, validé par le BDFL). Companion d’ADR-019 (modèle d’erreurs hybride), d’ADR-027 (doc ABI C) et d’ADR-012 (stabilité ABI 10 ans). Réalise la doctrine libc (vision « libc Rust Air » + « kernel = bible, pas de globale libc ») au niveau de la frontière C. Cadrage détaillé : docs/draft/abi-c-t1-design-fr.md.

Catégorie : Architecture (ABI C — contrat, transverse à toute la surface C-ABI).

Contexte

La première passe ABI C (crate air-base-capilibair-base.so, ADR-027 addendum C) doit décider comment les erreurs traversent la frontière C — décision contractuelle (ABI 10 ans) qui fera précédent pour toute la future libc Air.

POSIX/glibc utilisent errno : un canal hors-bande, thread-local aujourd’hui mais implicite (posé en effet de bord, absent de la signature, oublié, écrasé par un appel intermédiaire, non composable). La doctrine Air le refuse : pas de globale inventée par la libc, erreurs in-band, fidèles au kernel (qui rend -errno dans le registre de retour — c’est la libc qui ajoute la couche errno par-dessus).

Par ailleurs, aucune panic Rust ne doit traverser l’ABI (ADR-027 §B.2) ; et Air ne provoque aucune panic (Principes 2/3) — une panic = un bug.

Décision

  1. AirStatus rendu in-band : enum #[repr(C)] retourné comme valeur de retour de chaque pub extern "C", AIR_STATUS_OK = 0. Sur-ensemble d’AirErrorKind (miroir 1..=13) + codes propres à la frontière (AIR_STATUS_NULL_ARGUMENT = 100, AIR_STATUS_BUFFER_TOO_SMALL = 101). Discriminants explicites et committés (stabilité ABI, ADR-012).

  2. Aucun errno, aucune globale, aucun canal hors-bande. Les *out-params ne sont écrits que sur AIR_STATUS_OK. Validation amont des pointeurs : tout pointeur requis NULLAIR_STATUS_NULL_ARGUMENT, jamais de déréférencement (Principe 4).

  3. Message humain par chaîne statique : air_status_message(AirStatus) -> *const c_char rend une chaîne const statique (+0, jamais libérée), façon strerror mais sans état global ni locale. Le message dynamique d’AirError (contexte riche) n’est pas transporté en T1 (différé ; à réinstruire si un besoin réel apparaît).

  4. panic = "abort" (fail-fast) : aucune panic n’est voulue (panic = bug Air) → pas de catch_unwind, pas de statut AIR_PANIC. Un bug tue le process au point de faute, bruyamment, sans état douteux qui continue. Mémoire-sûr : même sous unwind, une panic atteignant une frontière extern "C" abort (Rust ≥ 1.81), jamais d’UB. La cdylib release est buildée panic = "abort" ; Cargo build les cibles de test en unwind automatiquement (libtest / should_panic / proptest intacts).

Conséquences

  • + Fidèle au kernel (in-band), zéro globale libc, erreurs visibles dans la signature → transparence (« dit ce qu’elle fait »). Convention d’erreur unique pour toute la future libc.
  • + ABI simple en T1 : aucun objet erreur à allouer/libérer (ownership trivial).
  • + panic = abort simplifie l’ABI (pas d’AIR_PANIC) et reste honnête (un bug est un bug).
  • Du code C attendant errno ne porte pas tel quel → adaptation requise (ou shim errno opt-in ultérieur — différé, réintroduirait le smell).
  • Le message dynamique (contexte riche d’AirError) est reporté.

Alternatives écartées

  • errno-style (globale / TLS) : rejeté — canal hors-bande implicite qui masque l’erreur ; viole « pas de globale libc » et « dit ce qu’elle fait ». (errno est déjà thread-local dans toute libc à threads : le vrai défaut n’est pas la course mais le caractère hors-bande.)
  • Objet AirError opaque (air_error_message/air_error_free) dès T1 : rejeté pour T1 — introduit propriété mémoire + allocation + fonction de libération prématurément. Réinstruire si le message dynamique devient nécessaire.
  • catch_unwindAIR_PANIC : rejeté — convertit un bug Air en statut « récupérable » que l’appelant peut ignorer, sur un état possiblement douteux ; abort est plus honnête et simplifie l’ABI.