1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/intrupt.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,330 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * File: intrupt.c 1.11 + * Purpose: testing thread interrupts 1.12 + */ 1.13 + 1.14 +#include "plgetopt.h" 1.15 +#include "prcvar.h" 1.16 +#include "prerror.h" 1.17 +#include "prinit.h" 1.18 +#include "prinrval.h" 1.19 +#include "prio.h" 1.20 +#include "prlock.h" 1.21 +#include "prlog.h" 1.22 +#include "prthread.h" 1.23 +#include "prtypes.h" 1.24 +#include "prnetdb.h" 1.25 + 1.26 +#include <stdio.h> 1.27 +#include <string.h> 1.28 + 1.29 +#define DEFAULT_TCP_PORT 12500 1.30 + 1.31 +static PRLock *ml = NULL; 1.32 +static PRCondVar *cv = NULL; 1.33 + 1.34 +static PRBool passed = PR_TRUE; 1.35 +static PRBool debug_mode = PR_FALSE; 1.36 +static PRThreadScope thread_scope = PR_LOCAL_THREAD; 1.37 + 1.38 +static void PR_CALLBACK AbortCV(void *arg) 1.39 +{ 1.40 + PRStatus rv; 1.41 + PRThread *me = PR_GetCurrentThread(); 1.42 + 1.43 + /* some other thread (main) is doing the interrupt */ 1.44 + PR_Lock(ml); 1.45 + rv = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); 1.46 + if (debug_mode) printf( "Expected interrupt on wait CV and "); 1.47 + if (PR_FAILURE == rv) 1.48 + { 1.49 + if (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) 1.50 + { 1.51 + if (debug_mode) printf("got it\n"); 1.52 + } 1.53 + else 1.54 + { 1.55 + if (debug_mode) printf("got random error\n"); 1.56 + passed = PR_FALSE; 1.57 + } 1.58 + } 1.59 + else 1.60 + { 1.61 + if (debug_mode) printf("got a successful completion\n"); 1.62 + passed = PR_FALSE; 1.63 + } 1.64 + 1.65 + rv = PR_WaitCondVar(cv, 10); 1.66 + if (debug_mode) 1.67 + { 1.68 + printf( 1.69 + "Expected success on wait CV and %s\n", 1.70 + (PR_SUCCESS == rv) ? "got it" : "failed"); 1.71 + } 1.72 + passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; 1.73 + 1.74 + /* interrupt myself, then clear */ 1.75 + PR_Interrupt(me); 1.76 + PR_ClearInterrupt(); 1.77 + rv = PR_WaitCondVar(cv, 10); 1.78 + if (debug_mode) 1.79 + { 1.80 + printf("Expected success on wait CV and "); 1.81 + if (PR_FAILURE == rv) 1.82 + { 1.83 + printf( 1.84 + "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ? 1.85 + "got interrupted" : "a random failure"); 1.86 + } 1.87 + printf("got it\n"); 1.88 + } 1.89 + passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; 1.90 + 1.91 + /* set, then wait - interrupt - then wait again */ 1.92 + PR_Interrupt(me); 1.93 + rv = PR_WaitCondVar(cv, 10); 1.94 + if (debug_mode) printf( "Expected interrupt on wait CV and "); 1.95 + if (PR_FAILURE == rv) 1.96 + { 1.97 + if (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) 1.98 + { 1.99 + if (debug_mode) printf("got it\n"); 1.100 + } 1.101 + else 1.102 + { 1.103 + if (debug_mode) printf("failed\n"); 1.104 + passed = PR_FALSE; 1.105 + } 1.106 + } 1.107 + else 1.108 + { 1.109 + if (debug_mode) printf("got a successful completion\n"); 1.110 + passed = PR_FALSE; 1.111 + } 1.112 + 1.113 + rv = PR_WaitCondVar(cv, 10); 1.114 + if (debug_mode) 1.115 + { 1.116 + printf( 1.117 + "Expected success on wait CV and %s\n", 1.118 + (PR_SUCCESS == rv) ? "got it" : "failed"); 1.119 + } 1.120 + passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; 1.121 + 1.122 + PR_Unlock(ml); 1.123 + 1.124 +} /* AbortCV */ 1.125 + 1.126 +static void PR_CALLBACK AbortIO(void *arg) 1.127 +{ 1.128 + PRStatus rv; 1.129 + PR_Sleep(PR_SecondsToInterval(2)); 1.130 + rv = PR_Interrupt((PRThread*)arg); 1.131 + PR_ASSERT(PR_SUCCESS == rv); 1.132 +} /* AbortIO */ 1.133 + 1.134 +static void PR_CALLBACK AbortJoin(void *arg) 1.135 +{ 1.136 +} /* AbortJoin */ 1.137 + 1.138 +static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr) 1.139 +{ 1.140 + PRStatus rv; 1.141 + PRInt16 port = DEFAULT_TCP_PORT; 1.142 + 1.143 + *listner = PR_NewTCPSocket(); 1.144 + PR_ASSERT(*listner != NULL); 1.145 + memset(netaddr, 0, sizeof(*netaddr)); 1.146 + (*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY); 1.147 + (*netaddr).inet.family = PR_AF_INET; 1.148 + do 1.149 + { 1.150 + (*netaddr).inet.port = PR_htons(port); 1.151 + rv = PR_Bind(*listner, netaddr); 1.152 + port += 1; 1.153 + PR_ASSERT(port < (DEFAULT_TCP_PORT + 10)); 1.154 + } while (PR_FAILURE == rv); 1.155 + 1.156 + rv = PR_Listen(*listner, 5); 1.157 + 1.158 + if (PR_GetSockName(*listner, netaddr) < 0) { 1.159 + if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n"); 1.160 + passed = PR_FALSE; 1.161 + return; 1.162 + } 1.163 + 1.164 +} 1.165 + 1.166 +static void PR_CALLBACK IntrBlock(void *arg) 1.167 +{ 1.168 + PRStatus rv; 1.169 + PRNetAddr netaddr; 1.170 + PRFileDesc *listner; 1.171 + 1.172 + /* some other thread (main) is doing the interrupt */ 1.173 + /* block the interrupt */ 1.174 + PR_BlockInterrupt(); 1.175 + PR_Lock(ml); 1.176 + rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4)); 1.177 + PR_Unlock(ml); 1.178 + if (debug_mode) 1.179 + { 1.180 + printf("Expected success on wait CV and "); 1.181 + if (PR_FAILURE == rv) 1.182 + { 1.183 + printf( 1.184 + "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ? 1.185 + "got interrupted" : "got a random failure"); 1.186 + } else 1.187 + printf("got it\n"); 1.188 + } 1.189 + passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; 1.190 + 1.191 + setup_listen_socket(&listner, &netaddr); 1.192 + PR_UnblockInterrupt(); 1.193 + if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL) 1.194 + { 1.195 + PRInt32 error = PR_GetError(); 1.196 + if (debug_mode) printf("Expected interrupt on PR_Accept() and "); 1.197 + if (PR_PENDING_INTERRUPT_ERROR == error) 1.198 + { 1.199 + if (debug_mode) printf("got it\n"); 1.200 + } 1.201 + else 1.202 + { 1.203 + if (debug_mode) printf("failed\n"); 1.204 + passed = PR_FALSE; 1.205 + } 1.206 + } 1.207 + else 1.208 + { 1.209 + if (debug_mode) printf("Failed to interrupt PR_Accept()\n"); 1.210 + passed = PR_FALSE; 1.211 + } 1.212 + 1.213 + (void)PR_Close(listner); listner = NULL; 1.214 +} /* TestIntrBlock */ 1.215 + 1.216 +void PR_CALLBACK Intrupt(void *arg) 1.217 +{ 1.218 + PRStatus rv; 1.219 + PRNetAddr netaddr; 1.220 + PRFileDesc *listner; 1.221 + PRThread *abortCV, *abortIO, *abortJoin, *intrBlock; 1.222 + 1.223 + ml = PR_NewLock(); 1.224 + cv = PR_NewCondVar(ml); 1.225 + 1.226 + /* Part I */ 1.227 + if (debug_mode) printf("Part I\n"); 1.228 + abortCV = PR_CreateThread( 1.229 + PR_USER_THREAD, AbortCV, 0, PR_PRIORITY_NORMAL, 1.230 + thread_scope, PR_JOINABLE_THREAD, 0); 1.231 + 1.232 + PR_Sleep(PR_SecondsToInterval(2)); 1.233 + rv = PR_Interrupt(abortCV); 1.234 + PR_ASSERT(PR_SUCCESS == rv); 1.235 + rv = PR_JoinThread(abortCV); 1.236 + PR_ASSERT(PR_SUCCESS == rv); 1.237 + 1.238 + /* Part II */ 1.239 + if (debug_mode) printf("Part II\n"); 1.240 + abortJoin = PR_CreateThread( 1.241 + PR_USER_THREAD, AbortJoin, 0, PR_PRIORITY_NORMAL, 1.242 + thread_scope, PR_JOINABLE_THREAD, 0); 1.243 + PR_Sleep(PR_SecondsToInterval(2)); 1.244 + if (debug_mode) printf("Expecting to interrupt an exited thread "); 1.245 + rv = PR_Interrupt(abortJoin); 1.246 + PR_ASSERT(PR_SUCCESS == rv); 1.247 + rv = PR_JoinThread(abortJoin); 1.248 + PR_ASSERT(PR_SUCCESS == rv); 1.249 + if (debug_mode) printf("and succeeded\n"); 1.250 + 1.251 + /* Part III */ 1.252 + if (debug_mode) printf("Part III\n"); 1.253 + setup_listen_socket(&listner, &netaddr); 1.254 + abortIO = PR_CreateThread( 1.255 + PR_USER_THREAD, AbortIO, PR_GetCurrentThread(), PR_PRIORITY_NORMAL, 1.256 + thread_scope, PR_JOINABLE_THREAD, 0); 1.257 + 1.258 + if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL) 1.259 + { 1.260 + PRInt32 error = PR_GetError(); 1.261 + if (debug_mode) printf("Expected interrupt on PR_Accept() and "); 1.262 + if (PR_PENDING_INTERRUPT_ERROR == error) 1.263 + { 1.264 + if (debug_mode) printf("got it\n"); 1.265 + } 1.266 + else 1.267 + { 1.268 + if (debug_mode) printf("failed\n"); 1.269 + passed = PR_FALSE; 1.270 + } 1.271 + } 1.272 + else 1.273 + { 1.274 + if (debug_mode) printf("Failed to interrupt PR_Accept()\n"); 1.275 + passed = PR_FALSE; 1.276 + } 1.277 + 1.278 + (void)PR_Close(listner); listner = NULL; 1.279 + 1.280 + rv = PR_JoinThread(abortIO); 1.281 + PR_ASSERT(PR_SUCCESS == rv); 1.282 + /* Part VI */ 1.283 + if (debug_mode) printf("Part VI\n"); 1.284 + intrBlock = PR_CreateThread( 1.285 + PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL, 1.286 + thread_scope, PR_JOINABLE_THREAD, 0); 1.287 + 1.288 + PR_Sleep(PR_SecondsToInterval(2)); 1.289 + rv = PR_Interrupt(intrBlock); 1.290 + PR_ASSERT(PR_SUCCESS == rv); 1.291 + rv = PR_JoinThread(intrBlock); 1.292 + PR_ASSERT(PR_SUCCESS == rv); 1.293 + 1.294 + PR_DestroyCondVar(cv); 1.295 + PR_DestroyLock(ml); 1.296 +} /* Intrupt */ 1.297 + 1.298 +int main(int argc, char **argv) 1.299 +{ 1.300 + PRThread *intrupt; 1.301 + PLOptStatus os; 1.302 + PLOptState *opt = PL_CreateOptState(argc, argv, "dG"); 1.303 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.304 + { 1.305 + if (PL_OPT_BAD == os) continue; 1.306 + switch (opt->option) 1.307 + { 1.308 + case 'd': /* debug mode */ 1.309 + debug_mode = PR_TRUE; 1.310 + break; 1.311 + case 'G': /* use global threads */ 1.312 + thread_scope = PR_GLOBAL_THREAD; 1.313 + break; 1.314 + } 1.315 + } 1.316 + PL_DestroyOptState(opt); 1.317 + PR_STDIO_INIT(); 1.318 + intrupt = PR_CreateThread( 1.319 + PR_USER_THREAD, Intrupt, NULL, PR_PRIORITY_NORMAL, 1.320 + thread_scope, PR_JOINABLE_THREAD, 0); 1.321 + if (intrupt == NULL) { 1.322 + fprintf(stderr, "cannot create thread\n"); 1.323 + passed = PR_FALSE; 1.324 + } else { 1.325 + PRStatus rv; 1.326 + rv = PR_JoinThread(intrupt); 1.327 + PR_ASSERT(rv == PR_SUCCESS); 1.328 + } 1.329 + printf("%s\n", ((passed) ? "PASSED" : "FAILED")); 1.330 + return ((passed) ? 0 : 1); 1.331 +} /* main */ 1.332 + 1.333 +/* intrupt.c */