Browse code

core: daemon status/pipe fixes & interface changes

- moved most of the daemon status stuff to daemonize.[ch].
- nicer interface (e.g. daemon_status_send(code))
- send/read only 1 byte which will be used as exit code
- send an error status on error (fixes
"Main process exited before writing to pipe" error message)
- disabled the timeout. Not needed (now a status is sent always
and even an unlikely process crash before sending it is detected via
the read() failure) and very hard to find a good value (some
setups start very slow).
- close the pipe "send" fd in processes not needing it
- attempt to send back status only if dont_daemonize is not set
(not only if dont_fork==0, it is possible to have forking
enabled, but daemonize disabled: ser -DD)
- BSDed daemonize.[ch] and pt.[ch]

Andrei Pelinescu-Onciul authored on 19/08/2010 18:03:54
Showing 5 changed files
... ...
@@ -3,21 +3,17 @@
3 3
  *
4 4
  * Copyright (C) 2001-2003 FhG Fokus
5 5
  *
6
- * This file is part of SIP-router, a free SIP server.
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
7 9
  *
8
- * SIP-router is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version
12
- *
13
- * SIP-router is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License 
19
- * along with this program; if not, write to the Free Software 
20
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 17
  */
22 18
 /*
23 19
  * 
... ...
@@ -81,16 +77,165 @@
81 81
 #define MAX_FD 32 /* maximum number of inherited open file descriptors,
82 82
 		    (normally it shouldn't  be bigger  than 3) */
83 83
 
84
-/*! \brief daemon init, return 0 on success, -1 on error */
85
-int daemonize(char*  name,  int daemon_status_fd_input)
84
+/** temporary pipe FDs for sending exit status back to the ancestor process.
85
+ * This pipe is used to send the desired exit status to the initial process,
86
+ * that waits for it in the foreground. This way late errors preventing
87
+ * startup (e.g. during modules child inits or TCP late init) can still be
88
+ * reported back.
89
+ */
90
+static int daemon_status_fd[2];
91
+
92
+
93
+
94
+/** init daemon status reporting.
95
+ * Must be called before any other daemon_status function has a chance to
96
+ * run.
97
+ */
98
+void daemon_status_init()
99
+{
100
+	daemon_status_fd[0] = -1;
101
+	daemon_status_fd[1] = -1;
102
+}
103
+
104
+
105
+
106
+/** pre-daemonize init for daemon status reporting.
107
+ * Must be called before forking.
108
+ * Typically the parent process will call daemon_status_wait() while
109
+ * one of the children will call daemon_status_send() at some point.
110
+ *
111
+ * @return 0 on success, -1 on error (and sets errno).
112
+ */
113
+int daemon_status_pre_daemonize()
114
+{
115
+	int ret;
116
+	
117
+retry:
118
+	ret = pipe(daemon_status_fd);
119
+	if (ret < 0 && errno == EINTR)
120
+		goto retry;
121
+	return ret;
122
+}
123
+
124
+
125
+
126
+/** wait for an exit status to be send by daemon_status_send().
127
+ * @param status - filled with the sent status (a char).
128
+ * @return  0 on success, -1 on error (e.g. process died before sending
129
+ *          status, not intialized a.s.o.).
130
+ * Side-effects: it will close the write side of the pipe
131
+ *  (must not be used from the same process as the daemon_status_send()).
132
+ * Note: if init is not complete (only init, but no pre-daemonize)
133
+ * it will return success always and status 0.
134
+ */
135
+int daemon_status_wait(char* status)
136
+{
137
+	int ret;
138
+	
139
+	/* close the output side of the pipe */
140
+	if (daemon_status_fd[1] != -1) {
141
+		close(daemon_status_fd[1]);
142
+		daemon_status_fd[1] = -1;
143
+	}
144
+	if (daemon_status_fd[0] == -1) {
145
+		*status = 0;
146
+		return -1;
147
+	}
148
+retry:
149
+	ret = read(daemon_status_fd[0], status, 1);
150
+	if (ret < 0 && errno == EINTR)
151
+		goto retry;
152
+	return (ret ==1 ) ? 0 : -1;
153
+}
154
+
155
+
156
+
157
+/** send 'status' to a waiting process running daemon_status_wait().
158
+ * @param status - status byte
159
+ * @return 0 on success, -1 on error.
160
+ * Note: if init is not complete (only init, but no pre-daemonize)
161
+ * it will return success always.
162
+ */
163
+int daemon_status_send(char status)
164
+{
165
+	int ret;
166
+
167
+	if (daemon_status_fd[1] == -1)
168
+		return 0;
169
+retry:
170
+	ret = write(daemon_status_fd[1], &status, 1);
171
+	if (ret < 0 && errno == EINTR)
172
+		goto retry;
173
+	return (ret ==1 ) ? 0 : -1;
174
+}
175
+
176
+
177
+
178
+/** cleanup functions for new processes.
179
+ * Should be called after fork(), for each new process that _does_ _not_
180
+ * use  daemon_status_send() or daemon_status_wait().
181
+ */
182
+void daemon_status_on_fork_cleanup()
183
+{
184
+	if (daemon_status_fd[0] != -1) {
185
+		close(daemon_status_fd[0]);
186
+		daemon_status_fd[0] = -1;
187
+	}
188
+	if (daemon_status_fd[1] != -1) {
189
+		close(daemon_status_fd[1]);
190
+		daemon_status_fd[1] = -1;
191
+	}
192
+}
193
+
194
+
195
+
196
+/** cleanup functions for processes that don't intead to wait.
197
+ * Should be called after fork(), for each new process that doesn't
198
+ * use daemon_status_wait().
199
+ */
200
+void daemon_status_no_wait()
201
+{
202
+	if (daemon_status_fd[0] != -1) {
203
+		close(daemon_status_fd[0]);
204
+		daemon_status_fd[0] = -1;
205
+	}
206
+}
207
+
208
+
209
+
210
+/** daemon init.
211
+ *@param name - daemon name used for logging (used when opening syslog).
212
+ *@param status_wait  - if 1 the original process will wait until it gets
213
+ *                  an exit code send using daemon_status_send().
214
+ *@return 0 in the child process (in case of daemonize mode),
215
+ *        -1 on error.
216
+ * The original process that called daemonize() will be terminated if
217
+ * dont_daemonize == 0. The exit code depends on status_wait. If status_wait
218
+ * is non-zero, the original process will wait for a status code, that
219
+ * must be sent with daemon_status_send() (daemon_status_send() must be
220
+ * called or the original process will remain waiting until all the children
221
+ * close()). If status_wait is 0, the original process will exit immediately
222
+ * with exit(0).
223
+ * Global variables/config params used:
224
+ * dont_daemonize
225
+ * chroot_dir
226
+ * working_dir
227
+ * pid_file - if set the pid will be written here (ascii).
228
+ * pgid_file - if set, the pgid will be written here (ascii).
229
+ * log_stderr - if not set syslog will be opened (openlog(name,...))
230
+ * 
231
+ *
232
+ * Side-effects:
233
+ *  sets own_pgid after becoming session leader (own process group).
234
+*/
235
+int daemonize(char*  name,  int status_wait)
86 236
 {
87 237
 	FILE *pid_stream;
88 238
 	pid_t pid;
89 239
 	int r, p;
90
-
240
+	char pipe_status;
91 241
 
92 242
 	p=-1;
93
-
94 243
 	/* flush std file descriptors to avoid flushes after fork
95 244
 	 *  (same message appearing multiple times)
96 245
 	 *  and switch to unbuffered
... ...
@@ -108,14 +253,27 @@ int daemonize(char*  name,  int daemon_status_fd_input)
108 108
 	}
109 109
 
110 110
 	if (!dont_daemonize) {
111
+		if (status_wait) {
112
+			if (daemon_status_pre_daemonize() < 0)
113
+				goto error;
114
+		}
111 115
 		/* fork to become!= group leader*/
112 116
 		if ((pid=fork())<0){
113 117
 			LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
114 118
 			goto error;
115
-		}else if (pid!=0){	
116
-			/*parent process => return 0 */
117
-			return 0;
119
+		}else if (pid!=0){
120
+			if (status_wait) {
121
+				if (daemon_status_wait(&pipe_status) == 0)
122
+					exit((int)pipe_status);
123
+				else{
124
+					LOG(L_ERR, "Main process exited before writing to pipe\n");
125
+					exit(-1);
126
+				}
127
+			}
128
+			exit(0);
118 129
 		}
130
+		if (status_wait)
131
+			daemon_status_no_wait(); /* clean unused read fd */
119 132
 		/* become session leader to drop the ctrl. terminal */
120 133
 		if (setsid()<0){
121 134
 			LOG(L_WARN, "setsid failed: %s\n",strerror(errno));
... ...
@@ -211,11 +369,11 @@ int daemonize(char*  name,  int daemon_status_fd_input)
211 211
 		/* continue, leave it open */
212 212
 	};
213 213
 	
214
-	/* close all but the daemon_status_fd_input as the main process
214
+	/* close all but the daemon_status_fd output as the main process
215 215
 	  must still write into it to tell the parent to exit with 0 */
216 216
 	closelog();
217 217
 	for (r=3;r<MAX_FD; r++){
218
-		if(r !=  daemon_status_fd_input)
218
+		if(r !=  daemon_status_fd[1])
219 219
 			close(r);
220 220
 	}
221 221
 	
... ...
@@ -440,5 +598,3 @@ int set_rt_prio(int prio, int policy)
440 440
 	return -1;
441 441
 #endif
442 442
 }
443
-
444
-
... ...
@@ -3,28 +3,25 @@
3 3
  *
4 4
  * Copyright (C) 2001-2003 FhG Fokus
5 5
  *
6
- * This file is part of SIP-router, a free SIP server.
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
7 9
  *
8
- * SIP-router is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version
12
- *
13
- * SIP-router is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License 
19
- * along with this program; if not, write to the Free Software 
20
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 17
  */
22 18
 /*
23 19
  * 
24 20
  * History:
25 21
  * --------
26 22
  *  2004-02-20  created by andrei
27
- *  2007-06-07 added mem_lock_pages() (andrei)
23
+ *  2007-06-07  added mem_lock_pages() (andrei)
24
+ *  2010-08-19  send status via pipe code derived from 9167c1 (ibc) (andrei)
28 25
  */
29 26
 
30 27
 #ifndef _daemonize_h
... ...
@@ -37,5 +34,12 @@ int set_core_dump(int enable, int size);
37 37
 int mem_lock_pages();
38 38
 int set_rt_prio(int prio, int policy);
39 39
 
40
+void daemon_status_init();
41
+void daemon_status_on_fork_cleanup();
42
+int daemon_status_send(char status);
43
+void daemon_status_no_wait();
44
+void daemon_status_on_fork_cleanup();
45
+
46
+#endif /*_daemonize_h */
40 47
 
41
-#endif
48
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */
... ...
@@ -76,6 +76,7 @@
76 76
  * 2010-04-19  added daemon_status_fd pipe to communicate the parent process
77 77
  *              with the main process in daemonize mode, so the parent process
78 78
  *              can return the proper exit status code (ibc)
79
+ * 2010-08-19  moved the daemon status stuff to daemonize.c (andrei)
79 80
  */
80 81
 
81 82
 /** main file (init, daemonize, startup) 
... ...
@@ -259,9 +260,6 @@ Options:\n\
259 259
 #endif
260 260
 ;
261 261
 
262
-/*! pipe to communicate the parent and main processes when daemonizing in order
263
-    to get the proper exit status code */
264
-int daemon_status_fd[2];
265 262
 
266 263
 /* print compile-time constants */
267 264
 void print_ct_constants()
... ...
@@ -1666,11 +1664,11 @@ int main_loop()
1666 1666
 		}
1667 1667
 #endif
1668 1668
 		DBG("Expect maximum %d  open fds\n", get_max_open_fds());
1669
-		/* in daemonize mode write into daemon_status_fd[1] so the parent process
1670
-	 	will exit with 0 */
1671
-		if (!dont_fork){
1672
-			if (write(daemon_status_fd[1], "go", 2)<0){
1673
-				LM_CRIT("error writing into daemon_status_fd[1]\n");
1669
+		/* in daemonize mode send the exit code back to the parent process */
1670
+		if (!dont_daemonize) {
1671
+			if (daemon_status_send(0) < 0) {
1672
+				ERR("error sending daemon status: %s [%d]\n",
1673
+						strerror(errno), errno);
1674 1674
 				goto error;
1675 1675
 			}
1676 1676
 		}
... ...
@@ -1741,13 +1739,6 @@ int main(int argc, char** argv)
1741 1741
 	int debug_save, debug_flag;
1742 1742
 	int dont_fork_cnt;
1743 1743
 	struct name_lst* n_lst;
1744
-
1745
-	/* variables to control the master process exit status */
1746
-	int fd_nbytes;
1747
-	char fd_readbuffer[5];
1748
-	struct timeval tval;
1749
-	fd_set fds;
1750
-	int res;
1751 1744
 	char *p;
1752 1745
 
1753 1746
 	/*init*/
... ...
@@ -1758,6 +1749,7 @@ int main(int argc, char** argv)
1758 1758
 	debug_flag=0;
1759 1759
 	dont_fork_cnt=0;
1760 1760
 
1761
+	daemon_status_init();
1761 1762
 	/*init pkg mallocs (before parsing cfg or cmd line !)*/
1762 1763
 	if (init_pkg_mallocs()==-1)
1763 1764
 		goto error;
... ...
@@ -2322,43 +2314,8 @@ try_again:
2322 2322
 	}
2323 2323
 #endif /* USE_SCTP */
2324 2324
 	/* init_daemon? */
2325
-	if (!dont_fork){
2326
-		if (pipe(daemon_status_fd)<0){
2327
-			LM_CRIT("could not create pipe(daemon_status_fd), exiting...\n");
2328
-			goto error;
2329
-		}
2330
-		if (daemonize((log_name==0)?argv[0]:log_name, daemon_status_fd[1]) < 0)
2331
-			goto error;
2332
-		/* parent process? then wait the main process to write into the pipe */
2333
-		if (getpid() == creator_pid) {
2334
-			/* close the output side of the pipe */
2335
-			close(daemon_status_fd[1]);
2336
-#define MASTER_MAX_SLEEP 10
2337
-try_select_again:	tval.tv_usec = 0;
2338
-			tval.tv_sec = MASTER_MAX_SLEEP;/* 10 seconds */
2339
-			FD_ZERO(&fds);
2340
-			FD_SET(daemon_status_fd[0], &fds);
2341
-			res = select(daemon_status_fd[0]+1, &fds, NULL, NULL, &tval);
2342
-			if(res == -1 && errno == EINTR && time(NULL)-up_since < 2*MASTER_MAX_SLEEP) 
2343
-				goto try_select_again;
2344
-
2345
-			switch(res){
2346
-				case -1: /* error on select*/ LOG(L_ERR, "Error in select in master process\n");exit(-1);
2347
-				case 0: /* timeout */ LOG(L_ERR, "timeout in select in master process\n");exit(-2);
2348
-				default:{
2349
-					fd_nbytes = read(daemon_status_fd[0], fd_readbuffer, 5);
2350
-					/* something read, ok, exit with 0 */
2351
-					if (fd_nbytes > 0)
2352
-						exit(0);
2353
-					/* nothing read, error */
2354
-					else{
2355
-						LOG(L_ERR, "Main process exited before writing to pipe\n");
2356
-						exit(-1);
2357
-					}
2358
-				}
2359
-			}
2360
-		}
2361
-	}
2325
+	if( !dont_fork && daemonize((log_name==0)?argv[0]:log_name, 1) < 0)
2326
+		goto error;
2362 2327
 	if (install_sigs() != 0){
2363 2328
 		fprintf(stderr, "ERROR: could not install the signal handlers\n");
2364 2329
 		goto error;
... ...
@@ -2439,14 +2396,25 @@ try_select_again:	tval.tv_usec = 0;
2439 2439
 #endif
2440 2440
 
2441 2441
 	ret=main_loop();
2442
+	if (ret < 0)
2443
+		goto error;
2442 2444
 	/*kill everything*/
2443 2445
 	if (is_main) shutdown_children(SIGTERM, 0);
2446
+	if (!dont_daemonize) {
2447
+		if (daemon_status_send(0) < 0)
2448
+			ERR("error sending exit status: %s [%d]\n",
2449
+					strerror(errno), errno);
2450
+	}
2444 2451
 	/* else terminate process */
2445 2452
 	return ret;
2446 2453
 
2447 2454
 error:
2448 2455
 	/*kill everything*/
2449 2456
 	if (is_main) shutdown_children(SIGTERM, 0);
2457
+	if (!dont_daemonize) {
2458
+		if (daemon_status_send((char)-1) < 0)
2459
+			ERR("error sending exit status: %s [%d]\n",
2460
+					strerror(errno), errno);
2461
+	}
2450 2462
 	return -1;
2451
-
2452 2463
 }
... ...
@@ -3,30 +3,19 @@
3 3
  *
4 4
  * Process Table
5 5
  *
6
- *
7
- *
8 6
  * Copyright (C) 2001-2003 FhG Fokus
9 7
  *
10
- * This file is part of ser, a free SIP server.
11
- *
12
- * ser is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2 of the License, or
15
- * (at your option) any later version
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
16 11
  *
17
- * For a license to use the ser software under conditions
18
- * other than those described here, or to purchase support for this
19
- * software, please contact iptel.org by e-mail at the following addresses:
20
- *    info@iptel.org
21
- *
22
- * ser is distributed in the hope that it will be useful,
23
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
- * GNU General Public License for more details.
26
- *
27
- * You should have received a copy of the GNU General Public License 
28
- * along with this program; if not, write to the Free Software 
29
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 19
  */
31 20
 /*
32 21
  * History:
... ...
@@ -36,13 +25,11 @@
36 36
  *  2006-10-25	sanity check before allowing forking w/ tcp support (is_main
37 37
  *               & tcp not started yet); set is_main=0 in childs (andrei)
38 38
  *  2007-07-04	added register_fds() and get_max_open_fds(() (andrei)
39
+ *  2010-08-19	use daemon_status_on_fork_cleanup() (andrei)
39 40
  */
40
-
41
-/*!
42
- * \file
43
- * \brief SIP-router core :: 
44
- * \ingroup core
45
- * Module: \ref core
41
+/** internal fork functions and process table.
42
+ * @file: pt.c
43
+ * @ingroup core
46 44
  */
47 45
 
48 46
 
... ...
@@ -314,6 +301,7 @@ int fork_process(int child_id, char *desc, int make_sock)
314 314
 		/* child */
315 315
 		is_main=0; /* a forked process cannot be the "main" one */
316 316
 		process_no=child_process_no;
317
+		daemon_status_on_fork_cleanup();
317 318
 		/* close tcp unix sockets if this is not tcp main */
318 319
 #ifdef USE_TCP
319 320
 		close_extra_socks(child_id, process_no);
... ...
@@ -465,6 +453,7 @@ int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
465 465
 				tcp_children[i].unix_sock=-1;
466 466
 			}
467 467
 		}
468
+		daemon_status_on_fork_cleanup();
468 469
 		srand(new_seed1);
469 470
 		fastrand_seed(rand());
470 471
 		srandom(new_seed2+time(0));
... ...
@@ -7,26 +7,17 @@
7 7
  *
8 8
  * Copyright (C) 2001-2003 FhG Fokus
9 9
  *
10
- * This file is part of ser, a free SIP server.
10
+ * Permission to use, copy, modify, and distribute this software for any
11
+ * purpose with or without fee is hereby granted, provided that the above
12
+ * copyright notice and this permission notice appear in all copies.
11 13
  *
12
- * ser is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2 of the License, or
15
- * (at your option) any later version
16
- *
17
- * For a license to use the ser software under conditions
18
- * other than those described here, or to purchase support for this
19
- * software, please contact iptel.org by e-mail at the following addresses:
20
- *    info@iptel.org
21
- *
22
- * ser is distributed in the hope that it will be useful,
23
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
- * GNU General Public License for more details.
26
- *
27
- * You should have received a copy of the GNU General Public License 
28
- * along with this program; if not, write to the Free Software 
29
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 21
  */
31 22
 /*
32 23
  * History:
... ...
@@ -35,6 +26,10 @@
35 35
  *  2006-06-14	added process table in shared mem (dragos)
36 36
  *  2007-07-04	added register_fds() and get_max_open_fds(() (andrei)
37 37
  */
38
+/** internal fork functions and process table.
39
+ * @file: pt.h
40
+ * @ingroup core
41
+ */
38 42
 
39 43
 
40 44
 #ifndef _PT_H