Make some minor fixups to bug reporting, etc.

This commit is contained in:
Justine Tunney 2022-07-11 05:55:17 -07:00
parent 84764ce7b8
commit 3f015b1e51
31 changed files with 244 additions and 134 deletions

View file

@ -309,7 +309,7 @@ void LoadRelationships(int argc, char *argv[]) {
for (i = 0; i < threads; ++i) {
if (_spawn(LoadRelationshipsWorker, (void *)(intptr_t)i, th + i) == -1) {
pthread_mutex_lock(&reportlock);
kprintf("error: clone(%d) failed %m\n", i);
kprintf("error: _spawn(%d) failed %m\n", i);
exit(1);
}
}
@ -420,7 +420,7 @@ void Explore(void) {
for (i = 0; i < threads; ++i) {
if (_spawn(Diver, (void *)(intptr_t)i, th + i) == -1) {
pthread_mutex_lock(&reportlock);
kprintf("error: clone(%d) failed %m\n", i);
kprintf("error: _spawn(%d) failed %m\n", i);
exit(1);
}
}

View file

@ -2015,6 +2015,48 @@ UNIX MODULE
This system call returns twice. The parent process gets the nonzero
pid. The child gets zero.
Here's a simple usage example of creating subprocesses, where we
fork off a child worker from a main process hook callback to do some
independent chores, such as sending an HTTP request back to redbean.
-- as soon as server starts, make a fetch to the server
-- then signal redbean to shutdown when fetch is complete
local onServerStart = function()
if assert(unix.fork()) == 0 then
local ok, headers, body = Fetch('http://127.0.0.1:8080/test')
unix.kill(unix.getppid(), unix.SIGTERM)
unix.exit(0)
end
end
OnServerStart = onServerStart
We didn't need to use wait() here, because (a) we want redbean to go
back to what it was doing before as the Fetch() completes, and (b)
redbean's main process already has a zombie collector. However it's
a moot point, since once the fetch is done, the child process then
asks redbean to gracefully shutdown by sending SIGTERM its parent.
This is actually a situation where we *must* use fork, because the
purpose of the main redbean process is to call accept() and create
workers. So if we programmed redbean to use the main process to send
a blocking request to itself instead, then redbean would deadlock
and never be able to accept() the client.
While deadlocking is an extreme example, the truth is that latency
issues can crop up for the same reason that just cause jitter
instead, and as such, can easily go unnoticed. For example, if you
do something that takes longer than a few milliseconds from inside
your redbean heartbeat, then that's a few milliseconds in which
redbean is no longer concurrent, and tail latency is being added to
its ability to accept new connections. fork() does a great job at
solving this.
If you're not sure how long something will take, then when in doubt,
fork off a process. You can then report its completion to something
like SQLite. Redbean makes having lots of processes cheap. On Linux
they're about as lightweight as what heavyweight environments call
greenlets. You can easily have 10,000 Redbean workers on one PC.
Here's some benchmarks for fork() performance across platforms:
Linux 5.4 fork l: 97,200𝑐 31,395𝑛𝑠 [metal]

View file

@ -82,7 +82,7 @@ int main(int argc, char *argv[]) {
if (IsWindows() && !IsAtLeastWindows10()) {
plan(0x50000000, 0x7ffdffff, "arena");
}
x = (intptr_t)GetStaticStackAddr(0);
x = GetStaticStackAddr(0);
y = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE);
plan(x - y, x - 1, "winargs");
plan(x, x + GetStackSize() - 1, "stack");