nsprpub/pr/tests/multiacc.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * File: multiacc.c
michael@0 8 *
michael@0 9 * Description:
michael@0 10 * This test creates multiple threads that accept on the
michael@0 11 * same listening socket.
michael@0 12 */
michael@0 13
michael@0 14 #include "nspr.h"
michael@0 15
michael@0 16 #include <stdio.h>
michael@0 17 #include <stdlib.h>
michael@0 18 #include <string.h>
michael@0 19
michael@0 20 #define NUM_SERVER_THREADS 10
michael@0 21
michael@0 22 static int num_server_threads = NUM_SERVER_THREADS;
michael@0 23 static PRThreadScope thread_scope = PR_GLOBAL_THREAD;
michael@0 24 static PRBool exit_flag = PR_FALSE;
michael@0 25
michael@0 26 static void ServerThreadFunc(void *arg)
michael@0 27 {
michael@0 28 PRFileDesc *listenSock = (PRFileDesc *) arg;
michael@0 29 PRFileDesc *acceptSock;
michael@0 30 PRErrorCode err;
michael@0 31 PRStatus status;
michael@0 32
michael@0 33 while (!exit_flag) {
michael@0 34 acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
michael@0 35 if (NULL == acceptSock) {
michael@0 36 err = PR_GetError();
michael@0 37 if (PR_PENDING_INTERRUPT_ERROR == err) {
michael@0 38 printf("server thread is interrupted\n");
michael@0 39 fflush(stdout);
michael@0 40 continue;
michael@0 41 }
michael@0 42 fprintf(stderr, "PR_Accept failed: %d\n", err);
michael@0 43 exit(1);
michael@0 44 }
michael@0 45 status = PR_Close(acceptSock);
michael@0 46 if (PR_FAILURE == status) {
michael@0 47 fprintf(stderr, "PR_Close failed\n");
michael@0 48 exit(1);
michael@0 49 }
michael@0 50 }
michael@0 51 }
michael@0 52
michael@0 53 int main(int argc, char **argv)
michael@0 54 {
michael@0 55 PRNetAddr serverAddr;
michael@0 56 PRFileDesc *dummySock;
michael@0 57 PRFileDesc *listenSock;
michael@0 58 PRFileDesc *clientSock;
michael@0 59 PRThread *dummyThread;
michael@0 60 PRThread **serverThreads;
michael@0 61 PRStatus status;
michael@0 62 PRUint16 port;
michael@0 63 int idx;
michael@0 64 PRInt32 nbytes;
michael@0 65 char buf[1024];
michael@0 66
michael@0 67 serverThreads = (PRThread **)
michael@0 68 PR_Malloc(num_server_threads * sizeof(PRThread *));
michael@0 69 if (NULL == serverThreads) {
michael@0 70 fprintf(stderr, "PR_Malloc failed\n");
michael@0 71 exit(1);
michael@0 72 }
michael@0 73
michael@0 74 /*
michael@0 75 * Create a dummy listening socket and have the first
michael@0 76 * (dummy) thread listen on it. This is to ensure that
michael@0 77 * the first thread becomes the I/O continuation thread
michael@0 78 * in the pthreads implementation (see ptio.c) and remains
michael@0 79 * so throughout the test, so that we never have to
michael@0 80 * recycle the I/O continuation thread.
michael@0 81 */
michael@0 82 dummySock = PR_NewTCPSocket();
michael@0 83 if (NULL == dummySock) {
michael@0 84 fprintf(stderr, "PR_NewTCPSocket failed\n");
michael@0 85 exit(1);
michael@0 86 }
michael@0 87 memset(&serverAddr, 0, sizeof(serverAddr));
michael@0 88 status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
michael@0 89 if (PR_FAILURE == status) {
michael@0 90 fprintf(stderr, "PR_InitializeNetAddr failed\n");
michael@0 91 exit(1);
michael@0 92 }
michael@0 93 status = PR_Bind(dummySock, &serverAddr);
michael@0 94 if (PR_FAILURE == status) {
michael@0 95 fprintf(stderr, "PR_Bind failed\n");
michael@0 96 exit(1);
michael@0 97 }
michael@0 98 status = PR_Listen(dummySock, 5);
michael@0 99 if (PR_FAILURE == status) {
michael@0 100 fprintf(stderr, "PR_Listen failed\n");
michael@0 101 exit(1);
michael@0 102 }
michael@0 103
michael@0 104 listenSock = PR_NewTCPSocket();
michael@0 105 if (NULL == listenSock) {
michael@0 106 fprintf(stderr, "PR_NewTCPSocket failed\n");
michael@0 107 exit(1);
michael@0 108 }
michael@0 109 memset(&serverAddr, 0, sizeof(serverAddr));
michael@0 110 status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
michael@0 111 if (PR_FAILURE == status) {
michael@0 112 fprintf(stderr, "PR_InitializeNetAddr failed\n");
michael@0 113 exit(1);
michael@0 114 }
michael@0 115 status = PR_Bind(listenSock, &serverAddr);
michael@0 116 if (PR_FAILURE == status) {
michael@0 117 fprintf(stderr, "PR_Bind failed\n");
michael@0 118 exit(1);
michael@0 119 }
michael@0 120 status = PR_GetSockName(listenSock, &serverAddr);
michael@0 121 if (PR_FAILURE == status) {
michael@0 122 fprintf(stderr, "PR_GetSockName failed\n");
michael@0 123 exit(1);
michael@0 124 }
michael@0 125 port = PR_ntohs(serverAddr.inet.port);
michael@0 126 status = PR_Listen(listenSock, 5);
michael@0 127 if (PR_FAILURE == status) {
michael@0 128 fprintf(stderr, "PR_Listen failed\n");
michael@0 129 exit(1);
michael@0 130 }
michael@0 131
michael@0 132 printf("creating dummy thread\n");
michael@0 133 fflush(stdout);
michael@0 134 dummyThread = PR_CreateThread(PR_USER_THREAD,
michael@0 135 ServerThreadFunc, dummySock, PR_PRIORITY_NORMAL,
michael@0 136 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 137 if (NULL == dummyThread) {
michael@0 138 fprintf(stderr, "PR_CreateThread failed\n");
michael@0 139 exit(1);
michael@0 140 }
michael@0 141 printf("sleeping one second before creating server threads\n");
michael@0 142 fflush(stdout);
michael@0 143 PR_Sleep(PR_SecondsToInterval(1));
michael@0 144 for (idx = 0; idx < num_server_threads; idx++) {
michael@0 145 serverThreads[idx] = PR_CreateThread(PR_USER_THREAD,
michael@0 146 ServerThreadFunc, listenSock, PR_PRIORITY_NORMAL,
michael@0 147 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 148 if (NULL == serverThreads[idx]) {
michael@0 149 fprintf(stderr, "PR_CreateThread failed\n");
michael@0 150 exit(1);
michael@0 151 }
michael@0 152 }
michael@0 153
michael@0 154 memset(&serverAddr, 0, sizeof(serverAddr));
michael@0 155 PR_InitializeNetAddr(PR_IpAddrLoopback, port, &serverAddr);
michael@0 156 clientSock = PR_NewTCPSocket();
michael@0 157 if (NULL == clientSock) {
michael@0 158 fprintf(stderr, "PR_NewTCPSocket failed\n");
michael@0 159 exit(1);
michael@0 160 }
michael@0 161 printf("sleeping one second before connecting\n");
michael@0 162 fflush(stdout);
michael@0 163 PR_Sleep(PR_SecondsToInterval(1));
michael@0 164 status = PR_Connect(clientSock, &serverAddr, PR_INTERVAL_NO_TIMEOUT);
michael@0 165 if (PR_FAILURE == status) {
michael@0 166 fprintf(stderr, "PR_Connect failed\n");
michael@0 167 exit(1);
michael@0 168 }
michael@0 169 nbytes = PR_Read(clientSock, buf, sizeof(buf));
michael@0 170 if (nbytes != 0) {
michael@0 171 fprintf(stderr, "expected 0 bytes but got %d bytes\n", nbytes);
michael@0 172 exit(1);
michael@0 173 }
michael@0 174 status = PR_Close(clientSock);
michael@0 175 if (PR_FAILURE == status) {
michael@0 176 fprintf(stderr, "PR_Close failed\n");
michael@0 177 exit(1);
michael@0 178 }
michael@0 179 printf("sleeping one second before shutting down server threads\n");
michael@0 180 fflush(stdout);
michael@0 181 PR_Sleep(PR_SecondsToInterval(1));
michael@0 182
michael@0 183 exit_flag = PR_TRUE;
michael@0 184 status = PR_Interrupt(dummyThread);
michael@0 185 if (PR_FAILURE == status) {
michael@0 186 fprintf(stderr, "PR_Interrupt failed\n");
michael@0 187 exit(1);
michael@0 188 }
michael@0 189 status = PR_JoinThread(dummyThread);
michael@0 190 if (PR_FAILURE == status) {
michael@0 191 fprintf(stderr, "PR_JoinThread failed\n");
michael@0 192 exit(1);
michael@0 193 }
michael@0 194 for (idx = 0; idx < num_server_threads; idx++) {
michael@0 195 status = PR_Interrupt(serverThreads[idx]);
michael@0 196 if (PR_FAILURE == status) {
michael@0 197 fprintf(stderr, "PR_Interrupt failed\n");
michael@0 198 exit(1);
michael@0 199 }
michael@0 200 status = PR_JoinThread(serverThreads[idx]);
michael@0 201 if (PR_FAILURE == status) {
michael@0 202 fprintf(stderr, "PR_JoinThread failed\n");
michael@0 203 exit(1);
michael@0 204 }
michael@0 205 }
michael@0 206 PR_Free(serverThreads);
michael@0 207 status = PR_Close(dummySock);
michael@0 208 if (PR_FAILURE == status) {
michael@0 209 fprintf(stderr, "PR_Close failed\n");
michael@0 210 exit(1);
michael@0 211 }
michael@0 212 status = PR_Close(listenSock);
michael@0 213 if (PR_FAILURE == status) {
michael@0 214 fprintf(stderr, "PR_Close failed\n");
michael@0 215 exit(1);
michael@0 216 }
michael@0 217
michael@0 218 printf("PASS\n");
michael@0 219 return 0;
michael@0 220 }

mercurial