View | Details | Raw Unified | Return to bug 17437
Collapse All | Expand All

(-)lib/libc_r/uthread/Makefile.inc (+1 lines)
Lines 6-11 Link Here
6
SRCS+= \
6
SRCS+= \
7
	uthread_accept.c \
7
	uthread_accept.c \
8
	uthread_aio_suspend.c \
8
	uthread_aio_suspend.c \
9
	uthread_atfork.c \
9
	uthread_attr_destroy.c \
10
	uthread_attr_destroy.c \
10
	uthread_attr_init.c \
11
	uthread_attr_init.c \
11
	uthread_attr_getdetachstate.c \
12
	uthread_attr_getdetachstate.c \
(-)lib/libc_r/man/pthread_atfork.3 (+73 lines)
Line 0 Link Here
1
.\"
2
.\" "THE BEER-WARE LICENSE" (Revision 42m):
3
.\" <mikko@dynas.se> wrote this file.  As long as you retain this notice you
4
.\" can do whatever you want with this stuff. If we meet some day, and you think
5
.\" this stuff is worth it, you can buy me a beer in return.  Mikko Työläjärvi
6
.\"
7
.\" $FreeBSD$
8
.\"
9
.Dd March 16, 2000
10
.Dt PTHREAD_ATFORK 3
11
.Os BSD 4
12
.Sh NAME
13
.Nm pthread_atfork
14
.Nd register fork handlers
15
.Sh SYNOPSIS
16
.Fd #include <pthread.h>
17
.Ft int
18
.Fn pthread_atfork "void (*prepare)(void)" "void (*parent)(void)" "void (*child)(void)"
19
.Sh DESCRIPTION
20
The
21
.Fn pthread_atfork
22
function registers fork handlers to be called before and after
23
.Fn fork .
24
Handlers are run in the context of the thread that calls
25
.Fn fork .
26
.Pp
27
The
28
.Fa prepare
29
handlers are invoked before fork processing. The
30
.Fa parent
31
and
32
.Fa child
33
handlers are invoked after fork processing, in the parent and child
34
processes respectively.
35
Handlers will be called in the parent process even when the
36
.Fn fork
37
operation fails.
38
.Pp
39
Any number of handlers can be registered by
40
.Fn pthread_atfork .
41
Function pointers that are NULL will be ignored.
42
The 
43
.Fa Parent
44
and
45
.Fa child
46
handlers are called in the order that they were registered. The
47
.Fn prepare
48
handlers are called in the reverse order.
49
.Pp
50
.Sh RETURN VALUES
51
If successful, the
52
.Fn pthread_atfork
53
function will return zero.
54
Otherwise an error number will be returned to
55
indicate the error.
56
.Sh ERRORS
57
.Fn pthread_atfork
58
will fail if:
59
.Bl -tag -width Er
60
.It Bq Er ENOMEM
61
The process cannot allocate enough memory to register another set of
62
handlers.
63
.El
64
.Pp
65
.Sh SEE ALSO
66
.Xr fork 2 ,
67
.Xr atexit 3
68
.Sh STANDARDS
69
.Fn pthread_atfork
70
conforms to ISO/IEC 9945-1 ANSI/IEEE
71
.Pq Dq Tn POSIX
72
.\" XXX: Dunno -- someone will have to check the exact details:
73
Std 1003.1 Second Edition 1996-07-12.
(-)lib/libc_r/man/Makefile.inc (-1 / +2 lines)
Lines 4-10 Link Here
4
4
5
.PATH: ${.CURDIR}/man
5
.PATH: ${.CURDIR}/man
6
6
7
MAN3+=	pthread_cancel.3 \
7
MAN3+=	pthread_atfork.3 \
8
	pthread_cancel.3 \
8
	pthread_cleanup_pop.3 \
9
	pthread_cleanup_pop.3 \
9
	pthread_cleanup_push.3 \
10
	pthread_cleanup_push.3 \
10
	pthread_cond_broadcast.3 \
11
	pthread_cond_broadcast.3 \
(-)include/pthread.h (+3 lines)
Lines 303-308 Link Here
303
303
304
int		pthread_attr_setfloatstate __P((pthread_attr_t *, int));
304
int		pthread_attr_setfloatstate __P((pthread_attr_t *, int));
305
int		pthread_attr_getfloatstate __P((pthread_attr_t *, int *));
305
int		pthread_attr_getfloatstate __P((pthread_attr_t *, int *));
306
307
int		pthread_atfork __P((void (*prepare)(void),
308
				    void (*parent)(void), void (*child)(void)));
306
__END_DECLS
309
__END_DECLS
307
310
308
#endif
311
#endif
(-)lib/libc_r/uthread/pthread_private.h (+11 lines)
Lines 999-1004 Link Here
999
#define _FD_UNLOCK(_fd,_type)		_thread_fd_unlock(_fd, _type)
999
#define _FD_UNLOCK(_fd,_type)		_thread_fd_unlock(_fd, _type)
1000
#endif
1000
#endif
1001
1001
1002
/* Atfork handlers */
1003
#define ATFORK_PREPARE	0
1004
#define ATFORK_PARENT	1
1005
#define ATFORK_CHILD	2
1006
1007
typedef struct atfork_data {
1008
	struct atfork_data *next, *prev;
1009
	void (*funcs[3])(void);
1010
} atfork_data;
1011
1002
/*
1012
/*
1003
 * Function prototype definitions.
1013
 * Function prototype definitions.
1004
 */
1014
 */
Lines 1060-1065 Link Here
1060
void	_thread_enter_cancellation_point(void);
1070
void	_thread_enter_cancellation_point(void);
1061
void	_thread_leave_cancellation_point(void);
1071
void	_thread_leave_cancellation_point(void);
1062
void	_thread_cancellation_point(void);
1072
void	_thread_cancellation_point(void);
1073
atfork_data *_thread_atfork_list(void);
1063
1074
1064
/* #include <signal.h> */
1075
/* #include <signal.h> */
1065
int     _thread_sys_sigaction(int, const struct sigaction *, struct sigaction *);
1076
int     _thread_sys_sigaction(int, const struct sigaction *, struct sigaction *);
(-)lib/libc_r/uthread/uthread_atfork.c (+56 lines)
Line 0 Link Here
1
/*
2
 * "THE BEER-WARE LICENSE" (Revision 42m):
3
 * <mikko@dynas.se> wrote this file.  As long as you retain this notice you
4
 * can do whatever you want with this stuff. If we meet some day, and you think
5
 * this stuff is worth it, you can buy me a beer in return.  Mikko Työläjärvi
6
 *
7
 * $FreeBSD$
8
 */
9
10
#include <errno.h>
11
#include <stdlib.h>
12
#ifdef _THREAD_SAFE
13
#include <pthread.h>
14
#include "pthread_private.h"
15
16
static atfork_data *atfork_list = NULL;
17
static spinlock_t atfork_lock	= _SPINLOCK_INITIALIZER;
18
19
int
20
pthread_atfork(void (*prepare)(void),
21
	       void (*parent)(void),
22
	       void (*child)(void))
23
{
24
	atfork_data *ap;
25
26
	if (prepare == NULL && parent == NULL && child == NULL)
27
		return 0;
28
29
	if ((ap = malloc(sizeof(atfork_data))) == NULL)
30
		return ENOMEM;
31
32
	ap->funcs[ATFORK_PREPARE] = prepare;
33
	ap->funcs[ATFORK_PARENT] = parent;
34
	ap->funcs[ATFORK_CHILD] = child;
35
36
	_SPINLOCK(&atfork_lock);
37
	if ((ap->next = atfork_list) != NULL)
38
		atfork_list->prev = ap;
39
	atfork_list = ap;
40
	_SPINUNLOCK(&atfork_lock);
41
42
	return 0;
43
}
44
45
atfork_data *
46
_thread_atfork_list(void)
47
{
48
	atfork_data *ap;
49
50
	_SPINLOCK(&atfork_lock);
51
	ap = atfork_list;
52
	_SPINUNLOCK(&atfork_lock);
53
54
	return ap;
55
}
56
#endif
(-)lib/libc_r/uthread/uthread_fork.c (+19 lines)
Lines 47-52 Link Here
47
	pid_t		ret;
47
	pid_t		ret;
48
	pthread_t	pthread;
48
	pthread_t	pthread;
49
	pthread_t	pthread_save;
49
	pthread_t	pthread_save;
50
	atfork_data	*ap, *alist;
51
52
	/* Run any registered "prepare" callbacks: */
53
	alist = _thread_atfork_list();
54
	for (ap = alist; ap != NULL; ap = ap->next) {
55
		if (ap->funcs[ATFORK_PREPARE] != NULL)
56
			ap->funcs[ATFORK_PREPARE]();
57
		if (ap->next == NULL)
58
			break;
59
	}
50
60
51
	/*
61
	/*
52
	 * Defer signals to protect the scheduling queues from access
62
	 * Defer signals to protect the scheduling queues from access
Lines 216-221 Link Here
216
	 * Undefer and handle pending signals, yielding if necessary:
226
	 * Undefer and handle pending signals, yielding if necessary:
217
	 */
227
	 */
218
	_thread_kern_sig_undefer();
228
	_thread_kern_sig_undefer();
229
230
	/*
231
	 * Run any parent/child callbacks matching the "prepare" callbacks
232
	 * from function entry, in reverse order:
233
	 */
234
	i = ret ? ATFORK_PARENT : ATFORK_CHILD;
235
	for (; ap != NULL; ap = (ap != alist) ? ap->prev : NULL)
236
		if (ap->funcs[i] != NULL)
237
			ap->funcs[i]();
219
238
220
	/* Return the process ID: */
239
	/* Return the process ID: */
221
	return (ret);
240
	return (ret);

Return to bug 17437