nsprpub/pr/tests/intrupt.c

changeset 0
6474c204b198
     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 */

mercurial