Commit Diff


commit - 5b37d9126474864b5299426e27b2af37fcc96dd0
commit + b3a20a96eb2b91a5b0b8a8fb506e20a2fb50ebe8
blob - c01cd5166a40360c20712ac806afa4a5e69bedf5
blob + 8c80082926c22d787a71a030cacf390518812fa4
--- include/thread.h
+++ include/thread.h
@@ -1,7 +1,7 @@
 #ifndef _THREAD_H_
 #define _THREAD_H_ 1
 #if defined(__cplusplus)
-extern "C" { 
+extern "C" {
 #endif
 
 AUTOLIB(thread)
@@ -15,6 +15,7 @@ void		threadexits(char *);
 void		threadexitsall(char *);
 void		threadsetname(char*, ...);
 void		threadsetstate(char*, ...);
+void		threadneedbackground(void);
 char		*threadgetname(void);
 int			threadyield(void);
 int			threadidle(void);
@@ -60,6 +61,8 @@ void		**threaddata(void);
 void		threadmain(int argc, char *argv[]);
 extern	int	mainstacksize;
 
+int	threadmaybackground(void);
+
 /*
  * channel communication
  */
@@ -180,7 +183,7 @@ int		threadspawnl(int[3], char*, ...);
 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
@@ -33,6 +33,7 @@ threadintgrp,
 threadkill,
 threadkillgrp,
 threadmain,
+threadmaybackground,
 threadnotify,
 threadid,
 threadpid,
@@ -80,6 +81,7 @@ struct Alt {
 .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)
@@ -171,7 +173,7 @@ initialized to the desired value
 .BR 1024 ).
 When using the
 .I pthread
-library, 
+library,
 .B mainstacksize
 is ignored, as is the stack size argument to
 .BR proccreate :
@@ -185,7 +187,7 @@ executes
 .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
@@ -207,7 +209,7 @@ returning the id of the created thread.
 .\" in
 .\" .IR rforkflag .)
 .\" .I Proccreate
-.\" is identical to 
+.\" is identical to
 .\" .I procrfork
 .\" with
 .\" .I rforkflag
@@ -238,6 +240,14 @@ When the last thread in
 .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.
@@ -341,18 +351,18 @@ Also for debugging,
 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
@@ -398,11 +408,11 @@ response.
 .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
@@ -467,9 +477,9 @@ operation blocks until the corresponding
 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.
@@ -645,7 +655,7 @@ from the main proc before any other procs have been cr
 To create new processes, use
 .IR proccreate .
 .\" .PP
-.\" It is safe to use 
+.\" It is safe to use
 .\" .IR rfork
 .\" (see
 .\" .IR fork (3))
@@ -663,7 +673,7 @@ To create new processes, use
 .\" .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
@@ -97,6 +97,12 @@ usage(void)
 
 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
@@ -135,6 +135,12 @@ usage(void)
 	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
@@ -20,6 +20,12 @@ usage(void)
 	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
@@ -88,6 +88,12 @@ usage(void)
 {
 	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
@@ -59,6 +59,12 @@ readCmdPart(char *file, char ***pcmd, int *pncmd)
 	*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
@@ -49,6 +49,12 @@ fatal(char *fmt, ...)
 
 	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
@@ -119,6 +119,12 @@ checkaddress(void)
 	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
@@ -26,6 +26,12 @@ makeports(Ruleset *rules[])
 		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
@@ -51,6 +51,12 @@ smuglogin(void)
 	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
@@ -153,6 +153,12 @@ notifyf(void *a, char *s)
 	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
@@ -26,6 +26,12 @@ usage(void)
 	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
@@ -21,6 +21,12 @@ usage(void)
 	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
@@ -125,6 +125,12 @@ usage(void)
 	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
@@ -0,0 +1,7 @@
+#include "threadimpl.h"
+
+int
+threadmaybackground(void)
+{
+	return 0;
+}
blob - 387d1527280d0a6b584e26851e35f3d622616d53
blob + f994ffe159da4095a37a661be3f1d6b0bdbd711f
--- src/libthread/daemonize.c
+++ src/libthread/daemonize.c
@@ -8,7 +8,7 @@
 #undef wait
 
 static int sigpid;
-static int threadpassfd;
+static int threadpassfd = -1;
 static int gotsigchld;
 
 static void
@@ -163,9 +163,9 @@ _threadsetupdaemonize(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
@@ -4,6 +4,7 @@ SYSOFILES=`{sh ./sysofiles.sh}
 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
@@ -844,7 +844,7 @@ main(int argc, char **argv)
 	// 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;