commit - 5b37d9126474864b5299426e27b2af37fcc96dd0
commit + b3a20a96eb2b91a5b0b8a8fb506e20a2fb50ebe8
blob - c01cd5166a40360c20712ac806afa4a5e69bedf5
blob + 8c80082926c22d787a71a030cacf390518812fa4
--- include/thread.h
+++ include/thread.h
#ifndef _THREAD_H_
#define _THREAD_H_ 1
#if defined(__cplusplus)
-extern "C" {
+extern "C" {
#endif
AUTOLIB(thread)
void threadexitsall(char *);
void threadsetname(char*, ...);
void threadsetstate(char*, ...);
+void threadneedbackground(void);
char *threadgetname(void);
int threadyield(void);
int threadidle(void);
void threadmain(int argc, char *argv[]);
extern int mainstacksize;
+int threadmaybackground(void);
+
/*
* channel communication
*/
Channel* threadwaitchan(void);
/*
- * alternate interface to threadwaitchan - don't use both!
+ * alternate interface to threadwaitchan - don't use both!
*/
Waitmsg* procwait(int pid);
blob - 6c6b4602219ea8402fdb46eb7f07c8176d014f81
blob + 02e4c8686f181b9b700df591be57e63b9a227c0b
--- man/man3/thread.3
+++ man/man3/thread.3
threadkill,
threadkillgrp,
threadmain,
+threadmaybackground,
threadnotify,
threadid,
threadpid,
.ft L
.ta \w'\fLChannel* 'u +4n +4n +4n +4n
void threadmain(int argc, char *argv[])
+int threadmaybackground(void)
int mainstacksize
int proccreate(void (*fn)(void*), void *arg, uint stacksize)
int threadcreate(void (*fn)(void*), void *arg, uint stacksize)
.BR 1024 ).
When using the
.I pthread
-library,
+library,
.B mainstacksize
is ignored, as is the stack size argument to
.BR proccreate :
.I fn(arg)
on a stack of size
.IR stacksize .
-Thread stacks are allocated in shared memory, making it valid to pass
+Thread stacks are allocated in shared memory, making it valid to pass
pointers to stack variables between threads and procs.
.I Proccreate
creates a new proc, and inside that proc creates
.\" in
.\" .IR rforkflag .)
.\" .I Proccreate
-.\" is identical to
+.\" is identical to
.\" .I procrfork
.\" with
.\" .I rforkflag
.IR threadmain 's
proc exits, the program will appear to its parent to have exited.
The remaining procs will still run together, but as a background program.
+This functionality can only be relied upon if the program defines a function
+.I threadmaybackground
+returning a non-zero result.
+Programs that do not define such a
+.I threadmaybackground
+will crash instead should the last thread in
+.IR threadmain 's
+proc exit leaving behind other running procs.
.PP
The threads in a proc are coroutines, scheduled nonpreemptively
in a round-robin fashion.
threads have a string state associated with them.
.I Threadsetstate
sets the state string.
-There is no
+There is no
.IR threadgetstate ;
since the thread scheduler resets the state to
.B Running
-every time it runs the thread,
+every time it runs the thread,
it is only useful for debuggers to inspect the state.
.PP
.I Threaddata
returns a pointer to a per-thread pointer
that may be modified by threaded programs for
per-thread storage.
-Similarly,
+Similarly,
.I procdata
returns a pointer to a per-proc pointer.
.PP
.I Threadexecl
and
.I threadexec
-will duplicate
+will duplicate
(see
.MR dup (3) )
the three file descriptors in
-.I fd
+.I fd
onto standard input, output, and error for the external program
and then close them in the calling thread.
Beware of code that sets
operation occurs and
.IR "vice versa" .
.IR Chancreate
-allocates a new channel
+allocates a new channel
for messages of size
-.I elsize
+.I elsize
and with a buffer holding
.I nel
messages.
To create new processes, use
.IR proccreate .
.\" .PP
-.\" It is safe to use
+.\" It is safe to use
.\" .IR rfork
.\" (see
.\" .IR fork (3))
.\" .BR RFCENVG.
.\" (To create new processes, use
.\" .I proccreate
-.\" and
+.\" and
.\" .IR procrfork .)
.\" As mentioned above,
.\" the thread library depends on all procs being in the
blob - 69d1ad75d8853d8ce96529b69703c90c8d436849
blob + 4fa330a081aad33de1a434a13ae86905651b7bc4
--- src/cmd/9pfuse/main.c
+++ src/cmd/9pfuse/main.c
void fusereader(void*);
void watchfd(void*);
+
+int
+threadmaybackground(void)
+{
+ return 1;
+}
void
threadmain(int argc, char **argv)
blob - 255bcbb25244b6276cc3f973f1d084947f765e7b
blob + e26eef1465effe3d5073a73dd2620e145453002b
--- src/cmd/9pserve.c
+++ src/cmd/9pserve.c
fprint(2, "usage: 9pserve [-lnv] [-A aname afid] [-c addr] [-M msize] address\n");
fprint(2, "\treads/writes 9P messages on stdin/stdout\n");
threadexitsall("usage");
+}
+
+int
+threadmaybackground(void)
+{
+ return 1;
}
uchar vbuf[128];
blob - b3ace12c41e976d0e1ea2bf7889b0073ad6eb874
blob + 6dfc2a400be50ae1ae2199b46b8ea348ca7f8095
--- src/cmd/auth/factotum/main.c
+++ src/cmd/auth/factotum/main.c
threadexitsall("usage");
}
+int
+threadmaybackground(void)
+{
+ return 1;
+}
+
void
threadmain(int argc, char *argv[])
{
blob - c3b0c7ef35373bf992059fbadd170269971183e3
blob + e944e3901f0b7b023d952c7c80c90ebdbc57f511
--- src/cmd/auth/ssh-agent.c
+++ src/cmd/auth/ssh-agent.c
{
fprint(2, "usage: 9 ssh-agent [-D] [factotum]\n");
threadexitsall("usage");
+}
+
+int
+threadmaybackground(void)
+{
+ return 1;
}
void
blob - 002e851037b7c0bcd4a2612273d524c17eb588ac
blob + c5672c8697b52e9505d2cbb22a609c8cd09c88f7
--- src/cmd/fossil/fossil.c
+++ src/cmd/fossil/fossil.c
*pncmd = ncmd;
}
+int
+threadmaybackground(void)
+{
+ return 1;
+}
+
void
threadmain(int argc, char* argv[])
{
blob - 0be2f5b6f9e28a3fd7e662fa56cd260b0e9ac28c
blob + 7da70966e51fbc2180fb99415be748d0f5af3770
--- src/cmd/import.c
+++ src/cmd/import.c
fprint(2, "%s: %s\n", argv0 ? argv0 : "<prog>", buf);
threadexitsall("fatal");
+}
+
+int
+threadmaybackground(void)
+{
+ return 1;
}
void
blob - cb3170529338cc65d956250ab577d4966e223ed7
blob + 723989b96c058eabac92cb65e6aeaab2617413cd
--- src/cmd/ndb/dns.c
+++ src/cmd/ndb/dns.c
t = strchr(tcpaddr, '!');
if(u && t && strcmp(u, t) != 0)
fprint(2, "warning: announce mismatch %s %s\n", udpaddr, tcpaddr);
+}
+
+int
+threadmaybackground(void)
+{
+ return 1;
}
void
blob - c99282f02da0c4a939fb49ae3ec32c49b18fc5a5
blob + 5ead2e931307ae5347c86d96203da057914b68b9
--- src/cmd/plumb/plumber.c
+++ src/cmd/plumb/plumber.c
addport(rules[i]->port);
}
+int
+threadmaybackground(void)
+{
+ return 1;
+}
+
void
threadmain(int argc, char *argv[])
{
blob - e1c2745f6549ad4038c27a13c3976f5689e1c12c
blob + 31c9a752b6d25de09f2e70e6f33ffd230a89d243
--- src/cmd/smugfs/main.c
+++ src/cmd/smugfs/main.c
printerrors = 0;
}
+int
+threadmaybackground(void)
+{
+ return 1;
+}
+
void
threadmain(int argc, char **argv)
{
blob - dc6ff3ba6f7ccf3308d5819f1284af496b492717
blob + 32968e67ef72b298fa88d9952c62c19ef3974059
--- src/cmd/upas/fs/fs.c
+++ src/cmd/upas/fs/fs.c
if(strncmp(s, "interrupt", 9) == 0)
noted(NCONT);
noted(NDFLT);
+}
+
+int
+threadmaybackground(void)
+{
+ return 1;
}
void
blob - c72a48494e13b795abdbd9a2cf69e2f1695e1b1c
blob + 68ae141b54f79f6fa39f30ae33cf9083465283c4
--- src/cmd/upas/nfs/main.c
+++ src/cmd/upas/nfs/main.c
threadexitsall("usage");
}
+int
+threadmaybackground(void)
+{
+ return 1;
+}
+
void
threadmain(int argc, char **argv)
{
blob - 1725537a2bc1838c8d43bd788088f035a596e297
blob + 67fda91e1687030b44c5ef1a570aeb359938761b
--- src/cmd/venti/srv/venti.c
+++ src/cmd/venti/srv/venti.c
fprint(2, "usage: venti [-Ldrs] [-a address] [-B blockcachesize] [-c config] "
"[-C lumpcachesize] [-h httpaddress] [-I indexcachesize] [-W webroot]\n");
threadexitsall("usage");
+}
+
+int
+threadmaybackground(void)
+{
+ return 1;
}
void
blob - b7a07c7d00758d5e45189265ac0dd947ee81fcd0
blob + 7cf6489d57d28598bf6791d8d20c0aa07a50bd8c
--- src/lib9p/ramfs.c
+++ src/lib9p/ramfs.c
threadexitsall("usage");
}
+int
+threadmaybackground(void)
+{
+ return 1;
+}
+
void
threadmain(int argc, char **argv)
{
blob - /dev/null
blob + 2edbc0e48d4ae6f8009692de502874e09722b7c2 (mode 644)
--- /dev/null
+++ src/libthread/bg.c
+#include "threadimpl.h"
+
+int
+threadmaybackground(void)
+{
+ return 0;
+}
blob - 387d1527280d0a6b584e26851e35f3d622616d53
blob + f994ffe159da4095a37a661be3f1d6b0bdbd711f
--- src/libthread/daemonize.c
+++ src/libthread/daemonize.c
#undef wait
static int sigpid;
-static int threadpassfd;
+static int threadpassfd = -1;
static int gotsigchld;
static void
void
_threaddaemonize(void)
{
- if(threadpassfd >= 0){
- write(threadpassfd, "0", 1);
- close(threadpassfd);
- threadpassfd = -1;
- }
+ if(threadpassfd < 0)
+ sysfatal("threads in main proc exited w/o threadmaybackground");
+ write(threadpassfd, "0", 1);
+ close(threadpassfd);
+ threadpassfd = -1;
}
blob - 8a77a316175189b619f9b0b15c60bdb78acdc40a
blob + eca4f4df445f7bfdcef6e2923386fa295ddc49ee
--- src/libthread/mkfile
+++ src/libthread/mkfile
LIB=libthread.a
OFILES=\
$SYSOFILES\
+ bg.$O\
channel.$O\
daemonize.$O\
exec.$O\
blob - 65e651949b2fe0e783ab745f5f11f70ad11b4d39
blob + 7151e8756f26afb856e83107529bcb7c0a1451dc
--- src/libthread/thread.c
+++ src/libthread/thread.c
// Easier to just run in pthread-per-thread mode.
pthreadperthread = 1;
#endif
- if(strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil)
+ if(threadmaybackground() && strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil)
_threadsetupdaemonize();
threadargc = argc;