libthread: add threadmaybackground

Programs that want to background themselves now need
to define threadmaybackground returning 1.
This avoids a confusing (to people and debuggers)
extra parent process for all the threaded programs
that will never want to background themselves.
This commit is contained in:
Russ Cox 2020-12-30 00:10:11 -05:00
parent 5b37d91264
commit b3a20a96eb
19 changed files with 120 additions and 21 deletions

View file

@ -1,7 +1,7 @@
#ifndef _THREAD_H_ #ifndef _THREAD_H_
#define _THREAD_H_ 1 #define _THREAD_H_ 1
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
AUTOLIB(thread) AUTOLIB(thread)
@ -15,6 +15,7 @@ void threadexits(char *);
void threadexitsall(char *); void threadexitsall(char *);
void threadsetname(char*, ...); void threadsetname(char*, ...);
void threadsetstate(char*, ...); void threadsetstate(char*, ...);
void threadneedbackground(void);
char *threadgetname(void); char *threadgetname(void);
int threadyield(void); int threadyield(void);
int threadidle(void); int threadidle(void);
@ -60,6 +61,8 @@ void **threaddata(void);
void threadmain(int argc, char *argv[]); void threadmain(int argc, char *argv[]);
extern int mainstacksize; extern int mainstacksize;
int threadmaybackground(void);
/* /*
* channel communication * channel communication
*/ */
@ -180,7 +183,7 @@ int threadspawnl(int[3], char*, ...);
Channel* threadwaitchan(void); Channel* threadwaitchan(void);
/* /*
* alternate interface to threadwaitchan - don't use both! * alternate interface to threadwaitchan - don't use both!
*/ */
Waitmsg* procwait(int pid); Waitmsg* procwait(int pid);

View file

@ -33,6 +33,7 @@ threadintgrp,
threadkill, threadkill,
threadkillgrp, threadkillgrp,
threadmain, threadmain,
threadmaybackground,
threadnotify, threadnotify,
threadid, threadid,
threadpid, threadpid,
@ -80,6 +81,7 @@ struct Alt {
.ft L .ft L
.ta \w'\fLChannel* 'u +4n +4n +4n +4n .ta \w'\fLChannel* 'u +4n +4n +4n +4n
void threadmain(int argc, char *argv[]) void threadmain(int argc, char *argv[])
int threadmaybackground(void)
int mainstacksize int mainstacksize
int proccreate(void (*fn)(void*), void *arg, uint stacksize) int proccreate(void (*fn)(void*), void *arg, uint stacksize)
int threadcreate(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 ). .BR 1024 ).
When using the When using the
.I pthread .I pthread
library, library,
.B mainstacksize .B mainstacksize
is ignored, as is the stack size argument to is ignored, as is the stack size argument to
.BR proccreate : .BR proccreate :
@ -185,7 +187,7 @@ executes
.I fn(arg) .I fn(arg)
on a stack of size on a stack of size
.IR stacksize . .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. pointers to stack variables between threads and procs.
.I Proccreate .I Proccreate
creates a new proc, and inside that proc creates creates a new proc, and inside that proc creates
@ -207,7 +209,7 @@ returning the id of the created thread.
.\" in .\" in
.\" .IR rforkflag .) .\" .IR rforkflag .)
.\" .I Proccreate .\" .I Proccreate
.\" is identical to .\" is identical to
.\" .I procrfork .\" .I procrfork
.\" with .\" with
.\" .I rforkflag .\" .I rforkflag
@ -238,6 +240,14 @@ When the last thread in
.IR threadmain 's .IR threadmain 's
proc exits, the program will appear to its parent to have exited. proc exits, the program will appear to its parent to have exited.
The remaining procs will still run together, but as a background program. 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 .PP
The threads in a proc are coroutines, scheduled nonpreemptively The threads in a proc are coroutines, scheduled nonpreemptively
in a round-robin fashion. in a round-robin fashion.
@ -341,18 +351,18 @@ Also for debugging,
threads have a string state associated with them. threads have a string state associated with them.
.I Threadsetstate .I Threadsetstate
sets the state string. sets the state string.
There is no There is no
.IR threadgetstate ; .IR threadgetstate ;
since the thread scheduler resets the state to since the thread scheduler resets the state to
.B Running .B Running
every time it runs the thread, every time it runs the thread,
it is only useful for debuggers to inspect the state. it is only useful for debuggers to inspect the state.
.PP .PP
.I Threaddata .I Threaddata
returns a pointer to a per-thread pointer returns a pointer to a per-thread pointer
that may be modified by threaded programs for that may be modified by threaded programs for
per-thread storage. per-thread storage.
Similarly, Similarly,
.I procdata .I procdata
returns a pointer to a per-proc pointer. returns a pointer to a per-proc pointer.
.PP .PP
@ -398,11 +408,11 @@ response.
.I Threadexecl .I Threadexecl
and and
.I threadexec .I threadexec
will duplicate will duplicate
(see (see
.MR dup (3) ) .MR dup (3) )
the three file descriptors in the three file descriptors in
.I fd .I fd
onto standard input, output, and error for the external program onto standard input, output, and error for the external program
and then close them in the calling thread. and then close them in the calling thread.
Beware of code that sets Beware of code that sets
@ -467,9 +477,9 @@ operation blocks until the corresponding
operation occurs and operation occurs and
.IR "vice versa" . .IR "vice versa" .
.IR Chancreate .IR Chancreate
allocates a new channel allocates a new channel
for messages of size for messages of size
.I elsize .I elsize
and with a buffer holding and with a buffer holding
.I nel .I nel
messages. messages.
@ -645,7 +655,7 @@ from the main proc before any other procs have been created.
To create new processes, use To create new processes, use
.IR proccreate . .IR proccreate .
.\" .PP .\" .PP
.\" It is safe to use .\" It is safe to use
.\" .IR rfork .\" .IR rfork
.\" (see .\" (see
.\" .IR fork (3)) .\" .IR fork (3))
@ -663,7 +673,7 @@ To create new processes, use
.\" .BR RFCENVG. .\" .BR RFCENVG.
.\" (To create new processes, use .\" (To create new processes, use
.\" .I proccreate .\" .I proccreate
.\" and .\" and
.\" .IR procrfork .) .\" .IR procrfork .)
.\" As mentioned above, .\" As mentioned above,
.\" the thread library depends on all procs being in the .\" the thread library depends on all procs being in the

View file

@ -98,6 +98,12 @@ usage(void)
void fusereader(void*); void fusereader(void*);
void watchfd(void*); void watchfd(void*);
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {

View file

@ -137,6 +137,12 @@ usage(void)
threadexitsall("usage"); threadexitsall("usage");
} }
int
threadmaybackground(void)
{
return 1;
}
uchar vbuf[128]; uchar vbuf[128];
extern int _threaddebuglevel; extern int _threaddebuglevel;
void void

View file

@ -20,6 +20,12 @@ usage(void)
threadexitsall("usage"); threadexitsall("usage");
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char *argv[]) threadmain(int argc, char *argv[])
{ {

View file

@ -90,6 +90,12 @@ usage(void)
threadexitsall("usage"); threadexitsall("usage");
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {

View file

@ -59,6 +59,12 @@ readCmdPart(char *file, char ***pcmd, int *pncmd)
*pncmd = ncmd; *pncmd = ncmd;
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char* argv[]) threadmain(int argc, char* argv[])
{ {

View file

@ -51,6 +51,12 @@ fatal(char *fmt, ...)
threadexitsall("fatal"); threadexitsall("fatal");
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char *argv[]) threadmain(int argc, char *argv[])
{ {

View file

@ -121,6 +121,12 @@ checkaddress(void)
fprint(2, "warning: announce mismatch %s %s\n", udpaddr, tcpaddr); fprint(2, "warning: announce mismatch %s %s\n", udpaddr, tcpaddr);
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char *argv[]) threadmain(int argc, char *argv[])
{ {

View file

@ -26,6 +26,12 @@ makeports(Ruleset *rules[])
addport(rules[i]->port); addport(rules[i]->port);
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char *argv[]) threadmain(int argc, char *argv[])
{ {

View file

@ -51,6 +51,12 @@ smuglogin(void)
printerrors = 0; printerrors = 0;
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {

View file

@ -155,6 +155,12 @@ notifyf(void *a, char *s)
noted(NDFLT); noted(NDFLT);
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char *argv[]) threadmain(int argc, char *argv[])
{ {

View file

@ -26,6 +26,12 @@ usage(void)
threadexitsall("usage"); threadexitsall("usage");
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {

View file

@ -23,6 +23,12 @@ usage(void)
threadexitsall("usage"); threadexitsall("usage");
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char *argv[]) threadmain(int argc, char *argv[])
{ {

View file

@ -125,6 +125,12 @@ usage(void)
threadexitsall("usage"); threadexitsall("usage");
} }
int
threadmaybackground(void)
{
return 1;
}
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {

7
src/libthread/bg.c Normal file
View file

@ -0,0 +1,7 @@
#include "threadimpl.h"
int
threadmaybackground(void)
{
return 0;
}

View file

@ -8,7 +8,7 @@
#undef wait #undef wait
static int sigpid; static int sigpid;
static int threadpassfd; static int threadpassfd = -1;
static int gotsigchld; static int gotsigchld;
static void static void
@ -163,9 +163,9 @@ _threadsetupdaemonize(void)
void void
_threaddaemonize(void) _threaddaemonize(void)
{ {
if(threadpassfd >= 0){ if(threadpassfd < 0)
write(threadpassfd, "0", 1); sysfatal("threads in main proc exited w/o threadmaybackground");
close(threadpassfd); write(threadpassfd, "0", 1);
threadpassfd = -1; close(threadpassfd);
} threadpassfd = -1;
} }

View file

@ -4,6 +4,7 @@ SYSOFILES=`{sh ./sysofiles.sh}
LIB=libthread.a LIB=libthread.a
OFILES=\ OFILES=\
$SYSOFILES\ $SYSOFILES\
bg.$O\
channel.$O\ channel.$O\
daemonize.$O\ daemonize.$O\
exec.$O\ exec.$O\

View file

@ -844,7 +844,7 @@ main(int argc, char **argv)
// Easier to just run in pthread-per-thread mode. // Easier to just run in pthread-per-thread mode.
pthreadperthread = 1; pthreadperthread = 1;
#endif #endif
if(strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil) if(threadmaybackground() && strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil)
_threadsetupdaemonize(); _threadsetupdaemonize();
threadargc = argc; threadargc = argc;