nsprpub/pr/tests/intrupt.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * File: intrupt.c
michael@0 8 * Purpose: testing thread interrupts
michael@0 9 */
michael@0 10
michael@0 11 #include "plgetopt.h"
michael@0 12 #include "prcvar.h"
michael@0 13 #include "prerror.h"
michael@0 14 #include "prinit.h"
michael@0 15 #include "prinrval.h"
michael@0 16 #include "prio.h"
michael@0 17 #include "prlock.h"
michael@0 18 #include "prlog.h"
michael@0 19 #include "prthread.h"
michael@0 20 #include "prtypes.h"
michael@0 21 #include "prnetdb.h"
michael@0 22
michael@0 23 #include <stdio.h>
michael@0 24 #include <string.h>
michael@0 25
michael@0 26 #define DEFAULT_TCP_PORT 12500
michael@0 27
michael@0 28 static PRLock *ml = NULL;
michael@0 29 static PRCondVar *cv = NULL;
michael@0 30
michael@0 31 static PRBool passed = PR_TRUE;
michael@0 32 static PRBool debug_mode = PR_FALSE;
michael@0 33 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
michael@0 34
michael@0 35 static void PR_CALLBACK AbortCV(void *arg)
michael@0 36 {
michael@0 37 PRStatus rv;
michael@0 38 PRThread *me = PR_GetCurrentThread();
michael@0 39
michael@0 40 /* some other thread (main) is doing the interrupt */
michael@0 41 PR_Lock(ml);
michael@0 42 rv = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
michael@0 43 if (debug_mode) printf( "Expected interrupt on wait CV and ");
michael@0 44 if (PR_FAILURE == rv)
michael@0 45 {
michael@0 46 if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
michael@0 47 {
michael@0 48 if (debug_mode) printf("got it\n");
michael@0 49 }
michael@0 50 else
michael@0 51 {
michael@0 52 if (debug_mode) printf("got random error\n");
michael@0 53 passed = PR_FALSE;
michael@0 54 }
michael@0 55 }
michael@0 56 else
michael@0 57 {
michael@0 58 if (debug_mode) printf("got a successful completion\n");
michael@0 59 passed = PR_FALSE;
michael@0 60 }
michael@0 61
michael@0 62 rv = PR_WaitCondVar(cv, 10);
michael@0 63 if (debug_mode)
michael@0 64 {
michael@0 65 printf(
michael@0 66 "Expected success on wait CV and %s\n",
michael@0 67 (PR_SUCCESS == rv) ? "got it" : "failed");
michael@0 68 }
michael@0 69 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
michael@0 70
michael@0 71 /* interrupt myself, then clear */
michael@0 72 PR_Interrupt(me);
michael@0 73 PR_ClearInterrupt();
michael@0 74 rv = PR_WaitCondVar(cv, 10);
michael@0 75 if (debug_mode)
michael@0 76 {
michael@0 77 printf("Expected success on wait CV and ");
michael@0 78 if (PR_FAILURE == rv)
michael@0 79 {
michael@0 80 printf(
michael@0 81 "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
michael@0 82 "got interrupted" : "a random failure");
michael@0 83 }
michael@0 84 printf("got it\n");
michael@0 85 }
michael@0 86 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
michael@0 87
michael@0 88 /* set, then wait - interrupt - then wait again */
michael@0 89 PR_Interrupt(me);
michael@0 90 rv = PR_WaitCondVar(cv, 10);
michael@0 91 if (debug_mode) printf( "Expected interrupt on wait CV and ");
michael@0 92 if (PR_FAILURE == rv)
michael@0 93 {
michael@0 94 if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
michael@0 95 {
michael@0 96 if (debug_mode) printf("got it\n");
michael@0 97 }
michael@0 98 else
michael@0 99 {
michael@0 100 if (debug_mode) printf("failed\n");
michael@0 101 passed = PR_FALSE;
michael@0 102 }
michael@0 103 }
michael@0 104 else
michael@0 105 {
michael@0 106 if (debug_mode) printf("got a successful completion\n");
michael@0 107 passed = PR_FALSE;
michael@0 108 }
michael@0 109
michael@0 110 rv = PR_WaitCondVar(cv, 10);
michael@0 111 if (debug_mode)
michael@0 112 {
michael@0 113 printf(
michael@0 114 "Expected success on wait CV and %s\n",
michael@0 115 (PR_SUCCESS == rv) ? "got it" : "failed");
michael@0 116 }
michael@0 117 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
michael@0 118
michael@0 119 PR_Unlock(ml);
michael@0 120
michael@0 121 } /* AbortCV */
michael@0 122
michael@0 123 static void PR_CALLBACK AbortIO(void *arg)
michael@0 124 {
michael@0 125 PRStatus rv;
michael@0 126 PR_Sleep(PR_SecondsToInterval(2));
michael@0 127 rv = PR_Interrupt((PRThread*)arg);
michael@0 128 PR_ASSERT(PR_SUCCESS == rv);
michael@0 129 } /* AbortIO */
michael@0 130
michael@0 131 static void PR_CALLBACK AbortJoin(void *arg)
michael@0 132 {
michael@0 133 } /* AbortJoin */
michael@0 134
michael@0 135 static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr)
michael@0 136 {
michael@0 137 PRStatus rv;
michael@0 138 PRInt16 port = DEFAULT_TCP_PORT;
michael@0 139
michael@0 140 *listner = PR_NewTCPSocket();
michael@0 141 PR_ASSERT(*listner != NULL);
michael@0 142 memset(netaddr, 0, sizeof(*netaddr));
michael@0 143 (*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY);
michael@0 144 (*netaddr).inet.family = PR_AF_INET;
michael@0 145 do
michael@0 146 {
michael@0 147 (*netaddr).inet.port = PR_htons(port);
michael@0 148 rv = PR_Bind(*listner, netaddr);
michael@0 149 port += 1;
michael@0 150 PR_ASSERT(port < (DEFAULT_TCP_PORT + 10));
michael@0 151 } while (PR_FAILURE == rv);
michael@0 152
michael@0 153 rv = PR_Listen(*listner, 5);
michael@0 154
michael@0 155 if (PR_GetSockName(*listner, netaddr) < 0) {
michael@0 156 if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n");
michael@0 157 passed = PR_FALSE;
michael@0 158 return;
michael@0 159 }
michael@0 160
michael@0 161 }
michael@0 162
michael@0 163 static void PR_CALLBACK IntrBlock(void *arg)
michael@0 164 {
michael@0 165 PRStatus rv;
michael@0 166 PRNetAddr netaddr;
michael@0 167 PRFileDesc *listner;
michael@0 168
michael@0 169 /* some other thread (main) is doing the interrupt */
michael@0 170 /* block the interrupt */
michael@0 171 PR_BlockInterrupt();
michael@0 172 PR_Lock(ml);
michael@0 173 rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4));
michael@0 174 PR_Unlock(ml);
michael@0 175 if (debug_mode)
michael@0 176 {
michael@0 177 printf("Expected success on wait CV and ");
michael@0 178 if (PR_FAILURE == rv)
michael@0 179 {
michael@0 180 printf(
michael@0 181 "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
michael@0 182 "got interrupted" : "got a random failure");
michael@0 183 } else
michael@0 184 printf("got it\n");
michael@0 185 }
michael@0 186 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
michael@0 187
michael@0 188 setup_listen_socket(&listner, &netaddr);
michael@0 189 PR_UnblockInterrupt();
michael@0 190 if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
michael@0 191 {
michael@0 192 PRInt32 error = PR_GetError();
michael@0 193 if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
michael@0 194 if (PR_PENDING_INTERRUPT_ERROR == error)
michael@0 195 {
michael@0 196 if (debug_mode) printf("got it\n");
michael@0 197 }
michael@0 198 else
michael@0 199 {
michael@0 200 if (debug_mode) printf("failed\n");
michael@0 201 passed = PR_FALSE;
michael@0 202 }
michael@0 203 }
michael@0 204 else
michael@0 205 {
michael@0 206 if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
michael@0 207 passed = PR_FALSE;
michael@0 208 }
michael@0 209
michael@0 210 (void)PR_Close(listner); listner = NULL;
michael@0 211 } /* TestIntrBlock */
michael@0 212
michael@0 213 void PR_CALLBACK Intrupt(void *arg)
michael@0 214 {
michael@0 215 PRStatus rv;
michael@0 216 PRNetAddr netaddr;
michael@0 217 PRFileDesc *listner;
michael@0 218 PRThread *abortCV, *abortIO, *abortJoin, *intrBlock;
michael@0 219
michael@0 220 ml = PR_NewLock();
michael@0 221 cv = PR_NewCondVar(ml);
michael@0 222
michael@0 223 /* Part I */
michael@0 224 if (debug_mode) printf("Part I\n");
michael@0 225 abortCV = PR_CreateThread(
michael@0 226 PR_USER_THREAD, AbortCV, 0, PR_PRIORITY_NORMAL,
michael@0 227 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 228
michael@0 229 PR_Sleep(PR_SecondsToInterval(2));
michael@0 230 rv = PR_Interrupt(abortCV);
michael@0 231 PR_ASSERT(PR_SUCCESS == rv);
michael@0 232 rv = PR_JoinThread(abortCV);
michael@0 233 PR_ASSERT(PR_SUCCESS == rv);
michael@0 234
michael@0 235 /* Part II */
michael@0 236 if (debug_mode) printf("Part II\n");
michael@0 237 abortJoin = PR_CreateThread(
michael@0 238 PR_USER_THREAD, AbortJoin, 0, PR_PRIORITY_NORMAL,
michael@0 239 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 240 PR_Sleep(PR_SecondsToInterval(2));
michael@0 241 if (debug_mode) printf("Expecting to interrupt an exited thread ");
michael@0 242 rv = PR_Interrupt(abortJoin);
michael@0 243 PR_ASSERT(PR_SUCCESS == rv);
michael@0 244 rv = PR_JoinThread(abortJoin);
michael@0 245 PR_ASSERT(PR_SUCCESS == rv);
michael@0 246 if (debug_mode) printf("and succeeded\n");
michael@0 247
michael@0 248 /* Part III */
michael@0 249 if (debug_mode) printf("Part III\n");
michael@0 250 setup_listen_socket(&listner, &netaddr);
michael@0 251 abortIO = PR_CreateThread(
michael@0 252 PR_USER_THREAD, AbortIO, PR_GetCurrentThread(), PR_PRIORITY_NORMAL,
michael@0 253 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 254
michael@0 255 if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
michael@0 256 {
michael@0 257 PRInt32 error = PR_GetError();
michael@0 258 if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
michael@0 259 if (PR_PENDING_INTERRUPT_ERROR == error)
michael@0 260 {
michael@0 261 if (debug_mode) printf("got it\n");
michael@0 262 }
michael@0 263 else
michael@0 264 {
michael@0 265 if (debug_mode) printf("failed\n");
michael@0 266 passed = PR_FALSE;
michael@0 267 }
michael@0 268 }
michael@0 269 else
michael@0 270 {
michael@0 271 if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
michael@0 272 passed = PR_FALSE;
michael@0 273 }
michael@0 274
michael@0 275 (void)PR_Close(listner); listner = NULL;
michael@0 276
michael@0 277 rv = PR_JoinThread(abortIO);
michael@0 278 PR_ASSERT(PR_SUCCESS == rv);
michael@0 279 /* Part VI */
michael@0 280 if (debug_mode) printf("Part VI\n");
michael@0 281 intrBlock = PR_CreateThread(
michael@0 282 PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL,
michael@0 283 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 284
michael@0 285 PR_Sleep(PR_SecondsToInterval(2));
michael@0 286 rv = PR_Interrupt(intrBlock);
michael@0 287 PR_ASSERT(PR_SUCCESS == rv);
michael@0 288 rv = PR_JoinThread(intrBlock);
michael@0 289 PR_ASSERT(PR_SUCCESS == rv);
michael@0 290
michael@0 291 PR_DestroyCondVar(cv);
michael@0 292 PR_DestroyLock(ml);
michael@0 293 } /* Intrupt */
michael@0 294
michael@0 295 int main(int argc, char **argv)
michael@0 296 {
michael@0 297 PRThread *intrupt;
michael@0 298 PLOptStatus os;
michael@0 299 PLOptState *opt = PL_CreateOptState(argc, argv, "dG");
michael@0 300 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 301 {
michael@0 302 if (PL_OPT_BAD == os) continue;
michael@0 303 switch (opt->option)
michael@0 304 {
michael@0 305 case 'd': /* debug mode */
michael@0 306 debug_mode = PR_TRUE;
michael@0 307 break;
michael@0 308 case 'G': /* use global threads */
michael@0 309 thread_scope = PR_GLOBAL_THREAD;
michael@0 310 break;
michael@0 311 }
michael@0 312 }
michael@0 313 PL_DestroyOptState(opt);
michael@0 314 PR_STDIO_INIT();
michael@0 315 intrupt = PR_CreateThread(
michael@0 316 PR_USER_THREAD, Intrupt, NULL, PR_PRIORITY_NORMAL,
michael@0 317 thread_scope, PR_JOINABLE_THREAD, 0);
michael@0 318 if (intrupt == NULL) {
michael@0 319 fprintf(stderr, "cannot create thread\n");
michael@0 320 passed = PR_FALSE;
michael@0 321 } else {
michael@0 322 PRStatus rv;
michael@0 323 rv = PR_JoinThread(intrupt);
michael@0 324 PR_ASSERT(rv == PR_SUCCESS);
michael@0 325 }
michael@0 326 printf("%s\n", ((passed) ? "PASSED" : "FAILED"));
michael@0 327 return ((passed) ? 0 : 1);
michael@0 328 } /* main */
michael@0 329
michael@0 330 /* intrupt.c */

mercurial