VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/forktest.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/***********************************************************************
39**
40** Name: forktest.c
41**
42** Description: UNIX test for fork functions.
43**
44** Modification History:
45** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
46** The debug mode will print all of the printfs associated with this test.
47** The regress mode will be the default mode. Since the regress tool limits
48** the output to a one line status:PASS or FAIL,all of the printf statements
49** have been handled with an if (debug_mode) statement.
50** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
51** recognize the return code from tha main program.
52** 12-June-97 AGarcic - Revert to return code 0 and 1, remove debug option (obsolete).
53***********************************************************************/
54
55/***********************************************************************
56** Includes
57***********************************************************************/
58/* Used to get the command line option */
59#include "plgetopt.h"
60
61#include "nspr.h"
62#include <string.h>
63#include <stdio.h>
64#include <stdlib.h>
65
66PRIntn failed_already=0;
67
68#ifdef XP_UNIX
69
70#include <sys/types.h>
71#include <sys/wait.h>
72#include <unistd.h>
73#include <errno.h>
74
75static char *message = "Hello world!";
76
77static void
78ClientThreadFunc(void *arg)
79{
80 PRNetAddr addr;
81 PRFileDesc *sock = NULL;
82 PRInt32 tmp = (PRInt32)arg;
83
84 /*
85 * Make sure the PR_Accept call will block
86 */
87
88 printf("Wait one second before connect\n");
89 fflush(stdout);
90 PR_Sleep(PR_SecondsToInterval(1));
91
92 addr.inet.family = AF_INET;
93 addr.inet.ip = PR_htonl(INADDR_ANY);
94 addr.inet.port = 0;
95 if ((sock = PR_NewTCPSocket()) == NULL) {
96 fprintf(stderr, "failed to create TCP socket: error code %d\n",
97 PR_GetError());
98 failed_already = 1;
99 goto finish;
100 }
101 if (PR_Bind(sock, &addr) != PR_SUCCESS) {
102 fprintf(stderr, "PR_Bind failed: error code %d\n",
103 PR_GetError());
104 failed_already = 1;
105 goto finish;
106 }
107 addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
108 addr.inet.port = PR_htons((PRInt16)tmp);
109 printf("Connecting to port %hu\n", PR_ntohs(addr.inet.port));
110 fflush(stdout);
111 if (PR_Connect(sock, &addr, PR_SecondsToInterval(5)) !=
112 PR_SUCCESS) {
113 fprintf(stderr, "PR_Connect failed: error code %d\n",
114 PR_GetError());
115 failed_already = 1;
116 goto finish;
117 }
118 printf("Writing message \"%s\"\n", message);
119 fflush(stdout);
120 if (PR_Send(sock, message, strlen(message) + 1, 0, PR_INTERVAL_NO_TIMEOUT) ==
121 -1) {
122 fprintf(stderr, "PR_Send failed: error code %d\n",
123 PR_GetError());
124 failed_already = 1;
125 goto finish;
126 }
127finish:
128 if (sock) {
129 PR_Close(sock);
130 }
131 return;
132}
133
134/*
135 * DoIO --
136 * This function creates a thread that acts as a client and itself.
137 * acts as a server. Then it joins the client thread.
138 */
139static void
140DoIO(void)
141{
142 PRThread *clientThread;
143 PRFileDesc *listenSock = NULL;
144 PRFileDesc *sock = NULL;
145 PRNetAddr addr;
146 PRInt32 nBytes;
147 char buf[128];
148
149 listenSock = PR_NewTCPSocket();
150 if (!listenSock) {
151 fprintf(stderr, "failed to create a TCP socket: error code %d\n",
152 PR_GetError());
153 failed_already = 1;
154 goto finish;
155 }
156 addr.inet.family = AF_INET;
157 addr.inet.ip = PR_htonl(INADDR_ANY);
158 addr.inet.port = 0;
159 if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
160 fprintf(stderr, "failed to bind socket: error code %d\n",
161 PR_GetError());
162 failed_already = 1;
163 goto finish;
164 }
165 if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
166 fprintf(stderr, "failed to get socket port number: error code %d\n",
167 PR_GetError());
168 failed_already = 1;
169 goto finish;
170 }
171 if (PR_Listen(listenSock, 5) == PR_FAILURE) {
172 fprintf(stderr, "PR_Listen failed: error code %d\n",
173 PR_GetError());
174 failed_already = 1;
175 goto finish;
176 }
177 clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc,
178 (void *) PR_ntohs(addr.inet.port), PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
179 PR_JOINABLE_THREAD, 0);
180 if (clientThread == NULL) {
181 fprintf(stderr, "Cannot create client thread: (%d, %d)\n",
182 PR_GetError(), PR_GetOSError());
183 failed_already = 1;
184 goto finish;
185 }
186 printf("Accepting connection at port %hu\n", PR_ntohs(addr.inet.port));
187 fflush(stdout);
188 sock = PR_Accept(listenSock, &addr, PR_SecondsToInterval(5));
189 if (!sock) {
190 fprintf(stderr, "PR_Accept failed: error code %d\n",
191 PR_GetError());
192 failed_already = 1;
193 goto finish;
194 }
195 nBytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
196 if (nBytes == -1) {
197 fprintf(stderr, "PR_Recv failed: error code %d\n",
198 PR_GetError());
199 failed_already = 1;
200 goto finish;
201 }
202
203 /*
204 * Make sure it has proper null byte to mark end of string
205 */
206
207 buf[sizeof(buf) - 1] = '\0';
208 printf("Received \"%s\" from the client\n", buf);
209 fflush(stdout);
210 if (!strcmp(buf, message)) {
211 PR_JoinThread(clientThread);
212
213 printf("The message is received correctly\n");
214 fflush(stdout);
215 } else {
216 fprintf(stderr, "The message should be \"%s\"\n",
217 message);
218 failed_already = 1;
219 }
220
221finish:
222 if (listenSock) {
223 PR_Close(listenSock);
224 }
225 if (sock) {
226 PR_Close(sock);
227 }
228 return;
229}
230
231#ifdef _PR_DCETHREADS
232
233#include <syscall.h>
234
235pid_t PR_UnixFork1(void)
236{
237 pid_t parent = getpid();
238 int rv = syscall(SYS_fork);
239
240 if (rv == -1) {
241 return (pid_t) -1;
242 } else {
243 /* For each process, rv is the pid of the other process */
244 if (rv == parent) {
245 /* the child */
246 return 0;
247 } else {
248 /* the parent */
249 return rv;
250 }
251 }
252}
253
254#elif defined(SOLARIS)
255
256/*
257 * It seems like that in Solaris 2.4 one must call fork1() if the
258 * the child process is going to use thread functions. Solaris 2.5
259 * doesn't have this problem. Calling fork() also works.
260 */
261
262pid_t PR_UnixFork1(void)
263{
264 return fork1();
265}
266
267#else
268
269pid_t PR_UnixFork1(void)
270{
271 return fork();
272}
273
274#endif /* PR_DCETHREADS */
275
276int main(
277int argc,
278char *argv[]
279)
280{
281 pid_t pid;
282 int rv;
283
284 /* main test program */
285
286 DoIO();
287
288 pid = PR_UnixFork1();
289
290 if (pid == (pid_t) -1) {
291 fprintf(stderr, "Fork failed: errno %d\n", errno);
292 failed_already=1;
293 return 1;
294 } else if (pid > 0) {
295 int childStatus;
296
297 printf("Fork succeeded. Parent process continues.\n");
298 DoIO();
299 if ((rv = waitpid(pid, &childStatus, 0)) != pid) {
300#if defined(IRIX) && !defined(_PR_PTHREADS)
301 /*
302 * nspr may handle SIGCLD signal
303 */
304 if ((rv < 0) && (errno == ECHILD)) {
305 } else
306#endif
307 {
308 fprintf(stderr, "waitpid failed: %d\n", errno);
309 failed_already = 1;
310 }
311 } else if (!WIFEXITED(childStatus)
312 || WEXITSTATUS(childStatus) != 0) {
313 failed_already = 1;
314 }
315 printf("Parent process exits.\n");
316 if (!failed_already) {
317 printf("PASSED\n");
318 } else {
319 printf("FAILED\n");
320 }
321 return failed_already;
322 } else {
323#if defined(IRIX) && !defined(_PR_PTHREADS)
324 extern void _PR_IRIX_CHILD_PROCESS(void);
325 _PR_IRIX_CHILD_PROCESS();
326#endif
327 printf("Fork succeeded. Child process continues.\n");
328 DoIO();
329 printf("Child process exits.\n");
330 return failed_already;
331 }
332}
333
334#else /* XP_UNIX */
335
336int main( int argc,
337char *argv[]
338)
339{
340
341 printf("The fork test is applicable to Unix only.\n");
342 return 0;
343
344}
345
346#endif /* XP_UNIX */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette