io_timeoutu.c (5471B)
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/. */ 5 6 /* 7 ** name io_timeoutu.c 8 ** Description: Test socket IO timeouts (user level) 9 ** 10 ** Modification History: 11 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 12 ** The debug mode will print all of the printfs associated with this 13 *test. 14 ** The regress mode will be the default mode. Since the regress tool 15 *limits 16 ** the output to a one line status:PASS or FAIL,all of the printf 17 *statements 18 ** have been handled with an if (debug_mode) statement. 19 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been 20 *updated to 21 ** recognize the return code from tha main program. 22 ***********************************************************************/ 23 /*********************************************************************** 24 ** Includes 25 ***********************************************************************/ 26 /* Used to get the command line option */ 27 #include "plgetopt.h" 28 29 #include <stdio.h> 30 #include "nspr.h" 31 32 #define NUM_THREADS 1 33 #define BASE_PORT 8000 34 #define DEFAULT_ACCEPT_TIMEOUT 2 35 36 typedef struct threadInfo { 37 PRInt16 id; 38 PRInt16 accept_timeout; 39 PRLock* dead_lock; 40 PRCondVar* dead_cv; 41 PRInt32* alive; 42 } threadInfo; 43 PRIntn failed_already = 0; 44 PRIntn debug_mode; 45 46 void thread_main(void* _info) { 47 threadInfo* info = (threadInfo*)_info; 48 PRNetAddr listenAddr; 49 PRNetAddr clientAddr; 50 PRFileDesc* listenSock = NULL; 51 PRFileDesc* clientSock; 52 PRStatus rv; 53 54 if (debug_mode) { 55 printf("thread %d is alive\n", info->id); 56 } 57 58 listenSock = PR_NewTCPSocket(); 59 if (!listenSock) { 60 if (debug_mode) { 61 printf("unable to create listen socket\n"); 62 } 63 goto dead; 64 } 65 66 listenAddr.inet.family = AF_INET; 67 listenAddr.inet.port = PR_htons(BASE_PORT + info->id); 68 listenAddr.inet.ip = PR_htonl(INADDR_ANY); 69 rv = PR_Bind(listenSock, &listenAddr); 70 if (rv == PR_FAILURE) { 71 if (debug_mode) { 72 printf("unable to bind\n"); 73 } 74 goto dead; 75 } 76 77 rv = PR_Listen(listenSock, 4); 78 if (rv == PR_FAILURE) { 79 if (debug_mode) { 80 printf("unable to listen\n"); 81 } 82 goto dead; 83 } 84 85 if (debug_mode) 86 printf("thread %d going into accept for %d seconds\n", info->id, 87 info->accept_timeout + info->id); 88 89 clientSock = PR_Accept(listenSock, &clientAddr, 90 PR_SecondsToInterval(info->accept_timeout + info->id)); 91 92 if (clientSock == NULL) { 93 if (PR_GetError() == PR_IO_TIMEOUT_ERROR) 94 if (debug_mode) { 95 printf("PR_Accept() timeout worked!\n"); 96 printf("TEST FAILED! PR_Accept() returned error %d\n", 97 } 98 PR_GetError()); 99 else { 100 failed_already = 1; 101 } 102 } else { 103 if (debug_mode) { 104 printf("TEST FAILED! PR_Accept() succeeded?\n"); 105 } else { 106 failed_already = 1; 107 } 108 PR_Close(clientSock); 109 } 110 111 dead: 112 if (listenSock) { 113 PR_Close(listenSock); 114 } 115 PR_Lock(info->dead_lock); 116 (*info->alive)--; 117 PR_NotifyCondVar(info->dead_cv); 118 PR_Unlock(info->dead_lock); 119 120 if (debug_mode) { 121 printf("thread %d is dead\n", info->id); 122 } 123 } 124 125 void thread_test(PRInt32 scope, PRInt32 num_threads) { 126 PRInt32 index; 127 PRThread* thr; 128 PRLock* dead_lock; 129 PRCondVar* dead_cv; 130 PRInt32 alive; 131 132 if (debug_mode) { 133 printf("IO Timeout test started with %d threads\n", num_threads); 134 } 135 136 dead_lock = PR_NewLock(); 137 dead_cv = PR_NewCondVar(dead_lock); 138 alive = num_threads; 139 140 for (index = 0; index < num_threads; index++) { 141 threadInfo* info = (threadInfo*)malloc(sizeof(threadInfo)); 142 143 info->id = index; 144 info->dead_lock = dead_lock; 145 info->dead_cv = dead_cv; 146 info->alive = &alive; 147 info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT; 148 149 thr = PR_CreateThread(PR_USER_THREAD, thread_main, (void*)info, 150 PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0); 151 152 if (!thr) { 153 PR_Lock(dead_lock); 154 alive--; 155 PR_Unlock(dead_lock); 156 } 157 } 158 159 PR_Lock(dead_lock); 160 while (alive) { 161 if (debug_mode) { 162 printf("main loop awake; alive = %d\n", alive); 163 } 164 PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT); 165 } 166 PR_Unlock(dead_lock); 167 } 168 169 int main(int argc, char** argv) { 170 PRInt32 num_threads; 171 172 /* The command line argument: -d is used to determine if the test is being run 173 in debug mode. The regress tool requires only one line output:PASS or FAIL. 174 All of the printfs associated with this test has been handled with a if 175 (debug_mode) test. Usage: test_name -d 176 */ 177 PLOptStatus os; 178 PLOptState* opt = PL_CreateOptState(argc, argv, "d:"); 179 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 180 if (PL_OPT_BAD == os) { 181 continue; 182 } 183 switch (opt->option) { 184 case 'd': /* debug mode */ 185 debug_mode = 1; 186 break; 187 default: 188 break; 189 } 190 } 191 PL_DestroyOptState(opt); 192 193 /* main test */ 194 195 if (argc > 2) { 196 num_threads = atoi(argv[2]); 197 } else { 198 num_threads = NUM_THREADS; 199 } 200 201 PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0); 202 203 if (debug_mode) { 204 printf("user level test\n"); 205 } 206 thread_test(PR_LOCAL_THREAD, num_threads); 207 208 PR_Cleanup(); 209 if (failed_already) { 210 return 1; 211 } else { 212 return 0; 213 } 214 }