feat(process): fork/exec/id/session + system/popen
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user