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 77
 #define MAX_FD 32 /* maximum number of inherited open file descriptors,
82 78
 		    (normally it shouldn't  be bigger  than 3) */
83 79
 
84
-/*! \brief daemon init, return 0 on success, -1 on error */
85
-int daemonize(char*  name,  int daemon_status_fd_input)
80
+/** temporary pipe FDs for sending exit status back to the ancestor process.
81
+ * This pipe is used to send the desired exit status to the initial process,
82
+ * that waits for it in the foreground. This way late errors preventing
83
+ * startup (e.g. during modules child inits or TCP late init) can still be
84
+ * reported back.
85
+ */
86
+static int daemon_status_fd[2];
87
+
88
+
89
+
90
+/** init daemon status reporting.
91
+ * Must be called before any other daemon_status function has a chance to
92
+ * run.
93
+ */
94
+void daemon_status_init()
95
+{
96
+	daemon_status_fd[0] = -1;
97
+	daemon_status_fd[1] = -1;
98
+}
99
+
100
+
101
+
102
+/** pre-daemonize init for daemon status reporting.
103
+ * Must be called before forking.
104
+ * Typically the parent process will call daemon_status_wait() while
105
+ * one of the children will call daemon_status_send() at some point.
106
+ *
107
+ * @return 0 on success, -1 on error (and sets errno).
108
+ */
109
+int daemon_status_pre_daemonize()
110
+{
111
+	int ret;
112
+	
113
+retry:
114
+	ret = pipe(daemon_status_fd);
115
+	if (ret < 0 && errno == EINTR)
116
+		goto retry;
117
+	return ret;
118
+}
119
+
120
+
121
+
122
+/** wait for an exit status to be send by daemon_status_send().
123
+ * @param status - filled with the sent status (a char).
124
+ * @return  0 on success, -1 on error (e.g. process died before sending
125
+ *          status, not intialized a.s.o.).
126
+ * Side-effects: it will close the write side of the pipe
127
+ *  (must not be used from the same process as the daemon_status_send()).
128
+ * Note: if init is not complete (only init, but no pre-daemonize)
129
+ * it will return success always and status 0.
130
+ */
131
+int daemon_status_wait(char* status)
132
+{
133
+	int ret;
134
+	
135
+	/* close the output side of the pipe */
136
+	if (daemon_status_fd[1] != -1) {
137
+		close(daemon_status_fd[1]);
138
+		daemon_status_fd[1] = -1;
139
+	}
140
+	if (daemon_status_fd[0] == -1) {
141
+		*status = 0;
142
+		return -1;
143
+	}
144
+retry:
145
+	ret = read(daemon_status_fd[0], status, 1);
146
+	if (ret < 0 && errno == EINTR)
147
+		goto retry;
148
+	return (ret ==1 ) ? 0 : -1;
149
+}
150
+
151
+
152
+
153
+/** send 'status' to a waiting process running daemon_status_wait().
154
+ * @param status - status byte
155
+ * @return 0 on success, -1 on error.
156
+ * Note: if init is not complete (only init, but no pre-daemonize)
157
+ * it will return success always.
158
+ */
159
+int daemon_status_send(char status)
160
+{
161
+	int ret;
162
+
163
+	if (daemon_status_fd[1] == -1)
164
+		return 0;
165
+retry:
166
+	ret = write(daemon_status_fd[1], &status, 1);
167
+	if (ret < 0 && errno == EINTR)
168
+		goto retry;
169
+	return (ret ==1 ) ? 0 : -1;
170
+}
171
+
172
+
173
+
174
+/** cleanup functions for new processes.
175
+ * Should be called after fork(), for each new process that _does_ _not_
176
+ * use  daemon_status_send() or daemon_status_wait().
177
+ */
178
+void daemon_status_on_fork_cleanup()
179
+{
180
+	if (daemon_status_fd[0] != -1) {
181
+		close(daemon_status_fd[0]);
182
+		daemon_status_fd[0] = -1;
183
+	}
184
+	if (daemon_status_fd[1] != -1) {
185
+		close(daemon_status_fd[1]);
186
+		daemon_status_fd[1] = -1;
187
+	}
188
+}
189
+
190
+
191
+
192
+/** cleanup functions for processes that don't intead to wait.
193
+ * Should be called after fork(), for each new process that doesn't
194
+ * use daemon_status_wait().
195
+ */
196
+void daemon_status_no_wait()
197
+{
198
+	if (daemon_status_fd[0] != -1) {
199
+		close(daemon_status_fd[0]);
200
+		daemon_status_fd[0] = -1;
201
+	}
202
+}
203
+
204
+
205
+
206
+/** daemon init.
207
+ *@param name - daemon name used for logging (used when opening syslog).
208
+ *@param status_wait  - if 1 the original process will wait until it gets
209
+ *                  an exit code send using daemon_status_send().
210
+ *@return 0 in the child process (in case of daemonize mode),
211
+ *        -1 on error.
212
+ * The original process that called daemonize() will be terminated if
213
+ * dont_daemonize == 0. The exit code depends on status_wait. If status_wait
214
+ * is non-zero, the original process will wait for a status code, that
215
+ * must be sent with daemon_status_send() (daemon_status_send() must be
216
+ * called or the original process will remain waiting until all the children
217
+ * close()). If status_wait is 0, the original process will exit immediately
218
+ * with exit(0).
219
+ * Global variables/config params used:
220
+ * dont_daemonize
221
+ * chroot_dir
222
+ * working_dir
223
+ * pid_file - if set the pid will be written here (ascii).
224
+ * pgid_file - if set, the pgid will be written here (ascii).
225
+ * log_stderr - if not set syslog will be opened (openlog(name,...))
226
+ * 
227
+ *
228
+ * Side-effects:
229
+ *  sets own_pgid after becoming session leader (own process group).
230
+*/
231
+int daemonize(char*  name,  int status_wait)
86 232
 {
87 233
 	FILE *pid_stream;
88 234
 	pid_t pid;
89 235
 	int r, p;
90
-
236
+	char pipe_status;
91 237
 
92 238
 	p=-1;
93
-
94 239
 	/* flush std file descriptors to avoid flushes after fork
95 240
 	 *  (same message appearing multiple times)
96 241
 	 *  and switch to unbuffered
... ...
@@ -108,14 +253,27 @@ int daemonize(char*  name,  int daemon_status_fd_input)
108 253
 	}
109 254
 
110 255
 	if (!dont_daemonize) {
256
+		if (status_wait) {
257
+			if (daemon_status_pre_daemonize() < 0)
258
+				goto error;
259
+		}
111 260
 		/* fork to become!= group leader*/
112 261
 		if ((pid=fork())<0){
113 262
 			LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
114 263
 			goto error;
115
-		}else if (pid!=0){	
116
-			/*parent process => return 0 */
117
-			return 0;
264
+		}else if (pid!=0){
265
+			if (status_wait) {
266
+				if (daemon_status_wait(&pipe_status) == 0)
267
+					exit((int)pipe_status);
268
+				else{
269
+					LOG(L_ERR, "Main process exited before writing to pipe\n");
270
+					exit(-1);
271
+				}
272
+			}
273
+			exit(0);
118 274
 		}
275
+		if (status_wait)
276
+			daemon_status_no_wait(); /* clean unused read fd */
119 277
 		/* become session leader to drop the ctrl. terminal */
120 278
 		if (setsid()<0){
121 279
 			LOG(L_WARN, "setsid failed: %s\n",strerror(errno));
... ...
@@ -211,11 +369,11 @@ int daemonize(char*  name,  int daemon_status_fd_input)
211 369
 		/* continue, leave it open */
212 370
 	};
213 371
 	
214
-	/* close all but the daemon_status_fd_input as the main process
372
+	/* close all but the daemon_status_fd output as the main process
215 373
 	  must still write into it to tell the parent to exit with 0 */
216 374
 	closelog();
217 375
 	for (r=3;r<MAX_FD; r++){
218
-		if(r !=  daemon_status_fd_input)
376
+		if(r !=  daemon_status_fd[1])
219 377
 			close(r);
220 378
 	}
221 379
 	
... ...
@@ -440,5 +598,3 @@ int set_rt_prio(int prio, int policy)
440 598
 	return -1;
441 599
 #endif
442 600
 }
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 34
 int mem_lock_pages();
38 35
 int set_rt_prio(int prio, int policy);
39 36
 
37
+void daemon_status_init();
38
+void daemon_status_on_fork_cleanup();
39
+int daemon_status_send(char status);
40
+void daemon_status_no_wait();
41
+void daemon_status_on_fork_cleanup();
42
+
43
+#endif /*_daemonize_h */
40 44
 
41
-#endif
45
+/* 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 260
 #endif
260 261
 ;
261 262
 
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 263
 
266 264
 /* print compile-time constants */
267 265
 void print_ct_constants()
... ...
@@ -1666,11 +1664,11 @@ int main_loop()
1666 1664
 		}
1667 1665
 #endif
1668 1666
 		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");
1667
+		/* in daemonize mode send the exit code back to the parent process */
1668
+		if (!dont_daemonize) {
1669
+			if (daemon_status_send(0) < 0) {
1670
+				ERR("error sending daemon status: %s [%d]\n",
1671
+						strerror(errno), errno);
1674 1672
 				goto error;
1675 1673
 			}
1676 1674
 		}
... ...
@@ -1741,13 +1739,6 @@ int main(int argc, char** argv)
1741 1739
 	int debug_save, debug_flag;
1742 1740
 	int dont_fork_cnt;
1743 1741
 	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 1742
 	char *p;
1752 1743
 
1753 1744
 	/*init*/
... ...
@@ -1758,6 +1749,7 @@ int main(int argc, char** argv)
1758 1749
 	debug_flag=0;
1759 1750
 	dont_fork_cnt=0;
1760 1751
 
1752
+	daemon_status_init();
1761 1753
 	/*init pkg mallocs (before parsing cfg or cmd line !)*/
1762 1754
 	if (init_pkg_mallocs()==-1)
1763 1755
 		goto error;
... ...
@@ -2322,43 +2314,8 @@ try_again:
2322 2314
 	}
2323 2315
 #endif /* USE_SCTP */
2324 2316
 	/* 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
-	}
2317
+	if( !dont_fork && daemonize((log_name==0)?argv[0]:log_name, 1) < 0)
2318
+		goto error;
2362 2319
 	if (install_sigs() != 0){
2363 2320
 		fprintf(stderr, "ERROR: could not install the signal handlers\n");
2364 2321
 		goto error;
... ...
@@ -2439,14 +2396,25 @@ try_select_again:	tval.tv_usec = 0;
2439 2396
 #endif
2440 2397
 
2441 2398
 	ret=main_loop();
2399
+	if (ret < 0)
2400
+		goto error;
2442 2401
 	/*kill everything*/
2443 2402
 	if (is_main) shutdown_children(SIGTERM, 0);
2403
+	if (!dont_daemonize) {
2404
+		if (daemon_status_send(0) < 0)
2405
+			ERR("error sending exit status: %s [%d]\n",
2406
+					strerror(errno), errno);
2407
+	}
2444 2408
 	/* else terminate process */
2445 2409
 	return ret;
2446 2410
 
2447 2411
 error:
2448 2412
 	/*kill everything*/
2449 2413
 	if (is_main) shutdown_children(SIGTERM, 0);
2414
+	if (!dont_daemonize) {
2415
+		if (daemon_status_send((char)-1) < 0)
2416
+			ERR("error sending exit status: %s [%d]\n",
2417
+					strerror(errno), errno);
2418
+	}
2450 2419
 	return -1;
2451
-
2452 2420
 }
... ...
@@ -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 25
  *  2006-10-25	sanity check before allowing forking w/ tcp support (is_main
37 26
  *               & tcp not started yet); set is_main=0 in childs (andrei)
38 27
  *  2007-07-04	added register_fds() and get_max_open_fds(() (andrei)
28
+ *  2010-08-19	use daemon_status_on_fork_cleanup() (andrei)
39 29
  */
40
-
41
-/*!
42
- * \file
43
- * \brief SIP-router core :: 
44
- * \ingroup core
45
- * Module: \ref core
30
+/** internal fork functions and process table.
31
+ * @file: pt.c
32
+ * @ingroup core
46 33
  */
47 34
 
48 35
 
... ...
@@ -314,6 +301,7 @@ int fork_process(int child_id, char *desc, int make_sock)
314 301
 		/* child */
315 302
 		is_main=0; /* a forked process cannot be the "main" one */
316 303
 		process_no=child_process_no;
304
+		daemon_status_on_fork_cleanup();
317 305
 		/* close tcp unix sockets if this is not tcp main */
318 306
 #ifdef USE_TCP
319 307
 		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 453
 				tcp_children[i].unix_sock=-1;
466 454
 			}
467 455
 		}
456
+		daemon_status_on_fork_cleanup();
468 457
 		srand(new_seed1);
469 458
 		fastrand_seed(rand());
470 459
 		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 26
  *  2006-06-14	added process table in shared mem (dragos)
36 27
  *  2007-07-04	added register_fds() and get_max_open_fds(() (andrei)
37 28
  */
29
+/** internal fork functions and process table.
30
+ * @file: pt.h
31
+ * @ingroup core
32
+ */
38 33
 
39 34
 
40 35
 #ifndef _PT_H