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