Bug Summary

File:pr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests/../../../pr/tests/thrpool_server.c
Warning:line 345, column 18
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name thrpool_server.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nspr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nspr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests -resource-dir /usr/lib/llvm-18/lib/clang/18 -U NDEBUG -D DEBUG_jenkins -D PACKAGE_NAME="" -D PACKAGE_TARNAME="" -D PACKAGE_VERSION="" -D PACKAGE_STRING="" -D PACKAGE_BUGREPORT="" -D PACKAGE_URL="" -D DEBUG=1 -D HAVE_VISIBILITY_HIDDEN_ATTRIBUTE=1 -D HAVE_VISIBILITY_PRAGMA=1 -D XP_UNIX=1 -D _GNU_SOURCE=1 -D HAVE_FCNTL_FILE_LOCKING=1 -D HAVE_POINTER_LOCALTIME_R=1 -D LINUX=1 -D HAVE_DLADDR=1 -D HAVE_GETTID=1 -D HAVE_LCHOWN=1 -D HAVE_SETPRIORITY=1 -D HAVE_STRERROR=1 -D HAVE_SYSCALL=1 -D HAVE_SECURE_GETENV=1 -D _REENTRANT=1 -D FORCE_PR_LOG -D _PR_PTHREADS -U HAVE_CVAR_BUILT_ON_SEM -I /var/lib/jenkins/workspace/nss-scan-build/nss/../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../pr/include -I ../../../pr/include/private -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fno-inline -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c ../../../pr/tests/thrpool_server.c
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**
8** Name: thrpool.c
9**
10** Description: Test threadpool functionality.
11**
12** Modification History:
13*/
14#include "primpl.h"
15
16#include "plgetopt.h"
17
18#include <stdio.h>
19#include <string.h>
20#include <errno(*__errno_location ()).h>
21#ifdef XP_UNIX1
22#include <sys/mman.h>
23#endif
24#if defined(_PR_PTHREADS1)
25#include <pthread.h>
26#endif
27
28/* for getcwd */
29#if defined(XP_UNIX1) || defined (XP_OS2)
30#include <unistd.h>
31#elif defined(XP_PC)
32#include <direct.h>
33#endif
34
35#ifdef WIN32
36#include <process.h>
37#endif
38
39static int _debug_on = 0;
40static char *program_name = NULL((void*)0);
41static void serve_client_write(void *arg);
42
43#include "obsolete/prsem.h"
44
45#ifdef XP_PC
46#define mode_t int
47#endif
48
49#define DPRINTF(arg)if (_debug_on) printf arg if (_debug_on) printf arg
50
51
52#define BUF_DATA_SIZE(2 * 1024) (2 * 1024)
53#define TCP_MESG_SIZE1024 1024
54#define NUM_TCP_CLIENTS10 10 /* for a listen queue depth of 5 */
55
56
57#define NUM_TCP_CONNECTIONS_PER_CLIENT10 10
58#define NUM_TCP_MESGS_PER_CONNECTION10 10
59#define TCP_SERVER_PORT10000 10000
60#define SERVER_MAX_BIND_COUNT100 100
61
62#ifdef WINCE
63char *getcwd(char *buf, size_t size)
64{
65 wchar_t wpath[MAX_PATH];
66 _wgetcwd(wpath, MAX_PATH);
67 WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0);
68}
69
70#define perror(s)
71#endif
72
73static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS10;
74static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT10;
75static PRInt32 tcp_mesg_size = TCP_MESG_SIZE1024;
76static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION10;
77static void TCP_Server_Accept(void *arg);
78
79
80int failed_already=0;
81typedef struct buffer {
82 char data[BUF_DATA_SIZE(2 * 1024)];
83} buffer;
84
85
86typedef struct Server_Param {
87 PRJobIoDesc iod; /* socket to read from/write to */
88 PRInt32 datalen; /* bytes of data transfered in each read/write */
89 PRNetAddr netaddr;
90 PRMonitor *exit_mon; /* monitor to signal on exit */
91 PRInt32 *job_counterp; /* counter to decrement, before exit */
92 PRInt32 conn_counter; /* counter to decrement, before exit */
93 PRThreadPool *tp;
94} Server_Param;
95
96typedef struct Serve_Client_Param {
97 PRJobIoDesc iod; /* socket to read from/write to */
98 PRInt32 datalen; /* bytes of data transfered in each read/write */
99 PRMonitor *exit_mon; /* monitor to signal on exit */
100 PRInt32 *job_counterp; /* counter to decrement, before exit */
101 PRThreadPool *tp;
102} Serve_Client_Param;
103
104typedef struct Session {
105 PRJobIoDesc iod; /* socket to read from/write to */
106 buffer *in_buf;
107 PRInt32 bytes;
108 PRInt32 msg_num;
109 PRInt32 bytes_read;
110 PRMonitor *exit_mon; /* monitor to signal on exit */
111 PRInt32 *job_counterp; /* counter to decrement, before exit */
112 PRThreadPool *tp;
113} Session;
114
115static void
116serve_client_read(void *arg)
117{
118 Session *sp = (Session *) arg;
119 int rem;
120 int bytes;
121 int offset;
122 PRFileDesc *sockfd;
123 char *buf;
124 PRJob *jobp;
125
126 PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT0xffffffffUL;
127
128 sockfd = sp->iod.socket;
129 buf = sp->in_buf->data;
130
131 PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection)((sp->msg_num < num_tcp_mesgs_per_connection)?((void)0)
:PR_Assert("sp->msg_num < num_tcp_mesgs_per_connection"
,"../../../pr/tests/thrpool_server.c",131))
;
132 PR_ASSERT(sp->bytes_read < sp->bytes)((sp->bytes_read < sp->bytes)?((void)0):PR_Assert("sp->bytes_read < sp->bytes"
,"../../../pr/tests/thrpool_server.c",132))
;
133
134 offset = sp->bytes_read;
135 rem = sp->bytes - offset;
136 bytes = PR_Recv(sockfd, buf + offset, rem, 0, timeout);
137 if (bytes < 0) {
138 return;
139 }
140 sp->bytes_read += bytes;
141 sp->iod.timeout = PR_SecondsToInterval(60);
142 if (sp->bytes_read < sp->bytes) {
143 jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
144 PR_FALSE0);
145 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,145))
;
146 return;
147 }
148 PR_ASSERT(sp->bytes_read == sp->bytes)((sp->bytes_read == sp->bytes)?((void)0):PR_Assert("sp->bytes_read == sp->bytes"
,"../../../pr/tests/thrpool_server.c",148))
;
149 DPRINTF(("serve_client: read complete, msg(%d) \n", sp->msg_num))if (_debug_on) printf ("serve_client: read complete, msg(%d) \n"
, sp->msg_num)
;
150
151 sp->iod.timeout = PR_SecondsToInterval(60);
152 jobp = PR_QueueJob_Write(sp->tp, &sp->iod, serve_client_write, sp,
153 PR_FALSE0);
154 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,154))
;
155
156 return;
157}
158
159static void
160serve_client_write(void *arg)
161{
162 Session *sp = (Session *) arg;
163 int bytes;
164 PRFileDesc *sockfd;
165 char *buf;
166 PRJob *jobp;
167
168 sockfd = sp->iod.socket;
169 buf = sp->in_buf->data;
170
171 PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection)((sp->msg_num < num_tcp_mesgs_per_connection)?((void)0)
:PR_Assert("sp->msg_num < num_tcp_mesgs_per_connection"
,"../../../pr/tests/thrpool_server.c",171))
;
172
173 bytes = PR_Send(sockfd, buf, sp->bytes, 0, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
174 PR_ASSERT(bytes == sp->bytes)((bytes == sp->bytes)?((void)0):PR_Assert("bytes == sp->bytes"
,"../../../pr/tests/thrpool_server.c",174))
;
175
176 if (bytes < 0) {
177 return;
178 }
179 DPRINTF(("serve_client: write complete, msg(%d) \n", sp->msg_num))if (_debug_on) printf ("serve_client: write complete, msg(%d) \n"
, sp->msg_num)
;
180 sp->msg_num++;
181 if (sp->msg_num < num_tcp_mesgs_per_connection) {
182 sp->bytes_read = 0;
183 sp->iod.timeout = PR_SecondsToInterval(60);
184 jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
185 PR_FALSE0);
186 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,186))
;
187 return;
188 }
189
190 DPRINTF(("serve_client: read/write complete, msg(%d) \n", sp->msg_num))if (_debug_on) printf ("serve_client: read/write complete, msg(%d) \n"
, sp->msg_num)
;
191 if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
192 fprintf(stderrstderr,"%s: ERROR - PR_Shutdown\n", program_name);
193 }
194
195 PR_Close(sockfd);
196 PR_EnterMonitor(sp->exit_mon);
197 --(*sp->job_counterp);
198 PR_Notify(sp->exit_mon);
199 PR_ExitMonitor(sp->exit_mon);
200
201 PR_DELETE(sp->in_buf){ PR_Free(sp->in_buf); (sp->in_buf) = ((void*)0); };
202 PR_DELETE(sp){ PR_Free(sp); (sp) = ((void*)0); };
203
204 return;
205}
206
207/*
208 * Serve_Client
209 * Thread, started by the server, for serving a client connection.
210 * Reads data from socket and writes it back, unmodified, and
211 * closes the socket
212 */
213static void PR_CALLBACK
214Serve_Client(void *arg)
215{
216 Serve_Client_Param *scp = (Serve_Client_Param *) arg;
217 buffer *in_buf;
218 Session *sp;
219 PRJob *jobp;
220
221 sp = PR_NEW(Session)((Session *) (PR_Malloc((sizeof(Session)))));
222 sp->iod = scp->iod;
223
224 in_buf = PR_NEW(buffer)((buffer *) (PR_Malloc((sizeof(buffer)))));
225 if (in_buf == NULL((void*)0)) {
226 fprintf(stderrstderr,"%s: failed to alloc buffer struct\n",program_name);
227 failed_already=1;
228 return;
229 }
230
231 sp->in_buf = in_buf;
232 sp->bytes = scp->datalen;
233 sp->msg_num = 0;
234 sp->bytes_read = 0;
235 sp->tp = scp->tp;
236 sp->exit_mon = scp->exit_mon;
237 sp->job_counterp = scp->job_counterp;
238
239 sp->iod.timeout = PR_SecondsToInterval(60);
240 jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
241 PR_FALSE0);
242 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,242))
;
243 PR_DELETE(scp){ PR_Free(scp); (scp) = ((void*)0); };
244}
245
246static void
247print_stats(void *arg)
248{
249 Server_Param *sp = (Server_Param *) arg;
250 PRThreadPool *tp = sp->tp;
251 PRInt32 counter;
252 PRJob *jobp;
253
254 PR_EnterMonitor(sp->exit_mon);
255 counter = (*sp->job_counterp);
256 PR_ExitMonitor(sp->exit_mon);
257
258 printf("PRINT_STATS: #client connections = %d\n",counter);
259
260
261 jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500),
262 print_stats, sp, PR_FALSE0);
263
264 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,264))
;
265}
266
267static int job_counter = 0;
268/*
269 * TCP Server
270 * Server binds an address to a socket, starts a client process and
271 * listens for incoming connections.
272 * Each client connects to the server and sends a chunk of data
273 * Starts a Serve_Client job for each incoming connection, to read
274 * the data from the client and send it back to the client, unmodified.
275 * Each client checks that data received from server is same as the
276 * data it sent to the server.
277 * Finally, the threadpool is shutdown
278 */
279static void PR_CALLBACK
280TCP_Server(void *arg)
281{
282 PRThreadPool *tp = (PRThreadPool *) arg;
283 Server_Param *sp;
284 PRFileDesc *sockfd;
285 PRNetAddr netaddr;
286 PRMonitor *sc_mon;
1
'sc_mon' declared without an initial value
287 PRJob *jobp;
288 int i;
289 PRStatus rval;
290
291 /*
292 * Create a tcp socket
293 */
294 if ((sockfd = PR_NewTCPSocket()) == NULL((void*)0)) {
2
Assuming the condition is false
3
Taking false branch
295 fprintf(stderrstderr,"%s: PR_NewTCPSocket failed\n", program_name);
296 return;
297 }
298 memset(&netaddr, 0, sizeof(netaddr));
299 netaddr.inet.family = PR_AF_INET2;
300 netaddr.inet.port = PR_htons(TCP_SERVER_PORT10000);
301 netaddr.inet.ip = PR_htonl(PR_INADDR_ANY((in_addr_t) 0x00000000));
302 /*
303 * try a few times to bind server's address, if addresses are in
304 * use
305 */
306 i = 0;
307 while (PR_Bind(sockfd, &netaddr) < 0) {
4
Assuming the condition is false
5
Loop condition is false. Execution continues on line 320
308 if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR(-5982L)) {
309 netaddr.inet.port += 2;
310 if (i++ < SERVER_MAX_BIND_COUNT100) {
311 continue;
312 }
313 }
314 fprintf(stderrstderr,"%s: ERROR - PR_Bind failed\n", program_name);
315 perror("PR_Bind");
316 failed_already=1;
317 return;
318 }
319
320 if (PR_Listen(sockfd, 32) < 0) {
6
Assuming the condition is false
7
Taking false branch
321 fprintf(stderrstderr,"%s: ERROR - PR_Listen failed\n", program_name);
322 failed_already=1;
323 return;
324 }
325
326 if (PR_GetSockName(sockfd, &netaddr) < 0) {
8
Assuming the condition is false
9
Taking false branch
327 fprintf(stderrstderr,"%s: ERROR - PR_GetSockName failed\n", program_name);
328 failed_already=1;
329 return;
330 }
331
332 DPRINTF((if (_debug_on) printf ( "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n"
, netaddr.inet.ip, netaddr.inet.port)
10
Assuming '_debug_on' is 0
11
Taking false branch
333 "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",if (_debug_on) printf ( "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n"
, netaddr.inet.ip, netaddr.inet.port)
334 netaddr.inet.ip, netaddr.inet.port))if (_debug_on) printf ( "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n"
, netaddr.inet.ip, netaddr.inet.port)
;
335
336 sp = PR_NEW(Server_Param)((Server_Param *) (PR_Malloc((sizeof(Server_Param)))));
337 if (sp == NULL((void*)0)) {
12
Assuming 'sp' is not equal to NULL
13
Taking false branch
338 fprintf(stderrstderr,"%s: PR_NEW failed\n", program_name);
339 failed_already=1;
340 return;
341 }
342 sp->iod.socket = sockfd;
343 sp->iod.timeout = PR_SecondsToInterval(60);
344 sp->datalen = tcp_mesg_size;
345 sp->exit_mon = sc_mon;
14
Assigned value is garbage or undefined
346 sp->job_counterp = &job_counter;
347 sp->conn_counter = 0;
348 sp->tp = tp;
349 sp->netaddr = netaddr;
350
351 /* create and cancel an io job */
352 jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
353 PR_FALSE0);
354 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,354))
;
355 rval = PR_CancelJob(jobp);
356 PR_ASSERT(PR_SUCCESS == rval)((PR_SUCCESS == rval)?((void)0):PR_Assert("PR_SUCCESS == rval"
,"../../../pr/tests/thrpool_server.c",356))
;
357
358 /*
359 * create the client process
360 */
361 {
362#define MAX_ARGS4 4
363 char *argv[MAX_ARGS4 + 1];
364 int index = 0;
365 char port[32];
366 char path[1024 + sizeof("/thrpool_client")];
367
368 getcwd(path, sizeof(path));
369
370 (void)strcat(path, "/thrpool_client");
371#ifdef XP_PC
372 (void)strcat(path, ".exe");
373#endif
374 argv[index++] = path;
375 sprintf(port,"%d",PR_ntohs(netaddr.inet.port));
376 if (_debug_on)
377 {
378 argv[index++] = "-d";
379 argv[index++] = "-p";
380 argv[index++] = port;
381 argv[index++] = NULL((void*)0);
382 } else {
383 argv[index++] = "-p";
384 argv[index++] = port;
385 argv[index++] = NULL((void*)0);
386 }
387 PR_ASSERT(MAX_ARGS >= (index - 1))((4 >= (index - 1))?((void)0):PR_Assert("MAX_ARGS >= (index - 1)"
,"../../../pr/tests/thrpool_server.c",387))
;
388
389 DPRINTF(("creating client process %s ...\n", path))if (_debug_on) printf ("creating client process %s ...\n", path
)
;
390 if (PR_FAILURE == PR_CreateProcessDetached(path, argv, NULL((void*)0), NULL((void*)0))) {
391 fprintf(stderrstderr,
392 "thrpool_server: ERROR - PR_CreateProcessDetached failed\n");
393 failed_already=1;
394 return;
395 }
396 }
397
398 sc_mon = PR_NewMonitor();
399 if (sc_mon == NULL((void*)0)) {
400 fprintf(stderrstderr,"%s: PR_NewMonitor failed\n", program_name);
401 failed_already=1;
402 return;
403 }
404
405 sp->iod.socket = sockfd;
406 sp->iod.timeout = PR_SecondsToInterval(60);
407 sp->datalen = tcp_mesg_size;
408 sp->exit_mon = sc_mon;
409 sp->job_counterp = &job_counter;
410 sp->conn_counter = 0;
411 sp->tp = tp;
412 sp->netaddr = netaddr;
413
414 /* create and cancel a timer job */
415 jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(5000),
416 print_stats, sp, PR_FALSE0);
417 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,417))
;
418 rval = PR_CancelJob(jobp);
419 PR_ASSERT(PR_SUCCESS == rval)((PR_SUCCESS == rval)?((void)0):PR_Assert("PR_SUCCESS == rval"
,"../../../pr/tests/thrpool_server.c",419))
;
420
421 DPRINTF(("TCP_Server: Accepting connections \n"))if (_debug_on) printf ("TCP_Server: Accepting connections \n"
)
;
422
423 jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
424 PR_FALSE0);
425 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,425))
;
426 return;
427}
428
429static void
430TCP_Server_Accept(void *arg)
431{
432 Server_Param *sp = (Server_Param *) arg;
433 PRThreadPool *tp = sp->tp;
434 Serve_Client_Param *scp;
435 PRFileDesc *newsockfd;
436 PRJob *jobp;
437
438 if ((newsockfd = PR_Accept(sp->iod.socket, &sp->netaddr,
439 PR_INTERVAL_NO_TIMEOUT0xffffffffUL)) == NULL((void*)0)) {
440 fprintf(stderrstderr,"%s: ERROR - PR_Accept failed\n", program_name);
441 failed_already=1;
442 goto exit;
443 }
444 scp = PR_NEW(Serve_Client_Param)((Serve_Client_Param *) (PR_Malloc((sizeof(Serve_Client_Param
)))))
;
445 if (scp == NULL((void*)0)) {
446 fprintf(stderrstderr,"%s: PR_NEW failed\n", program_name);
447 failed_already=1;
448 goto exit;
449 }
450
451 /*
452 * Start a Serve_Client job for each incoming connection
453 */
454 scp->iod.socket = newsockfd;
455 scp->iod.timeout = PR_SecondsToInterval(60);
456 scp->datalen = tcp_mesg_size;
457 scp->exit_mon = sp->exit_mon;
458 scp->job_counterp = sp->job_counterp;
459 scp->tp = sp->tp;
460
461 PR_EnterMonitor(sp->exit_mon);
462 (*sp->job_counterp)++;
463 PR_ExitMonitor(sp->exit_mon);
464 jobp = PR_QueueJob(tp, Serve_Client, scp,
465 PR_FALSE0);
466
467 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,467))
;
468 DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", jobp))if (_debug_on) printf ("TCP_Server: Created Serve_Client = 0x%lx\n"
, jobp)
;
469
470 /*
471 * single-threaded update; no lock needed
472 */
473 sp->conn_counter++;
474 if (sp->conn_counter <
475 (num_tcp_clients * num_tcp_connections_per_client)) {
476 jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
477 PR_FALSE0);
478 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,478))
;
479 return;
480 }
481 jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500),
482 print_stats, sp, PR_FALSE0);
483
484 PR_ASSERT(NULL != jobp)((((void*)0) != jobp)?((void)0):PR_Assert("NULL != jobp","../../../pr/tests/thrpool_server.c"
,484))
;
485 DPRINTF(("TCP_Server: Created print_stats timer job = 0x%lx\n", jobp))if (_debug_on) printf ("TCP_Server: Created print_stats timer job = 0x%lx\n"
, jobp)
;
486
487exit:
488 PR_EnterMonitor(sp->exit_mon);
489 /* Wait for server jobs to finish */
490 while (0 != *sp->job_counterp) {
491 PR_Wait(sp->exit_mon, PR_INTERVAL_NO_TIMEOUT0xffffffffUL);
492 DPRINTF(("TCP_Server: conn_counter = %d\n",if (_debug_on) printf ("TCP_Server: conn_counter = %d\n", *sp
->job_counterp)
493 *sp->job_counterp))if (_debug_on) printf ("TCP_Server: conn_counter = %d\n", *sp
->job_counterp)
;
494 }
495
496 PR_ExitMonitor(sp->exit_mon);
497 if (sp->iod.socket) {
498 PR_Close(sp->iod.socket);
499 }
500 PR_DestroyMonitor(sp->exit_mon);
501 printf("%30s","TCP_Socket_Client_Server_Test:");
502 printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
503 num_tcp_clients, num_tcp_connections_per_client);
504 printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
505 num_tcp_mesgs_per_connection, tcp_mesg_size);
506
507 DPRINTF(("%s: calling PR_ShutdownThreadPool\n", program_name))if (_debug_on) printf ("%s: calling PR_ShutdownThreadPool\n",
program_name)
;
508 PR_ShutdownThreadPool(sp->tp);
509 PR_DELETE(sp){ PR_Free(sp); (sp) = ((void*)0); };
510}
511
512/************************************************************************/
513
514#define DEFAULT_INITIAL_THREADS4 4
515#define DEFAULT_MAX_THREADS100 100
516#define DEFAULT_STACKSIZE(512 * 1024) (512 * 1024)
517
518int main(int argc, char **argv)
519{
520 PRInt32 initial_threads = DEFAULT_INITIAL_THREADS4;
521 PRInt32 max_threads = DEFAULT_MAX_THREADS100;
522 PRInt32 stacksize = DEFAULT_STACKSIZE(512 * 1024);
523 PRThreadPool *tp = NULL((void*)0);
524 PRStatus rv;
525 PRJob *jobp;
526
527 /*
528 * -d debug mode
529 */
530 PLOptStatus os;
531 PLOptState *opt;
532
533 program_name = argv[0];
534 opt = PL_CreateOptState(argc, argv, "d");
535 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
536 {
537 if (PL_OPT_BAD == os) {
538 continue;
539 }
540 switch (opt->option)
541 {
542 case 'd': /* debug mode */
543 _debug_on = 1;
544 break;
545 default:
546 break;
547 }
548 }
549 PL_DestroyOptState(opt);
550
551 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
552 PR_STDIO_INIT();
553
554 PR_SetConcurrency(4);
555
556 tp = PR_CreateThreadPool(initial_threads, max_threads, stacksize);
557 if (NULL((void*)0) == tp) {
558 printf("PR_CreateThreadPool failed\n");
559 failed_already=1;
560 goto done;
561 }
562 jobp = PR_QueueJob(tp, TCP_Server, tp, PR_TRUE1);
563 rv = PR_JoinJob(jobp);
564 PR_ASSERT(PR_SUCCESS == rv)((PR_SUCCESS == rv)?((void)0):PR_Assert("PR_SUCCESS == rv","../../../pr/tests/thrpool_server.c"
,564))
;
565
566 DPRINTF(("%s: calling PR_JoinThreadPool\n", program_name))if (_debug_on) printf ("%s: calling PR_JoinThreadPool\n", program_name
)
;
567 rv = PR_JoinThreadPool(tp);
568 PR_ASSERT(PR_SUCCESS == rv)((PR_SUCCESS == rv)?((void)0):PR_Assert("PR_SUCCESS == rv","../../../pr/tests/thrpool_server.c"
,568))
;
569 DPRINTF(("%s: returning from PR_JoinThreadPool\n", program_name))if (_debug_on) printf ("%s: returning from PR_JoinThreadPool\n"
, program_name)
;
570
571done:
572 PR_Cleanup();
573 if (failed_already) {
574 return 1;
575 }
576 else {
577 return 0;
578 }
579}