123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- * File: multiacc.c
- *
- * Description:
- * This test creates multiple threads that accept on the
- * same listening socket.
- */
- #include "nspr.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define NUM_SERVER_THREADS 10
- static int num_server_threads = NUM_SERVER_THREADS;
- static PRThreadScope thread_scope = PR_GLOBAL_THREAD;
- static PRBool exit_flag = PR_FALSE;
- static void ServerThreadFunc(void *arg)
- {
- PRFileDesc *listenSock = (PRFileDesc *) arg;
- PRFileDesc *acceptSock;
- PRErrorCode err;
- PRStatus status;
- while (!exit_flag) {
- acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
- if (NULL == acceptSock) {
- err = PR_GetError();
- if (PR_PENDING_INTERRUPT_ERROR == err) {
- printf("server thread is interrupted\n");
- fflush(stdout);
- continue;
- }
- fprintf(stderr, "PR_Accept failed: %d\n", err);
- exit(1);
- }
- status = PR_Close(acceptSock);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Close failed\n");
- exit(1);
- }
- }
- }
- int main(int argc, char **argv)
- {
- PRNetAddr serverAddr;
- PRFileDesc *dummySock;
- PRFileDesc *listenSock;
- PRFileDesc *clientSock;
- PRThread *dummyThread;
- PRThread **serverThreads;
- PRStatus status;
- PRUint16 port;
- int idx;
- PRInt32 nbytes;
- char buf[1024];
- serverThreads = (PRThread **)
- PR_Malloc(num_server_threads * sizeof(PRThread *));
- if (NULL == serverThreads) {
- fprintf(stderr, "PR_Malloc failed\n");
- exit(1);
- }
- /*
- * Create a dummy listening socket and have the first
- * (dummy) thread listen on it. This is to ensure that
- * the first thread becomes the I/O continuation thread
- * in the pthreads implementation (see ptio.c) and remains
- * so throughout the test, so that we never have to
- * recycle the I/O continuation thread.
- */
- dummySock = PR_NewTCPSocket();
- if (NULL == dummySock) {
- fprintf(stderr, "PR_NewTCPSocket failed\n");
- exit(1);
- }
- memset(&serverAddr, 0, sizeof(serverAddr));
- status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_InitializeNetAddr failed\n");
- exit(1);
- }
- status = PR_Bind(dummySock, &serverAddr);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Bind failed\n");
- exit(1);
- }
- status = PR_Listen(dummySock, 5);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Listen failed\n");
- exit(1);
- }
- listenSock = PR_NewTCPSocket();
- if (NULL == listenSock) {
- fprintf(stderr, "PR_NewTCPSocket failed\n");
- exit(1);
- }
- memset(&serverAddr, 0, sizeof(serverAddr));
- status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_InitializeNetAddr failed\n");
- exit(1);
- }
- status = PR_Bind(listenSock, &serverAddr);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Bind failed\n");
- exit(1);
- }
- status = PR_GetSockName(listenSock, &serverAddr);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_GetSockName failed\n");
- exit(1);
- }
- port = PR_ntohs(serverAddr.inet.port);
- status = PR_Listen(listenSock, 5);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Listen failed\n");
- exit(1);
- }
- printf("creating dummy thread\n");
- fflush(stdout);
- dummyThread = PR_CreateThread(PR_USER_THREAD,
- ServerThreadFunc, dummySock, PR_PRIORITY_NORMAL,
- thread_scope, PR_JOINABLE_THREAD, 0);
- if (NULL == dummyThread) {
- fprintf(stderr, "PR_CreateThread failed\n");
- exit(1);
- }
- printf("sleeping one second before creating server threads\n");
- fflush(stdout);
- PR_Sleep(PR_SecondsToInterval(1));
- for (idx = 0; idx < num_server_threads; idx++) {
- serverThreads[idx] = PR_CreateThread(PR_USER_THREAD,
- ServerThreadFunc, listenSock, PR_PRIORITY_NORMAL,
- thread_scope, PR_JOINABLE_THREAD, 0);
- if (NULL == serverThreads[idx]) {
- fprintf(stderr, "PR_CreateThread failed\n");
- exit(1);
- }
- }
- memset(&serverAddr, 0, sizeof(serverAddr));
- PR_InitializeNetAddr(PR_IpAddrLoopback, port, &serverAddr);
- clientSock = PR_NewTCPSocket();
- if (NULL == clientSock) {
- fprintf(stderr, "PR_NewTCPSocket failed\n");
- exit(1);
- }
- printf("sleeping one second before connecting\n");
- fflush(stdout);
- PR_Sleep(PR_SecondsToInterval(1));
- status = PR_Connect(clientSock, &serverAddr, PR_INTERVAL_NO_TIMEOUT);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Connect failed\n");
- exit(1);
- }
- nbytes = PR_Read(clientSock, buf, sizeof(buf));
- if (nbytes != 0) {
- fprintf(stderr, "expected 0 bytes but got %d bytes\n", nbytes);
- exit(1);
- }
- status = PR_Close(clientSock);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Close failed\n");
- exit(1);
- }
- printf("sleeping one second before shutting down server threads\n");
- fflush(stdout);
- PR_Sleep(PR_SecondsToInterval(1));
- exit_flag = PR_TRUE;
- status = PR_Interrupt(dummyThread);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Interrupt failed\n");
- exit(1);
- }
- status = PR_JoinThread(dummyThread);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_JoinThread failed\n");
- exit(1);
- }
- for (idx = 0; idx < num_server_threads; idx++) {
- status = PR_Interrupt(serverThreads[idx]);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Interrupt failed\n");
- exit(1);
- }
- status = PR_JoinThread(serverThreads[idx]);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_JoinThread failed\n");
- exit(1);
- }
- }
- PR_Free(serverThreads);
- status = PR_Close(dummySock);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Close failed\n");
- exit(1);
- }
- status = PR_Close(listenSock);
- if (PR_FAILURE == status) {
- fprintf(stderr, "PR_Close failed\n");
- exit(1);
- }
- printf("PASS\n");
- return 0;
- }
|