| 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; |