prpollml.c (3956B)
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 * This test exercises the code that allocates and frees the syspoll_list 8 * array of PRThread in the pthreads version. This test is intended to be 9 * run under Purify to verify that there is no memory leak. 10 */ 11 12 #include "nspr.h" 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #define POLL_DESC_COUNT \ 19 256 /* This should be greater than the \ 20 * STACK_POLL_DESC_COUNT macro in \ 21 * ptio.c to cause syspoll_list to \ 22 * be created. */ 23 24 static PRPollDesc pd[POLL_DESC_COUNT]; 25 26 static void Test(void) { 27 int i; 28 PRInt32 rv; 29 PRIntervalTime timeout; 30 31 timeout = PR_MillisecondsToInterval(10); 32 /* cause syspoll_list to grow */ 33 for (i = 1; i <= POLL_DESC_COUNT; i++) { 34 rv = PR_Poll(pd, i, timeout); 35 if (rv != 0) { 36 fprintf(stderr, "PR_Poll should time out but returns %d (%d, %d)\n", 37 (int)rv, (int)PR_GetError(), (int)PR_GetOSError()); 38 exit(1); 39 } 40 } 41 /* syspoll_list should be large enough for all these */ 42 for (i = POLL_DESC_COUNT; i >= 1; i--) { 43 rv = PR_Poll(pd, i, timeout); 44 if (rv != 0) { 45 fprintf(stderr, "PR_Poll should time out but returns %d\n", (int)rv); 46 exit(1); 47 } 48 } 49 } 50 51 static void ThreadFunc(void* arg) { Test(); } 52 53 int main(int argc, char** argv) { 54 int i; 55 PRThread* thread; 56 PRFileDesc* sock; 57 PRNetAddr addr; 58 59 memset(&addr, 0, sizeof(addr)); 60 addr.inet.family = PR_AF_INET; 61 addr.inet.port = PR_htons(0); 62 addr.inet.ip = PR_htonl(PR_INADDR_ANY); 63 for (i = 0; i < POLL_DESC_COUNT; i++) { 64 sock = PR_NewTCPSocket(); 65 if (sock == NULL) { 66 fprintf(stderr, "PR_NewTCPSocket failed (%d, %d)\n", (int)PR_GetError(), 67 (int)PR_GetOSError()); 68 fprintf(stderr, 69 "Ensure the per process file descriptor limit " 70 "is greater than %d.", 71 POLL_DESC_COUNT); 72 exit(1); 73 } 74 if (PR_Bind(sock, &addr) == PR_FAILURE) { 75 fprintf(stderr, "PR_Bind failed (%d, %d)\n", (int)PR_GetError(), 76 (int)PR_GetOSError()); 77 exit(1); 78 } 79 if (PR_Listen(sock, 5) == PR_FAILURE) { 80 fprintf(stderr, "PR_Listen failed (%d, %d)\n", (int)PR_GetError(), 81 (int)PR_GetOSError()); 82 exit(1); 83 } 84 85 pd[i].fd = sock; 86 pd[i].in_flags = PR_POLL_READ; 87 } 88 89 /* first run the test on the primordial thread */ 90 Test(); 91 92 /* then run the test on all three kinds of threads */ 93 thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, 94 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 95 if (NULL == thread) { 96 fprintf(stderr, "PR_CreateThread failed\n"); 97 exit(1); 98 } 99 if (PR_JoinThread(thread) == PR_FAILURE) { 100 fprintf(stderr, "PR_JoinThread failed\n"); 101 exit(1); 102 } 103 thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, 104 PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); 105 if (NULL == thread) { 106 fprintf(stderr, "PR_CreateThread failed\n"); 107 exit(1); 108 } 109 if (PR_JoinThread(thread) == PR_FAILURE) { 110 fprintf(stderr, "PR_JoinThread failed\n"); 111 exit(1); 112 } 113 thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, 114 PR_GLOBAL_BOUND_THREAD, PR_JOINABLE_THREAD, 0); 115 if (NULL == thread) { 116 fprintf(stderr, "PR_CreateThread failed\n"); 117 exit(1); 118 } 119 if (PR_JoinThread(thread) == PR_FAILURE) { 120 fprintf(stderr, "PR_JoinThread failed\n"); 121 exit(1); 122 } 123 for (i = 0; i < POLL_DESC_COUNT; i++) { 124 if (PR_Close(pd[i].fd) == PR_FAILURE) { 125 fprintf(stderr, "PR_Close failed\n"); 126 exit(1); 127 } 128 } 129 PR_Cleanup(); 130 printf("PASS\n"); 131 return 0; 132 }