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