mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
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:
parent
5b37d91264
commit
b3a20a96eb
19 changed files with 120 additions and 21 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
7
src/libthread/bg.c
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
threadmaybackground(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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\
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue