nsprpub/pr/tests/forktest.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /***********************************************************************
     7 **
     8 ** Name: forktest.c
     9 **
    10 ** Description: UNIX test for fork functions.
    11 **
    12 ** Modification History:
    13 ** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
    14 **                 The debug mode will print all of the printfs associated with this test.
    15 **                         The regress mode will be the default mode. Since the regress tool limits
    16 **           the output to a one line status:PASS or FAIL,all of the printf statements
    17 **                         have been handled with an if (debug_mode) statement.
    18 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
    19 **                        recognize the return code from tha main program.
    20 ** 12-June-97 AGarcic - Revert to return code 0 and 1, remove debug option (obsolete).
    21 ***********************************************************************/
    23 /***********************************************************************
    24 ** Includes
    25 ***********************************************************************/
    26 /* Used to get the command line option */
    27 #include "plgetopt.h"
    29 #include "nspr.h"
    30 #include <string.h>
    31 #include <stdio.h>
    32 #include <stdlib.h>
    34 PRIntn failed_already=0;
    36 #ifdef XP_UNIX
    38 #include <sys/types.h>
    39 #include <sys/wait.h>
    40 #include <unistd.h>
    41 #include <errno.h>
    43 static char *message = "Hello world!";
    45 static void
    46 ClientThreadFunc(void *arg)
    47 {
    48     PRNetAddr addr;
    49     PRFileDesc *sock = NULL;
    50     PRInt32 tmp = (PRInt32)arg;
    52     /*
    53      * Make sure the PR_Accept call will block
    54      */
    56     printf("Wait one second before connect\n");
    57     fflush(stdout);
    58     PR_Sleep(PR_SecondsToInterval(1));
    60     addr.inet.family = AF_INET;
    61     addr.inet.ip = PR_htonl(INADDR_ANY);
    62     addr.inet.port = 0;
    63     if ((sock = PR_NewTCPSocket()) == NULL) {
    64         fprintf(stderr, "failed to create TCP socket: error code %d\n",
    65             PR_GetError());
    66         failed_already = 1;
    67         goto finish;
    68     }
    69     if (PR_Bind(sock, &addr) != PR_SUCCESS) {
    70         fprintf(stderr, "PR_Bind failed: error code %d\n",
    71             PR_GetError());
    72         failed_already = 1;
    73         goto finish;
    74     }
    75     addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
    76     addr.inet.port = PR_htons((PRInt16)tmp);
    77     printf("Connecting to port %hu\n", PR_ntohs(addr.inet.port));
    78     fflush(stdout);
    79     if (PR_Connect(sock, &addr, PR_SecondsToInterval(5)) !=
    80         PR_SUCCESS) {
    81         fprintf(stderr, "PR_Connect failed: error code %d\n",
    82             PR_GetError());
    83         failed_already = 1;
    84         goto finish;
    85     }
    86     printf("Writing message \"%s\"\n", message);
    87     fflush(stdout);
    88     if (PR_Send(sock, message, strlen(message) + 1, 0, PR_INTERVAL_NO_TIMEOUT) ==
    89         -1) {
    90         fprintf(stderr, "PR_Send failed: error code %d\n",
    91             PR_GetError());
    92         failed_already = 1;
    93         goto finish;
    94     }
    95 finish:
    96     if (sock) {
    97         PR_Close(sock);
    98     }
    99     return;
   100 }
   102 /*
   103  * DoIO --
   104  *     This function creates a thread that acts as a client and itself.
   105  *     acts as a server.  Then it joins the client thread.
   106  */
   107 static void
   108 DoIO(void)
   109 {
   110     PRThread *clientThread;
   111     PRFileDesc *listenSock = NULL;
   112     PRFileDesc *sock = NULL;
   113     PRNetAddr addr;
   114     PRInt32 nBytes;
   115     char buf[128];
   117     listenSock = PR_NewTCPSocket();
   118     if (!listenSock) {
   119         fprintf(stderr, "failed to create a TCP socket: error code %d\n",
   120             PR_GetError());
   121         failed_already = 1;
   122         goto finish;
   123     }
   124     addr.inet.family = AF_INET;
   125     addr.inet.ip = PR_htonl(INADDR_ANY);
   126     addr.inet.port = 0;
   127     if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
   128         fprintf(stderr, "failed to bind socket: error code %d\n",
   129             PR_GetError());
   130         failed_already = 1;
   131         goto finish;
   132     }
   133     if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
   134         fprintf(stderr, "failed to get socket port number: error code %d\n",
   135             PR_GetError());
   136         failed_already = 1;
   137         goto finish;
   138     }
   139     if (PR_Listen(listenSock, 5) == PR_FAILURE) {
   140         fprintf(stderr, "PR_Listen failed: error code %d\n",
   141             PR_GetError());
   142         failed_already = 1;
   143         goto finish;
   144     }
   145     clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc,
   146         (void *) PR_ntohs(addr.inet.port), PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
   147         PR_JOINABLE_THREAD, 0);
   148     if (clientThread == NULL) {
   149         fprintf(stderr, "Cannot create client thread: (%d, %d)\n",
   150             PR_GetError(), PR_GetOSError());
   151         failed_already = 1;
   152         goto finish;
   153     }
   154     printf("Accepting connection at port %hu\n", PR_ntohs(addr.inet.port));
   155     fflush(stdout);
   156     sock = PR_Accept(listenSock, &addr, PR_SecondsToInterval(5));
   157     if (!sock) {
   158         fprintf(stderr, "PR_Accept failed: error code %d\n",
   159             PR_GetError());
   160         failed_already = 1;
   161         goto finish;
   162     }
   163     nBytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
   164     if (nBytes == -1) {
   165         fprintf(stderr, "PR_Recv failed: error code %d\n",
   166             PR_GetError());
   167         failed_already = 1;
   168         goto finish;
   169     }
   171     /*
   172      * Make sure it has proper null byte to mark end of string 
   173      */
   175     buf[sizeof(buf) - 1] = '\0';
   176     printf("Received \"%s\" from the client\n", buf);
   177     fflush(stdout);
   178     if (!strcmp(buf, message)) {
   179         PR_JoinThread(clientThread);
   181         printf("The message is received correctly\n");
   182         fflush(stdout);
   183     } else {
   184         fprintf(stderr, "The message should be \"%s\"\n",
   185             message);
   186         failed_already = 1;
   187     }
   189 finish:
   190     if (listenSock) {
   191         PR_Close(listenSock);
   192     }
   193     if (sock) {
   194         PR_Close(sock);
   195     }
   196     return;
   197 }
   199 #ifdef _PR_DCETHREADS
   201 #include <syscall.h>
   203 pid_t PR_UnixFork1(void)
   204 {
   205     pid_t parent = getpid();
   206     int rv = syscall(SYS_fork);
   208     if (rv == -1) {
   209         return (pid_t) -1;
   210     } else {
   211         /* For each process, rv is the pid of the other process */
   212         if (rv == parent) {
   213             /* the child */
   214             return 0;
   215         } else {
   216             /* the parent */
   217             return rv;
   218         }
   219     }
   220 }
   222 #elif defined(SOLARIS)
   224 /*
   225  * It seems like that in Solaris 2.4 one must call fork1() if the
   226  * the child process is going to use thread functions.  Solaris 2.5
   227  * doesn't have this problem. Calling fork() also works. 
   228  */
   230 pid_t PR_UnixFork1(void)
   231 {
   232     return fork1();
   233 }
   235 #else
   237 pid_t PR_UnixFork1(void)
   238 {
   239     return fork();
   240 }
   242 #endif  /* PR_DCETHREADS */
   244 int main(int argc, char **argv)
   245 {
   246     pid_t pid;
   247 	int rv;
   249     /* main test program */
   251     DoIO();
   253     pid = PR_UnixFork1();
   255     if (pid  == (pid_t) -1) {
   256         fprintf(stderr, "Fork failed: errno %d\n", errno);
   257         failed_already=1;
   258         return 1;
   259     } else if (pid > 0) {
   260         int childStatus;
   262         printf("Fork succeeded.  Parent process continues.\n");
   263         DoIO();
   264         if ((rv = waitpid(pid, &childStatus, 0)) != pid) {
   265 #if defined(IRIX) && !defined(_PR_PTHREADS)
   266 			/*
   267 			 * nspr may handle SIGCLD signal
   268 			 */
   269 			if ((rv < 0) && (errno == ECHILD)) {
   270 			} else 
   271 #endif
   272 			{
   273 				fprintf(stderr, "waitpid failed: %d\n", errno);
   274 				failed_already = 1;
   275 			}
   276         } else if (!WIFEXITED(childStatus)
   277                 || WEXITSTATUS(childStatus) != 0) {
   278             failed_already = 1;
   279         }
   280         printf("Parent process exits.\n");
   281         if (!failed_already) {
   282             printf("PASSED\n");
   283         } else {
   284             printf("FAILED\n");
   285         }
   286         return failed_already;
   287     } else {
   288 #if defined(IRIX) && !defined(_PR_PTHREADS)
   289 		extern void _PR_IRIX_CHILD_PROCESS(void);
   290 		_PR_IRIX_CHILD_PROCESS();
   291 #endif
   292         printf("Fork succeeded.  Child process continues.\n");
   293         DoIO();
   294         printf("Child process exits.\n");
   295         return failed_already;
   296     }
   297 }
   299 #else  /* XP_UNIX */
   301 int main(    int     argc,
   302 char   *argv[]
   303 )
   304 {
   306     printf("The fork test is applicable to Unix only.\n");
   307     return 0;
   309 }
   311 #endif  /* XP_UNIX */

mercurial