tlibthread: add threadmaybackground - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit b3a20a96eb2b91a5b0b8a8fb506e20a2fb50ebe8
 (DIR) parent 5b37d9126474864b5299426e27b2af37fcc96dd0
 (HTM) Author: Russ Cox <rsc@swtch.com>
       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(-)
       ---
 (DIR) 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);
        
 (DIR) 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
 (DIR) 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)
        {
 (DIR) 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
 (DIR) 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[])
        {
 (DIR) 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)
        {
 (DIR) 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[])
        {
 (DIR) 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[])
        {
 (DIR) 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[])
        {
 (DIR) 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[])
        {
 (DIR) 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)
        {
 (DIR) 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[])
        {
 (DIR) 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)
        {
 (DIR) 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[])
        {
 (DIR) 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)
        {
 (DIR) 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;
       +}
 (DIR) 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;
        }
 (DIR) 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\
 (DIR) 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;