feat(process): fork/exec/id/session + system/popen

This commit is contained in:
2026-09-05 16:55:14 -04:00
parent c9e9676d38
commit 14c6fd6cf6
19 changed files with 2118 additions and 2 deletions
+111
View File
@@ -0,0 +1,111 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include "atfork_impl.h"
#include "../internal/malloc.h"
/*
* The atfork hook table (todo 20).
*
* The list is a doubly linked chain in registration order (head = oldest
* registration). fork() runs the phases through __vlibc_atfork_prepare/
* parent/child around the syscall; pthread_atfork (todo 45) appends
* entries via __vlibc_atfork_register. Nodes live on the malloc heap:
* registration happens long after the allocator is up, and fork() itself
* never allocates — the phases only walk the existing chain.
*
* Phase order (POSIX 1003.1-2008 pthread_atfork):
* - prepare: reverse registration order (tail to head);
* - parent and child: registration order (head to tail).
*/
struct vlibc_atfork_entry *volatile __vlibc_atfork_list = 0;
// NOLINTBEGIN(bugprone-easily-swappable-parameters)
int
__vlibc_atfork_register(void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
struct vlibc_atfork_entry *node;
struct vlibc_atfork_entry *tail;
node = (struct vlibc_atfork_entry *)__libc_malloc(sizeof(*node));
if (node == 0)
{
errno = ENOMEM;
return -1;
}
node->prepare = prepare;
node->parent = parent;
node->child = child;
node->prev = 0;
node->next = 0;
/* Append at the tail so the chain stays in registration order. */
if (__vlibc_atfork_list == 0)
{
__vlibc_atfork_list = node;
return 0;
}
tail = __vlibc_atfork_list;
while (tail->next != 0)
{
tail = tail->next;
}
tail->next = node;
node->prev = tail;
return 0;
}
// NOLINTEND(bugprone-easily-swappable-parameters)
void
__vlibc_atfork_prepare(void)
{
struct vlibc_atfork_entry *node = __vlibc_atfork_list;
/* Reverse registration order: walk to the tail, then back. */
while (node != 0 && node->next != 0)
{
node = node->next;
}
for (; node != 0; node = node->prev)
{
if (node->prepare != 0)
{
node->prepare();
}
}
}
void
__vlibc_atfork_parent(void)
{
struct vlibc_atfork_entry *node;
/* Registration order. */
for (node = __vlibc_atfork_list; node != 0; node = node->next)
{
if (node->parent != 0)
{
node->parent();
}
}
}
void
__vlibc_atfork_child(void)
{
struct vlibc_atfork_entry *node;
/* Registration order. */
for (node = __vlibc_atfork_list; node != 0; node = node->next)
{
if (node->child != 0)
{
node->child();
}
}
}