primblok.c (2940B)
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/. */ 5 6 /* 7 * File: primblok.c 8 * Purpose: testing whether the primordial thread can block in a 9 * native blocking function without affecting the correct 10 * functioning of NSPR I/O functions (Bugzilla bug #30746) 11 */ 12 13 #if !defined(WINNT) 14 15 # include <stdio.h> 16 17 int main(int argc, char** argv) { 18 printf("This test is not relevant on this platform\n"); 19 return 0; 20 } 21 22 #else /* WINNT */ 23 24 # include "nspr.h" 25 26 # include <windows.h> 27 # include <stdio.h> 28 # include <stdlib.h> 29 # include <string.h> 30 31 # define TEST_FILE_NAME "primblok.dat" 32 33 /* use InterlockedExchange to update this variable */ 34 static LONG iothread_done; 35 36 static void PR_CALLBACK IOThread(void* arg) { 37 PRFileDesc* fd; 38 char buf[32]; 39 PRInt32 nbytes; 40 41 /* Give the primordial thread one second to block */ 42 Sleep(1000); 43 44 /* 45 * See if our PR_Write call will hang when the primordial 46 * thread is blocking in a native blocking function. 47 */ 48 fd = PR_Open(TEST_FILE_NAME, PR_WRONLY | PR_CREATE_FILE, 0666); 49 if (NULL == fd) { 50 fprintf(stderr, "PR_Open failed\n"); 51 exit(1); 52 } 53 memset(buf, 0xaf, sizeof(buf)); 54 fprintf(stderr, "iothread: calling PR_Write\n"); 55 nbytes = PR_Write(fd, buf, sizeof(buf)); 56 fprintf(stderr, "iothread: PR_Write returned\n"); 57 if (nbytes != sizeof(buf)) { 58 fprintf(stderr, "PR_Write returned %d\n", nbytes); 59 exit(1); 60 } 61 if (PR_Close(fd) == PR_FAILURE) { 62 fprintf(stderr, "PR_Close failed\n"); 63 exit(1); 64 } 65 if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { 66 fprintf(stderr, "PR_Delete failed\n"); 67 exit(1); 68 } 69 70 /* Tell the main thread that we are done */ 71 InterlockedExchange(&iothread_done, 1); 72 } 73 74 int main(int argc, char** argv) { 75 PRThread* iothread; 76 77 /* Must be a global thread */ 78 iothread = PR_CreateThread(PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL, 79 PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); 80 if (iothread == NULL) { 81 fprintf(stderr, "cannot create thread\n"); 82 exit(1); 83 } 84 85 /* 86 * Block in a native blocking function. 87 * Give iothread 5 seconds to finish its task. 88 */ 89 Sleep(5000); 90 91 /* 92 * Is iothread done or is it hung? 93 * 94 * I'm actually only interested in reading the value 95 * of iothread_done. I'm using InterlockedExchange as 96 * a thread-safe way to read iothread_done. 97 */ 98 if (InterlockedExchange(&iothread_done, 1) == 0) { 99 fprintf(stderr, "iothread is hung\n"); 100 fprintf(stderr, "FAILED\n"); 101 exit(1); 102 } 103 104 if (PR_JoinThread(iothread) == PR_FAILURE) { 105 fprintf(stderr, "PR_JoinThread failed\n"); 106 exit(1); 107 } 108 printf("PASSED\n"); 109 return 0; 110 } /* main */ 111 112 #endif /* WINNT */