Back to index

lightning-sunbird  0.9+nobinonly
multiacc.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * File: multiacc.c
00040  *
00041  * Description:
00042  * This test creates multiple threads that accept on the
00043  * same listening socket.
00044  */
00045 
00046 #include "nspr.h"
00047 
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <string.h>
00051 
00052 #define NUM_SERVER_THREADS 10
00053 
00054 static int num_server_threads = NUM_SERVER_THREADS;
00055 static PRThreadScope thread_scope = PR_GLOBAL_THREAD;
00056 static PRBool exit_flag = PR_FALSE;
00057 
00058 static void ServerThreadFunc(void *arg)
00059 {
00060     PRFileDesc *listenSock = (PRFileDesc *) arg;
00061     PRFileDesc *acceptSock;
00062     PRErrorCode err;
00063     PRStatus status;
00064 
00065     while (!exit_flag) {
00066         acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
00067         if (NULL == acceptSock) {
00068             err = PR_GetError();
00069             if (PR_PENDING_INTERRUPT_ERROR == err) {
00070                 printf("server thread is interrupted\n");
00071                 fflush(stdout);
00072                 continue;
00073             }
00074             fprintf(stderr, "PR_Accept failed: %d\n", err);
00075             exit(1);
00076         }
00077         status = PR_Close(acceptSock);
00078         if (PR_FAILURE == status) {
00079             fprintf(stderr, "PR_Close failed\n");
00080             exit(1);
00081         }
00082     }
00083 }
00084 
00085 int main(int argc, char **argv)
00086 {
00087     PRNetAddr serverAddr;
00088     PRFileDesc *dummySock;
00089     PRFileDesc *listenSock;
00090     PRFileDesc *clientSock;
00091     PRThread *dummyThread;
00092     PRThread **serverThreads;
00093     PRStatus status;
00094     PRUint16 port;
00095     int idx;
00096     PRInt32 nbytes;
00097     char buf[1024];
00098 
00099     serverThreads = (PRThread **)
00100             PR_Malloc(num_server_threads * sizeof(PRThread *));
00101     if (NULL == serverThreads) {
00102         fprintf(stderr, "PR_Malloc failed\n");
00103         exit(1);
00104     }
00105 
00106     /*
00107      * Create a dummy listening socket and have the first
00108      * (dummy) thread listen on it.  This is to ensure that
00109      * the first thread becomes the I/O continuation thread
00110      * in the pthreads implementation (see ptio.c) and remains
00111      * so throughout the test, so that we never have to
00112      * recycle the I/O continuation thread.
00113      */
00114     dummySock = PR_NewTCPSocket();
00115     if (NULL == dummySock) {
00116         fprintf(stderr, "PR_NewTCPSocket failed\n");
00117         exit(1);
00118     }
00119     memset(&serverAddr, 0, sizeof(serverAddr));
00120     status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
00121     if (PR_FAILURE == status) {
00122         fprintf(stderr, "PR_InitializeNetAddr failed\n");
00123         exit(1);
00124     }
00125     status = PR_Bind(dummySock, &serverAddr);
00126     if (PR_FAILURE == status) {
00127         fprintf(stderr, "PR_Bind failed\n");
00128         exit(1);
00129     }
00130     status = PR_Listen(dummySock, 5);
00131     if (PR_FAILURE == status) {
00132         fprintf(stderr, "PR_Listen failed\n");
00133         exit(1);
00134     }
00135 
00136     listenSock = PR_NewTCPSocket();
00137     if (NULL == listenSock) {
00138         fprintf(stderr, "PR_NewTCPSocket failed\n");
00139         exit(1);
00140     }
00141     memset(&serverAddr, 0, sizeof(serverAddr));
00142     status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
00143     if (PR_FAILURE == status) {
00144         fprintf(stderr, "PR_InitializeNetAddr failed\n");
00145         exit(1);
00146     }
00147     status = PR_Bind(listenSock, &serverAddr);
00148     if (PR_FAILURE == status) {
00149         fprintf(stderr, "PR_Bind failed\n");
00150         exit(1);
00151     }
00152     status = PR_GetSockName(listenSock, &serverAddr);
00153     if (PR_FAILURE == status) {
00154         fprintf(stderr, "PR_GetSockName failed\n");
00155         exit(1);
00156     }
00157     port = PR_ntohs(serverAddr.inet.port);
00158     status = PR_Listen(listenSock, 5);
00159     if (PR_FAILURE == status) {
00160         fprintf(stderr, "PR_Listen failed\n");
00161         exit(1);
00162     }
00163 
00164     printf("creating dummy thread\n");
00165     fflush(stdout);
00166     dummyThread = PR_CreateThread(PR_USER_THREAD,
00167             ServerThreadFunc, dummySock, PR_PRIORITY_NORMAL,
00168             thread_scope, PR_JOINABLE_THREAD, 0);
00169     if (NULL == dummyThread) {
00170         fprintf(stderr, "PR_CreateThread failed\n");
00171         exit(1);
00172     }
00173     printf("sleeping one second before creating server threads\n");
00174     fflush(stdout);
00175     PR_Sleep(PR_SecondsToInterval(1));
00176     for (idx = 0; idx < num_server_threads; idx++) {
00177         serverThreads[idx] = PR_CreateThread(PR_USER_THREAD,
00178                 ServerThreadFunc, listenSock, PR_PRIORITY_NORMAL,
00179                 thread_scope, PR_JOINABLE_THREAD, 0);
00180         if (NULL == serverThreads[idx]) {
00181             fprintf(stderr, "PR_CreateThread failed\n");
00182             exit(1);
00183         }
00184     }
00185 
00186     memset(&serverAddr, 0, sizeof(serverAddr));
00187     PR_InitializeNetAddr(PR_IpAddrLoopback, port, &serverAddr);
00188     clientSock = PR_NewTCPSocket();
00189     if (NULL == clientSock) {
00190         fprintf(stderr, "PR_NewTCPSocket failed\n");
00191         exit(1);
00192     }
00193     printf("sleeping one second before connecting\n");
00194     fflush(stdout);
00195     PR_Sleep(PR_SecondsToInterval(1));
00196     status = PR_Connect(clientSock, &serverAddr, PR_INTERVAL_NO_TIMEOUT);
00197     if (PR_FAILURE == status) {
00198         fprintf(stderr, "PR_Connect failed\n");
00199         exit(1);
00200     }
00201     nbytes = PR_Read(clientSock, buf, sizeof(buf));
00202     if (nbytes != 0) {
00203         fprintf(stderr, "expected 0 bytes but got %d bytes\n", nbytes);
00204         exit(1);
00205     }
00206     status = PR_Close(clientSock);
00207     if (PR_FAILURE == status) {
00208         fprintf(stderr, "PR_Close failed\n");
00209         exit(1);
00210     }
00211     printf("sleeping one second before shutting down server threads\n");
00212     fflush(stdout);
00213     PR_Sleep(PR_SecondsToInterval(1));
00214 
00215     exit_flag = PR_TRUE;
00216     status = PR_Interrupt(dummyThread);
00217     if (PR_FAILURE == status) {
00218         fprintf(stderr, "PR_Interrupt failed\n");
00219         exit(1);
00220     }
00221     status = PR_JoinThread(dummyThread);
00222     if (PR_FAILURE == status) {
00223         fprintf(stderr, "PR_JoinThread failed\n");
00224         exit(1);
00225     }
00226     for (idx = 0; idx < num_server_threads; idx++) {
00227         status = PR_Interrupt(serverThreads[idx]);
00228         if (PR_FAILURE == status) {
00229             fprintf(stderr, "PR_Interrupt failed\n");
00230             exit(1);
00231         }
00232         status = PR_JoinThread(serverThreads[idx]);
00233         if (PR_FAILURE == status) {
00234             fprintf(stderr, "PR_JoinThread failed\n");
00235             exit(1);
00236         }
00237     }
00238     PR_Free(serverThreads);
00239     status = PR_Close(dummySock);
00240     if (PR_FAILURE == status) {
00241         fprintf(stderr, "PR_Close failed\n");
00242         exit(1);
00243     }
00244     status = PR_Close(listenSock);
00245     if (PR_FAILURE == status) {
00246         fprintf(stderr, "PR_Close failed\n");
00247         exit(1);
00248     }
00249 
00250     printf("PASS\n");
00251     return 0;
00252 }