tlibthread: add threadmaybackground - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit b3a20a96eb2b91a5b0b8a8fb506e20a2fb50ebe8
parent 5b37d9126474864b5299426e27b2af37fcc96dd0
Author: Russ Cox 
Date:   Wed, 30 Dec 2020 00:10:11 -0500

libthread: add threadmaybackground

Programs that want to background themselves now need
tto define threadmaybackground returning 1.
This avoids a confusing (to people and debuggers)
extra parent process for all the threaded programs
tthat will never want to background themselves.

Diffstat:
  M include/thread.h                    |       7 +++++--
  M man/man3/thread.3                   |      34 ++++++++++++++++++++-----------
  M src/cmd/9pfuse/main.c               |       6 ++++++
  M src/cmd/9pserve.c                   |       6 ++++++
  M src/cmd/auth/factotum/main.c        |       6 ++++++
  M src/cmd/auth/ssh-agent.c            |       6 ++++++
  M src/cmd/fossil/fossil.c             |       6 ++++++
  M src/cmd/import.c                    |       6 ++++++
  M src/cmd/ndb/dns.c                   |       6 ++++++
  M src/cmd/plumb/plumber.c             |       6 ++++++
  M src/cmd/smugfs/main.c               |       6 ++++++
  M src/cmd/upas/fs/fs.c                |       6 ++++++
  M src/cmd/upas/nfs/main.c             |       6 ++++++
  M src/cmd/venti/srv/venti.c           |       6 ++++++
  M src/lib9p/ramfs.c                   |       6 ++++++
  A src/libthread/bg.c                  |       7 +++++++
  M src/libthread/daemonize.c           |      12 ++++++------
  M src/libthread/mkfile                |       1 +
  M src/libthread/thread.c              |       2 +-

19 files changed, 120 insertions(+), 21 deletions(-)
---
diff --git a/include/thread.h b/include/thread.h
t@@ -1,7 +1,7 @@
 #ifndef _THREAD_H_
 #define _THREAD_H_ 1
 #if defined(__cplusplus)
-extern "C" { 
+extern "C" {
 #endif
 
 AUTOLIB(thread)
t@@ -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);
t@@ -60,6 +61,8 @@ void                **threaddata(void);
 void                threadmain(int argc, char *argv[]);
 extern        int        mainstacksize;
 
+int        threadmaybackground(void);
+
 /*
  * channel communication
  */
t@@ -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);
 
diff --git a/man/man3/thread.3 b/man/man3/thread.3
t@@ -33,6 +33,7 @@ threadintgrp,
 threadkill,
 threadkillgrp,
 threadmain,
+threadmaybackground,
 threadnotify,
 threadid,
 threadpid,
t@@ -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)
t@@ -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 :
t@@ -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
t@@ -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
t@@ -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.
t@@ -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
t@@ -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
t@@ -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.
t@@ -645,7 +655,7 @@ from the main proc before any other procs have been created.
 To create new processes, use
 .IR proccreate .
 .\" .PP
-.\" It is safe to use 
+.\" It is safe to use
 .\" .IR rfork
 .\" (see
 .\" .IR fork (3))
t@@ -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
diff --git a/src/cmd/9pfuse/main.c b/src/cmd/9pfuse/main.c
t@@ -98,6 +98,12 @@ usage(void)
 void fusereader(void*);
 void watchfd(void*);
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char **argv)
 {
diff --git a/src/cmd/9pserve.c b/src/cmd/9pserve.c
t@@ -137,6 +137,12 @@ usage(void)
         threadexitsall("usage");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 uchar vbuf[128];
 extern int _threaddebuglevel;
 void
diff --git a/src/cmd/auth/factotum/main.c b/src/cmd/auth/factotum/main.c
t@@ -20,6 +20,12 @@ usage(void)
         threadexitsall("usage");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char *argv[])
 {
diff --git a/src/cmd/auth/ssh-agent.c b/src/cmd/auth/ssh-agent.c
t@@ -90,6 +90,12 @@ usage(void)
         threadexitsall("usage");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char **argv)
 {
diff --git a/src/cmd/fossil/fossil.c b/src/cmd/fossil/fossil.c
t@@ -59,6 +59,12 @@ readCmdPart(char *file, char ***pcmd, int *pncmd)
         *pncmd = ncmd;
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char* argv[])
 {
diff --git a/src/cmd/import.c b/src/cmd/import.c
t@@ -51,6 +51,12 @@ fatal(char *fmt, ...)
         threadexitsall("fatal");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char *argv[])
 {
diff --git a/src/cmd/ndb/dns.c b/src/cmd/ndb/dns.c
t@@ -121,6 +121,12 @@ checkaddress(void)
                 fprint(2, "warning: announce mismatch %s %s\n", udpaddr, tcpaddr);
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char *argv[])
 {
diff --git a/src/cmd/plumb/plumber.c b/src/cmd/plumb/plumber.c
t@@ -26,6 +26,12 @@ makeports(Ruleset *rules[])
                 addport(rules[i]->port);
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char *argv[])
 {
diff --git a/src/cmd/smugfs/main.c b/src/cmd/smugfs/main.c
t@@ -51,6 +51,12 @@ smuglogin(void)
         printerrors = 0;
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char **argv)
 {
diff --git a/src/cmd/upas/fs/fs.c b/src/cmd/upas/fs/fs.c
t@@ -155,6 +155,12 @@ notifyf(void *a, char *s)
         noted(NDFLT);
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char *argv[])
 {
diff --git a/src/cmd/upas/nfs/main.c b/src/cmd/upas/nfs/main.c
t@@ -26,6 +26,12 @@ usage(void)
         threadexitsall("usage");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char **argv)
 {
diff --git a/src/cmd/venti/srv/venti.c b/src/cmd/venti/srv/venti.c
t@@ -23,6 +23,12 @@ usage(void)
         threadexitsall("usage");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char *argv[])
 {
diff --git a/src/lib9p/ramfs.c b/src/lib9p/ramfs.c
t@@ -125,6 +125,12 @@ usage(void)
         threadexitsall("usage");
 }
 
+int
+threadmaybackground(void)
+{
+        return 1;
+}
+
 void
 threadmain(int argc, char **argv)
 {
diff --git a/src/libthread/bg.c b/src/libthread/bg.c
t@@ -0,0 +1,7 @@
+#include "threadimpl.h"
+
+int
+threadmaybackground(void)
+{
+        return 0;
+}
diff --git a/src/libthread/daemonize.c b/src/libthread/daemonize.c
t@@ -8,7 +8,7 @@
 #undef wait
 
 static int sigpid;
-static int threadpassfd;
+static int threadpassfd = -1;
 static int gotsigchld;
 
 static void
t@@ -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;
 }
diff --git a/src/libthread/mkfile b/src/libthread/mkfile
t@@ -4,6 +4,7 @@ SYSOFILES=`{sh ./sysofiles.sh}
 LIB=libthread.a
 OFILES=\
         $SYSOFILES\
+        bg.$O\
         channel.$O\
         daemonize.$O\
         exec.$O\
diff --git a/src/libthread/thread.c b/src/libthread/thread.c
t@@ -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;