nsprpub/pr/tests/io_timeout.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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 ** Test socket IO timeouts
     8 **
     9 **
    10 **
    11 **
    12 ** Modification History:
    13 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
    14 **	         The debug mode will print all of the printfs associated with this test.
    15 **			 The regress mode will be the default mode. Since the regress tool limits
    16 **           the output to a one line status:PASS or FAIL,all of the printf statements
    17 **			 have been handled with an if (debug_mode) statement. 
    18 ***********************************************************************/
    19 /***********************************************************************
    20 ** Includes
    21 ***********************************************************************/
    22 /* Used to get the command line option */
    23 #include "plgetopt.h"
    25 #include <stdio.h>
    26 #include "nspr.h"
    28 #define NUM_THREADS 1
    29 #define BASE_PORT   8000
    30 #define DEFAULT_ACCEPT_TIMEOUT 2
    32 typedef struct threadInfo {
    33     PRInt16 id;
    34     PRInt16 accept_timeout;
    35     PRLock *dead_lock;
    36     PRCondVar *dead_cv;
    37     PRInt32   *alive;
    38 } threadInfo;
    40 PRIntn failed_already = 0;
    41 PRIntn debug_mode = 0;
    43 #define	LOCAL_SCOPE_STRING			"LOCAL scope"
    44 #define	GLOBAL_SCOPE_STRING			"GLOBAL scope"
    45 #define	GLOBAL_BOUND_SCOPE_STRING	"GLOBAL_BOUND scope"
    47 void 
    48 thread_main(void *_info)
    49 {
    50     threadInfo *info = (threadInfo *)_info;
    51     PRNetAddr listenAddr;
    52     PRNetAddr clientAddr;
    53     PRFileDesc *listenSock = NULL;
    54     PRFileDesc *clientSock;
    55     PRStatus rv;
    56 	PRThreadScope tscope;
    57 	char *scope_str;
    60 	if (debug_mode)
    61     	printf("thread %d is alive\n", info->id);
    62 	tscope = PR_GetThreadScope(PR_GetCurrentThread());
    64 	switch(tscope) {
    65 		case PR_LOCAL_THREAD:
    66 			scope_str = LOCAL_SCOPE_STRING;
    67 			break;
    68 		case PR_GLOBAL_THREAD:
    69 			scope_str = GLOBAL_SCOPE_STRING;
    70 			break;
    71 		case PR_GLOBAL_BOUND_THREAD:
    72 			scope_str = GLOBAL_BOUND_SCOPE_STRING;
    73 			break;
    74 		default:
    75 			PR_ASSERT(!"Invalid thread scope");
    76 			break;
    77 	}
    78 	printf("thread id %d, scope %s\n", info->id, scope_str);
    80     listenSock = PR_NewTCPSocket();
    81     if (!listenSock) {
    82 		if (debug_mode)
    83         	printf("unable to create listen socket\n");
    84 		failed_already=1;
    85         goto dead;
    86     }
    88     listenAddr.inet.family = PR_AF_INET;
    89     listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
    90     listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
    91     rv = PR_Bind(listenSock, &listenAddr);
    92     if (rv == PR_FAILURE) {
    93 		if (debug_mode)
    94         	printf("unable to bind\n");
    95 		failed_already=1;
    96         goto dead;
    97     }
    99     rv = PR_Listen(listenSock, 4);
   100     if (rv == PR_FAILURE) {
   101 		if (debug_mode)
   102         	printf("unable to listen\n");
   103 		failed_already=1;
   104         goto dead;
   105     }
   107 	if (debug_mode)
   108     	printf("thread %d going into accept for %d seconds\n", 
   109         	info->id, info->accept_timeout + info->id);
   111     clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id));
   113     if (clientSock == NULL) {
   114         if (PR_GetError() == PR_IO_TIMEOUT_ERROR) {
   115 			if (debug_mode) {	
   116             	printf("PR_Accept() timeout worked!\n"); 
   117 				printf("TEST PASSED! PR_Accept() returned error %d\n",
   118 							PR_IO_TIMEOUT_ERROR);
   119 			}
   120     	} else {
   121 			if (debug_mode)
   122             	printf("TEST FAILED! PR_Accept() returned error %d\n",
   123 														PR_GetError());
   124 			failed_already=1;
   125 		}
   126     } else {
   127 		if (debug_mode)
   128         	printf ("TEST FAILED! PR_Accept() succeeded?\n");
   129 		failed_already=1;
   130 		PR_Close(clientSock);
   131     }
   133 dead:
   134     if (listenSock) {
   135 		PR_Close(listenSock);
   136     }
   137     PR_Lock(info->dead_lock);
   138     (*info->alive)--;
   139     PR_NotifyCondVar(info->dead_cv);
   140     PR_Unlock(info->dead_lock);
   142 	if (debug_mode)
   143     	printf("thread %d is dead\n", info->id);
   145     PR_Free(info);
   146 }
   148 void
   149 thread_test(PRThreadScope scope, PRInt32 num_threads)
   150 {
   151     PRInt32 index;
   152     PRThread *thr;
   153     PRLock *dead_lock;
   154     PRCondVar *dead_cv;
   155     PRInt32 alive;
   157 	if (debug_mode)
   158     	printf("IO Timeout test started with %d threads\n", num_threads);
   160     dead_lock = PR_NewLock();
   161     dead_cv = PR_NewCondVar(dead_lock);
   162     alive = num_threads;
   164     for (index = 0; index < num_threads; index++) {
   165         threadInfo *info = (threadInfo *)PR_Malloc(sizeof(threadInfo));
   167         info->id = index;
   168         info->dead_lock = dead_lock;
   169         info->dead_cv = dead_cv;
   170         info->alive = &alive;
   171         info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
   173         thr = PR_CreateThread( PR_USER_THREAD,
   174                                thread_main,
   175                                (void *)info,
   176                                PR_PRIORITY_NORMAL,
   177                                scope,
   178                                PR_UNJOINABLE_THREAD,
   179                                0);
   181         if (!thr) {
   182         	printf("Failed to create thread, error = %d(%d)\n",
   183 											PR_GetError(), PR_GetOSError());
   184 			failed_already=1;
   186             PR_Lock(dead_lock);
   187             alive--;
   188             PR_Unlock(dead_lock);
   189         }
   190     }
   192     PR_Lock(dead_lock);
   193     while(alive) {
   194 		if (debug_mode)
   195         	printf("main loop awake; alive = %d\n", alive);
   196         PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
   197     }
   198     PR_Unlock(dead_lock);
   200     PR_DestroyCondVar(dead_cv);
   201     PR_DestroyLock(dead_lock);
   202 }
   204 int main(int argc, char **argv)
   205 {
   206     PRInt32 num_threads = 0;
   208 	/* The command line argument: -d is used to determine if the test is being run
   209 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
   210 	All of the printfs associated with this test has been handled with a if (debug_mode)
   211 	test.
   212 	Usage: test_name [-d] [-t <threads>]
   213 	*/
   214 	PLOptStatus os;
   215 	PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
   216 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   217     {
   218 		if (PL_OPT_BAD == os) continue;
   219         switch (opt->option)
   220         {
   221         case 'd':  /* debug mode */
   222 			debug_mode = 1;
   223             break;
   224         case 't':  /* threads to involve */
   225 			num_threads = atoi(opt->value);
   226             break;
   227          default:
   228             break;
   229         }
   230     }
   231 	PL_DestroyOptState(opt);
   233  /* main test */
   235     if (0 == num_threads)
   236         num_threads = NUM_THREADS;
   238     PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
   239     PR_STDIO_INIT();
   241     printf("test with global bound thread\n");
   242     thread_test(PR_GLOBAL_BOUND_THREAD, num_threads);
   244     printf("test with local thread\n");
   245     thread_test(PR_LOCAL_THREAD, num_threads);
   247     printf("test with global thread\n");
   248     thread_test(PR_GLOBAL_THREAD, num_threads);
   250     PR_Cleanup();
   252 	if (failed_already)
   253 		return 1;
   254 	else
   255     	return 0;
   256 }

mercurial