nsprpub/pr/tests/intrupt.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial