iv_wait(3)
π iv_wait β the ivykis wait4(2) wrapper, bestie edition π
okay so this is iv_wait(3) from the ivykis programmer's manual and it's literally the group chat between your event loop and your child processes π«Ά
β¨ NAME β¨
IV_WAIT_INTEREST_INIT, iv_wait_interest_register, iv_wait_interest_register_spawn, iv_wait_interest_unregister, iv_wait_interest_kill β all of them, together, are the ivykis wait4(2) wrapper. that's the whole vibe π
πΈ SYNOPSIS πΈ
#include <iv_wait.h>
struct iv_wait_interest {
pid_t pid;
void *cookie;
void (*handler)(void *cookie, int status,
const struct rusage *rusage);
};
void IV_WAIT_INTEREST_INIT(struct iv_wait_interest *this);
int iv_wait_interest_register(struct iv_wait_interest *this);
int iv_wait_interest_register_spawn(struct iv_wait_interest *this, void
(*fn)(void *), void *cookie);
void iv_wait_interest_unregister(struct iv_wait_interest *this);
int iv_wait_interest_kill(const struct iv_wait_interest *this, int sig);
π¦ DESCRIPTION π¦
okay so iv_wait is an ivykis(3) wrapper around wait4(2), and what it does is integrate process state change notification with the ivykis event loop. it's giving matchmaker energy, but for processes π
so if your ivykis app wants to know when a process changes state, you register a struct iv_wait_interest object by calling iv_wait_interest_register. but first you gotta initialise it with IV_WAIT_INTEREST_INIT, and then fill in the ->pid, ->cookie and ->handler members. order matters, no cap π«Ά
alternatively β and this is the iconic part β your ivykis app can use iv_wait_interest_register_spawn to atomically fork off a child process and register a struct iv_wait_interest for it in one go β¨
and when it says 'atomically', bestie, it means: the call to iv_wait_interest_register_spawn will be serialised with respect to invocations of wait4(2). why does that matter?? because it closes the race where process state change notifications can occur and be delivered between forking off the child process and registering a struct iv_wait_interest for the child's pid. that race is a whole villain arc and we are NOT doing it π
the child process will run the function given by the iv_wait_interest_register_spawn argument fn, with argument cookie as its argument. yes. cookie is the argument. it's cookies all the way down π
so once a process state change occurs β as indicated by delivery of a SIGCHLD signal to the current process β iv_wait does the whole routine:
- calls
wait4(2)to return information about the process state change π - looks up the returned process ID in the set of registered
struct iv_wait_interestobjects π - and if there's a registered interest with a matching
->pidfield, it arranges for that object's callback function to be called in the thread that the object was registered in π§΅
notifications keep getting delivered to the object's callback function until either iv_wait_interest_unregister is called on the object, or until a WIFEXITED or WIFSIGNALED status for this pid is returned by wait4(2). periodt β
important, bestie: delivery of aWIFEXITEDorWIFSIGNALEDstatus does not automatically unregister the object. this always needs to be done explicitly. the library will not do it for you, she's not your mom π
π the rules of unregistering
unregistering a struct iv_wait_interest object can only be done from the thread that that object was registered in. thread loyalty fr fr π«Ά
but within that thread, it can safely be done from β and its underlying memory allocation can safely be freed from β its own callback function. iconic. self-referential. main character energy π
lowkey scary: registering multiple struct iv_wait_interest objects for the same process ID will produce undefined behavior. do not. just don't. i'm begging π
π₯ sending signals
to send a signal to a child process, use iv_wait_interest_kill. this function will internally serialise with invocations of wait4(2), to avoid the race between sending a signal to a process and collecting a termination notification for that process β which is the thing that makes its pid available for reuse. keeping the pid safe so nobody steals it, we love to see it π
π§ under the hood
internally, iv_wait is implemented using iv_signal(3) and iv_event(3). that's the whole magic trick, don't look behind the curtain π
π SEE ALSO π
that's the whole page, bestie β go forth and wait4 responsibly πβ¨
this was brought to you by ivykis, dated 2010-09-03, and yeah the date is ancient but she's still slaying π πΈπ¦
π¦ where this page comes from
- alpine 3.22: ivykis-doc 0.43.2-r0 Β· LGPL-2.1-or-later
- alpine 3.23: ivykis-doc 0.43.2-r0 Β· LGPL-2.1-or-later
- alpine 3.24: ivykis-doc 0.43.2-r0 Β· LGPL-2.1-or-later
- debian bookworm: libivykis-dev 0.42.4-1
- debian trixie: libivykis-dev 0.43.2-1+b1
- epel 10: ivykis-devel 0.43.2-2.el10_0 Β· LicenseRef-Callaway-LGPLv2+
- epel 9: ivykis-devel 0.42.4-7.el9 Β· LGPLv2+
- fedora 43: ivykis-devel 0.43.2-4.fc43 Β· LicenseRef-Callaway-LGPLv2+
- fedora 43: ivykis-devel 0.43.2-4.fc43 Β· LicenseRef-Callaway-LGPLv2+
- fedora 44: ivykis-devel 0.43.2-5.fc44 Β· LicenseRef-Callaway-LGPLv2+
- fedora 44: ivykis-devel 0.43.2-5.fc44 Β· LicenseRef-Callaway-LGPLv2+
- nixpkgs unstable: libivykis 0.43.2
- opensuse-leap 16.0: ivykis-devel 0.43-bp160.1.12 Β· LGPL-2.1-only
- opensuse-leap 16.0: ivykis-devel 0.43-bp160.1.12 Β· LGPL-2.1-only
- opensuse-leap 16.0: ivykis-devel 0.43-bp160.1.12 Β· LGPL-2.1-only
- opensuse-leap 16.0: ivykis-devel 0.43-bp160.1.12 Β· LGPL-2.1-only
- ubuntu jammy: libivykis-dev 0.42.4-1
- ubuntu noble: libivykis-dev 0.43-1build1
- ubuntu questing: libivykis-dev 0.43.2-1
- ubuntu resolute: libivykis-dev 0.43.2-1build1
- ubuntu stonking: libivykis-dev 0.43.2-1build1
- Copyright (C) 2010 Lennert Buytenhek
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms