1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/primblok.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,116 @@ 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: primblok.c 1.11 + * Purpose: testing whether the primordial thread can block in a 1.12 + * native blocking function without affecting the correct 1.13 + * functioning of NSPR I/O functions (Bugzilla bug #30746) 1.14 + */ 1.15 + 1.16 +#if !defined(WINNT) 1.17 + 1.18 +#include <stdio.h> 1.19 + 1.20 +int main(int argc, char **argv) 1.21 +{ 1.22 + printf("This test is not relevant on this platform\n"); 1.23 + return 0; 1.24 +} 1.25 + 1.26 +#else /* WINNT */ 1.27 + 1.28 +#include "nspr.h" 1.29 + 1.30 +#include <windows.h> 1.31 +#include <stdio.h> 1.32 +#include <stdlib.h> 1.33 +#include <string.h> 1.34 + 1.35 +#define TEST_FILE_NAME "primblok.dat" 1.36 + 1.37 +/* use InterlockedExchange to update this variable */ 1.38 +static LONG iothread_done; 1.39 + 1.40 +static void PR_CALLBACK IOThread(void *arg) 1.41 +{ 1.42 + PRFileDesc *fd; 1.43 + char buf[32]; 1.44 + PRInt32 nbytes; 1.45 + 1.46 + /* Give the primordial thread one second to block */ 1.47 + Sleep(1000); 1.48 + 1.49 + /* 1.50 + * See if our PR_Write call will hang when the primordial 1.51 + * thread is blocking in a native blocking function. 1.52 + */ 1.53 + fd = PR_Open(TEST_FILE_NAME, PR_WRONLY|PR_CREATE_FILE, 0666); 1.54 + if (NULL == fd) { 1.55 + fprintf(stderr, "PR_Open failed\n"); 1.56 + exit(1); 1.57 + } 1.58 + memset(buf, 0xaf, sizeof(buf)); 1.59 + fprintf(stderr, "iothread: calling PR_Write\n"); 1.60 + nbytes = PR_Write(fd, buf, sizeof(buf)); 1.61 + fprintf(stderr, "iothread: PR_Write returned\n"); 1.62 + if (nbytes != sizeof(buf)) { 1.63 + fprintf(stderr, "PR_Write returned %d\n", nbytes); 1.64 + exit(1); 1.65 + } 1.66 + if (PR_Close(fd) == PR_FAILURE) { 1.67 + fprintf(stderr, "PR_Close failed\n"); 1.68 + exit(1); 1.69 + } 1.70 + if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { 1.71 + fprintf(stderr, "PR_Delete failed\n"); 1.72 + exit(1); 1.73 + } 1.74 + 1.75 + /* Tell the main thread that we are done */ 1.76 + InterlockedExchange(&iothread_done, 1); 1.77 +} 1.78 + 1.79 +int main(int argc, char **argv) 1.80 +{ 1.81 + PRThread *iothread; 1.82 + 1.83 + /* Must be a global thread */ 1.84 + iothread = PR_CreateThread( 1.85 + PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL, 1.86 + PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); 1.87 + if (iothread == NULL) { 1.88 + fprintf(stderr, "cannot create thread\n"); 1.89 + exit(1); 1.90 + } 1.91 + 1.92 + /* 1.93 + * Block in a native blocking function. 1.94 + * Give iothread 5 seconds to finish its task. 1.95 + */ 1.96 + Sleep(5000); 1.97 + 1.98 + /* 1.99 + * Is iothread done or is it hung? 1.100 + * 1.101 + * I'm actually only interested in reading the value 1.102 + * of iothread_done. I'm using InterlockedExchange as 1.103 + * a thread-safe way to read iothread_done. 1.104 + */ 1.105 + if (InterlockedExchange(&iothread_done, 1) == 0) { 1.106 + fprintf(stderr, "iothread is hung\n"); 1.107 + fprintf(stderr, "FAILED\n"); 1.108 + exit(1); 1.109 + } 1.110 + 1.111 + if (PR_JoinThread(iothread) == PR_FAILURE) { 1.112 + fprintf(stderr, "PR_JoinThread failed\n"); 1.113 + exit(1); 1.114 + } 1.115 + printf("PASSED\n"); 1.116 + return 0; 1.117 +} /* main */ 1.118 + 1.119 +#endif /* WINNT */