nameshm1.c (15202B)
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: nameshm1.c -- Test Named Shared Memory 8 ** 9 ** Description: 10 ** nameshm1 tests Named Shared Memory. nameshm1 performs two tests of 11 ** named shared memory. 12 ** 13 ** The first test is a basic test. The basic test operates as a single 14 ** process. The process exercises all the API elements of the facility. 15 ** This test also attempts to write to all locations in the shared 16 ** memory. 17 ** 18 ** The second test is a client-server test. The client-server test 19 ** creates a new instance of nameshm1, passing the -C argument to the 20 ** new process; this creates the client-side process. The server-side 21 ** (the instance of nameshm1 created from the command line) and the 22 ** client-side interact via inter-process semaphores to verify that the 23 ** shared memory segment can be read and written by both sides in a 24 ** synchronized maner. 25 ** 26 ** Note: Because this test runs in two processes, the log files created 27 ** by the test are not in chronological sequence; makes it hard to read. 28 ** As a temporary circumvention, I changed the definition(s) of the 29 ** _PUT_LOG() macro in prlog.c to force a flushall(), or equivalent. 30 ** This causes the log entries to be emitted in true chronological 31 ** order. 32 ** 33 ** Synopsis: nameshm1 [options] [name] 34 ** 35 ** Options: 36 ** -d Enables debug trace via PR_LOG() 37 ** -v Enables verbose mode debug trace via PR_LOG() 38 ** -w Causes the basic test to attempt to write to the segment 39 ** mapped as read-only. When this option is specified, the 40 ** test should crash with a seg-fault; this is a destructive 41 ** test and is considered successful when it seg-faults. 42 ** 43 ** -C Causes nameshm1 to start as the client-side of a 44 ** client-server pair of processes. Only the instance 45 ** of nameshm1 operating as the server-side process should 46 ** specify the -C option when creating the client-side process; 47 ** the -C option should not be specified at the command line. 48 ** The client-side uses the shared memory segment created by 49 ** the server-side to communicate with the server-side 50 ** process. 51 ** 52 ** -p <n> Specify the number of iterations the client-server tests 53 ** should perform. Default: 1000. 54 ** 55 ** -s <n> Size, in KBytes (1024), of the shared memory segment. 56 ** Default: (10 * 1024) 57 ** 58 ** -i <n> Number of client-side iterations. Default: 3 59 ** 60 ** name specifies the name of the shared memory segment to be used. 61 ** Default: /tmp/xxxNSPRshm 62 ** 63 ** 64 ** See also: prshm.h 65 ** 66 ** /lth. Aug-1999. 67 */ 68 69 #include <plgetopt.h> 70 #include <nspr.h> 71 #include <stdlib.h> 72 #include <string.h> 73 #include <private/primpl.h> 74 75 #ifdef DEBUG 76 # define SEM_D "D" 77 #else 78 # define SEM_D 79 #endif 80 #ifdef IS_64 81 # define SEM_64 "64" 82 #else 83 # define SEM_64 84 #endif 85 86 #define SEM_NAME1 "/tmp/nameshmSEM1" SEM_D SEM_64 87 #define SEM_NAME2 "/tmp/nameshmSEM2" SEM_D SEM_64 88 #define OPT_NAME "/tmp/xxxNSPRshm" SEM_D SEM_64 89 #define EXE_NAME "nameshm1" 90 #define SEM_MODE 0666 91 #define SHM_MODE 0666 92 93 #define NameSize (1024) 94 95 PRIntn debug = 0; 96 PRIntn failed_already = 0; 97 PRLogModuleLevel msgLevel = PR_LOG_NONE; 98 PRLogModuleInfo* lm; 99 100 /* command line options */ 101 PRIntn optDebug = 0; 102 PRIntn optVerbose = 0; 103 PRUint32 optWriteRO = 0; /* test write to read-only memory. should crash */ 104 PRUint32 optClient = 0; 105 PRUint32 optCreate = 1; 106 PRUint32 optAttachRW = 1; 107 PRUint32 optAttachRO = 1; 108 PRUint32 optClose = 1; 109 PRUint32 optDelete = 1; 110 PRInt32 optPing = 1000; 111 PRUint32 optSize = (10 * 1024); 112 PRInt32 optClientIterations = 3; 113 char optName[NameSize] = OPT_NAME; 114 115 char buf[1024] = ""; 116 117 static void BasicTest(void) { 118 PRSharedMemory* shm; 119 char* addr; /* address of shared memory segment */ 120 PRUint32 i; 121 PRInt32 rc; 122 123 PR_LOG(lm, msgLevel, ("nameshm1: Begin BasicTest")); 124 125 if (PR_FAILURE == PR_DeleteSharedMemory(optName)) { 126 PR_LOG(lm, msgLevel, 127 ("nameshm1: Initial PR_DeleteSharedMemory() failed. No problem")); 128 } else 129 PR_LOG(lm, msgLevel, ("nameshm1: Initial PR_DeleteSharedMemory() success")); 130 131 shm = PR_OpenSharedMemory(optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), 132 SHM_MODE); 133 if (NULL == shm) { 134 PR_LOG(lm, msgLevel, 135 ("nameshm1: RW Create: Error: %ld. OSError: %ld", PR_GetError(), 136 PR_GetOSError())); 137 failed_already = 1; 138 return; 139 } 140 PR_LOG(lm, msgLevel, ("nameshm1: RW Create: success: %p", shm)); 141 142 addr = PR_AttachSharedMemory(shm, 0); 143 if (NULL == addr) { 144 PR_LOG(lm, msgLevel, 145 ("nameshm1: RW Attach: Error: %ld. OSError: %ld", PR_GetError(), 146 PR_GetOSError())); 147 failed_already = 1; 148 return; 149 } 150 PR_LOG(lm, msgLevel, ("nameshm1: RW Attach: success: %p", addr)); 151 152 /* fill memory with i */ 153 for (i = 0; i < optSize; i++) { 154 *(addr + i) = i; 155 } 156 157 rc = PR_DetachSharedMemory(shm, addr); 158 if (PR_FAILURE == rc) { 159 PR_LOG(lm, msgLevel, 160 ("nameshm1: RW Detach: Error: %ld. OSError: %ld", PR_GetError(), 161 PR_GetOSError())); 162 failed_already = 1; 163 return; 164 } 165 PR_LOG(lm, msgLevel, ("nameshm1: RW Detach: success: ")); 166 167 rc = PR_CloseSharedMemory(shm); 168 if (PR_FAILURE == rc) { 169 PR_LOG(lm, msgLevel, 170 ("nameshm1: RW Close: Error: %ld. OSError: %ld", PR_GetError(), 171 PR_GetOSError())); 172 failed_already = 1; 173 return; 174 } 175 PR_LOG(lm, msgLevel, ("nameshm1: RW Close: success: ")); 176 177 rc = PR_DeleteSharedMemory(optName); 178 if (PR_FAILURE == rc) { 179 PR_LOG(lm, msgLevel, 180 ("nameshm1: RW Delete: Error: %ld. OSError: %ld", PR_GetError(), 181 PR_GetOSError())); 182 failed_already = 1; 183 return; 184 } 185 PR_LOG(lm, msgLevel, ("nameshm1: RW Delete: success: ")); 186 187 PR_LOG(lm, msgLevel, ("nameshm1: BasicTest(): Passed")); 188 189 return; 190 } /* end BasicTest() */ 191 192 static void ReadOnlyTest(void) { 193 PRSharedMemory* shm; 194 char* roAddr; /* read-only address of shared memory segment */ 195 PRInt32 rc; 196 197 PR_LOG(lm, msgLevel, ("nameshm1: Begin ReadOnlyTest")); 198 199 shm = PR_OpenSharedMemory(optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), 200 SHM_MODE); 201 if (NULL == shm) { 202 PR_LOG(lm, msgLevel, 203 ("nameshm1: RO Create: Error: %ld. OSError: %ld", PR_GetError(), 204 PR_GetOSError())); 205 failed_already = 1; 206 return; 207 } 208 PR_LOG(lm, msgLevel, ("nameshm1: RO Create: success: %p", shm)); 209 210 roAddr = PR_AttachSharedMemory(shm, PR_SHM_READONLY); 211 if (NULL == roAddr) { 212 PR_LOG(lm, msgLevel, 213 ("nameshm1: RO Attach: Error: %ld. OSError: %ld", PR_GetError(), 214 PR_GetOSError())); 215 failed_already = 1; 216 return; 217 } 218 PR_LOG(lm, msgLevel, ("nameshm1: RO Attach: success: %p", roAddr)); 219 220 if (optWriteRO) { 221 *roAddr = 0x00; /* write to read-only memory */ 222 failed_already = 1; 223 PR_LOG(lm, msgLevel, ("nameshm1: Wrote to read-only memory segment!")); 224 return; 225 } 226 227 rc = PR_DetachSharedMemory(shm, roAddr); 228 if (PR_FAILURE == rc) { 229 PR_LOG(lm, msgLevel, 230 ("nameshm1: RO Detach: Error: %ld. OSError: %ld", PR_GetError(), 231 PR_GetOSError())); 232 failed_already = 1; 233 return; 234 } 235 PR_LOG(lm, msgLevel, ("nameshm1: RO Detach: success: ")); 236 237 rc = PR_CloseSharedMemory(shm); 238 if (PR_FAILURE == rc) { 239 PR_LOG(lm, msgLevel, 240 ("nameshm1: RO Close: Error: %ld. OSError: %ld", PR_GetError(), 241 PR_GetOSError())); 242 failed_already = 1; 243 return; 244 } 245 PR_LOG(lm, msgLevel, ("nameshm1: RO Close: success: ")); 246 247 rc = PR_DeleteSharedMemory(optName); 248 if (PR_FAILURE == rc) { 249 PR_LOG(lm, msgLevel, 250 ("nameshm1: RO Destroy: Error: %ld. OSError: %ld", PR_GetError(), 251 PR_GetOSError())); 252 failed_already = 1; 253 return; 254 } 255 PR_LOG(lm, msgLevel, ("nameshm1: RO Destroy: success: ")); 256 257 PR_LOG(lm, msgLevel, ("nameshm1: ReadOnlyTest(): Passed")); 258 259 return; 260 } /* end ReadOnlyTest() */ 261 262 static void DoClient(void) { 263 PRStatus rc; 264 PRSem *sem1, *sem2; 265 PRSharedMemory* shm; 266 PRUint32* addr; 267 PRInt32 i; 268 269 PR_LOG(lm, msgLevel, ("nameshm1: DoClient(): Starting")); 270 271 sem1 = PR_OpenSemaphore(SEM_NAME1, 0, 0, 0); 272 PR_ASSERT(sem1); 273 274 sem2 = PR_OpenSemaphore(SEM_NAME2, 0, 0, 0); 275 PR_ASSERT(sem1); 276 277 shm = PR_OpenSharedMemory(optName, optSize, 0, SHM_MODE); 278 if (NULL == shm) { 279 PR_LOG(lm, msgLevel, 280 ("nameshm1: DoClient(): Create: Error: %ld. OSError: %ld", 281 PR_GetError(), PR_GetOSError())); 282 failed_already = 1; 283 return; 284 } 285 PR_LOG(lm, msgLevel, ("nameshm1: DoClient(): Create: success: %p", shm)); 286 287 addr = PR_AttachSharedMemory(shm, 0); 288 if (NULL == addr) { 289 PR_LOG(lm, msgLevel, 290 ("nameshm1: DoClient(): Attach: Error: %ld. OSError: %ld", 291 PR_GetError(), PR_GetOSError())); 292 failed_already = 1; 293 return; 294 } 295 PR_LOG(lm, msgLevel, ("nameshm1: DoClient(): Attach: success: %p", addr)); 296 297 PR_LOG(lm, msgLevel, ("Client found: %s", addr)); 298 299 PR_Sleep(PR_SecondsToInterval(4)); 300 for (i = 0; i < optPing; i++) { 301 rc = PR_WaitSemaphore(sem2); 302 PR_ASSERT(PR_FAILURE != rc); 303 304 (*addr)++; 305 PR_ASSERT((*addr % 2) == 0); 306 if (optVerbose) 307 PR_LOG(lm, msgLevel, ("nameshm1: Client ping: %d, i: %d", *addr, i)); 308 309 rc = PR_PostSemaphore(sem1); 310 PR_ASSERT(PR_FAILURE != rc); 311 } 312 313 rc = PR_CloseSemaphore(sem1); 314 PR_ASSERT(PR_FAILURE != rc); 315 316 rc = PR_CloseSemaphore(sem2); 317 PR_ASSERT(PR_FAILURE != rc); 318 319 rc = PR_DetachSharedMemory(shm, addr); 320 if (PR_FAILURE == rc) { 321 PR_LOG(lm, msgLevel, 322 ("nameshm1: DoClient(): Detach: Error: %ld. OSError: %ld", 323 PR_GetError(), PR_GetOSError())); 324 failed_already = 1; 325 return; 326 } 327 PR_LOG(lm, msgLevel, ("nameshm1: DoClient(): Detach: success: ")); 328 329 rc = PR_CloseSharedMemory(shm); 330 if (PR_FAILURE == rc) { 331 PR_LOG(lm, msgLevel, 332 ("nameshm1: DoClient(): Close: Error: %ld. OSError: %ld", 333 PR_GetError(), PR_GetOSError())); 334 failed_already = 1; 335 return; 336 } 337 PR_LOG(lm, msgLevel, ("nameshm1: DoClient(): Close: success: ")); 338 339 return; 340 } /* end DoClient() */ 341 342 static void ClientServerTest(void) { 343 PRStatus rc; 344 PRSem *sem1, *sem2; 345 PRProcess* proc; 346 PRInt32 exit_status; 347 PRSharedMemory* shm; 348 PRUint32* addr; 349 PRInt32 i; 350 char* child_argv[8]; 351 char buf[24]; 352 353 PR_LOG(lm, msgLevel, ("nameshm1: Begin ClientServerTest")); 354 355 rc = PR_DeleteSharedMemory(optName); 356 if (PR_FAILURE == rc) { 357 PR_LOG(lm, msgLevel, ("nameshm1: Server: Destroy: failed. No problem")); 358 } else 359 PR_LOG(lm, msgLevel, ("nameshm1: Server: Destroy: success")); 360 361 shm = PR_OpenSharedMemory(optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), 362 SHM_MODE); 363 if (NULL == shm) { 364 PR_LOG(lm, msgLevel, 365 ("nameshm1: Server: Create: Error: %ld. OSError: %ld", PR_GetError(), 366 PR_GetOSError())); 367 failed_already = 1; 368 return; 369 } 370 PR_LOG(lm, msgLevel, ("nameshm1: Server: Create: success: %p", shm)); 371 372 addr = PR_AttachSharedMemory(shm, 0); 373 if (NULL == addr) { 374 PR_LOG(lm, msgLevel, 375 ("nameshm1: Server: Attach: Error: %ld. OSError: %ld", PR_GetError(), 376 PR_GetOSError())); 377 failed_already = 1; 378 return; 379 } 380 PR_LOG(lm, msgLevel, ("nameshm1: Server: Attach: success: %p", addr)); 381 382 sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0); 383 PR_ASSERT(sem1); 384 385 sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 1); 386 PR_ASSERT(sem1); 387 388 strcpy((char*)addr, "FooBar"); 389 390 child_argv[0] = EXE_NAME; 391 child_argv[1] = "-C"; 392 child_argv[2] = "-p"; 393 sprintf(buf, "%d", optPing); 394 child_argv[3] = buf; 395 child_argv[4] = optName; 396 child_argv[5] = NULL; 397 398 proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); 399 PR_ASSERT(proc); 400 401 PR_Sleep(PR_SecondsToInterval(4)); 402 403 *addr = 1; 404 for (i = 0; i < optPing; i++) { 405 rc = PR_WaitSemaphore(sem1); 406 PR_ASSERT(PR_FAILURE != rc); 407 408 (*addr)++; 409 PR_ASSERT((*addr % 2) == 1); 410 if (optVerbose) 411 PR_LOG(lm, msgLevel, ("nameshm1: Server pong: %d, i: %d", *addr, i)); 412 413 rc = PR_PostSemaphore(sem2); 414 PR_ASSERT(PR_FAILURE != rc); 415 } 416 417 rc = PR_WaitProcess(proc, &exit_status); 418 PR_ASSERT(PR_FAILURE != rc); 419 420 rc = PR_CloseSemaphore(sem1); 421 PR_ASSERT(PR_FAILURE != rc); 422 423 rc = PR_CloseSemaphore(sem2); 424 PR_ASSERT(PR_FAILURE != rc); 425 426 rc = PR_DeleteSemaphore(SEM_NAME1); 427 PR_ASSERT(PR_FAILURE != rc); 428 429 rc = PR_DeleteSemaphore(SEM_NAME2); 430 PR_ASSERT(PR_FAILURE != rc); 431 432 rc = PR_DetachSharedMemory(shm, addr); 433 if (PR_FAILURE == rc) { 434 PR_LOG(lm, msgLevel, 435 ("nameshm1: Server: Detach: Error: %ld. OSError: %ld", PR_GetError(), 436 PR_GetOSError())); 437 failed_already = 1; 438 return; 439 } 440 PR_LOG(lm, msgLevel, ("nameshm1: Server: Detach: success: ")); 441 442 rc = PR_CloseSharedMemory(shm); 443 if (PR_FAILURE == rc) { 444 PR_LOG(lm, msgLevel, 445 ("nameshm1: Server: Close: Error: %ld. OSError: %ld", PR_GetError(), 446 PR_GetOSError())); 447 failed_already = 1; 448 return; 449 } 450 PR_LOG(lm, msgLevel, ("nameshm1: Server: Close: success: ")); 451 452 rc = PR_DeleteSharedMemory(optName); 453 if (PR_FAILURE == rc) { 454 PR_LOG(lm, msgLevel, 455 ("nameshm1: Server: Destroy: Error: %ld. OSError: %ld", 456 PR_GetError(), PR_GetOSError())); 457 failed_already = 1; 458 return; 459 } 460 PR_LOG(lm, msgLevel, ("nameshm1: Server: Destroy: success")); 461 462 return; 463 } /* end ClientServerTest() */ 464 465 int main(int argc, char** argv) { 466 { 467 /* 468 ** Get command line options 469 */ 470 PLOptStatus os; 471 PLOptState* opt = PL_CreateOptState(argc, argv, "Cdvw:s:p:i:"); 472 473 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 474 if (PL_OPT_BAD == os) { 475 continue; 476 } 477 switch (opt->option) { 478 case 'v': /* debug mode */ 479 optVerbose = 1; 480 /* no break! fall into debug option */ 481 case 'd': /* debug mode */ 482 debug = 1; 483 msgLevel = PR_LOG_DEBUG; 484 break; 485 case 'w': /* try writing to memory mapped read-only */ 486 optWriteRO = 1; 487 break; 488 case 'C': 489 optClient = 1; 490 break; 491 case 's': 492 optSize = atol(opt->value) * 1024; 493 break; 494 case 'p': 495 optPing = atol(opt->value); 496 break; 497 case 'i': 498 optClientIterations = atol(opt->value); 499 break; 500 default: 501 strcpy(optName, opt->value); 502 break; 503 } 504 } 505 PL_DestroyOptState(opt); 506 } 507 508 lm = PR_NewLogModule("Test"); /* Initialize logging */ 509 510 PR_LOG(lm, msgLevel, ("nameshm1: Starting")); 511 512 if (optClient) { 513 DoClient(); 514 } else { 515 BasicTest(); 516 if (failed_already != 0) { 517 goto Finished; 518 } 519 ReadOnlyTest(); 520 if (failed_already != 0) { 521 goto Finished; 522 } 523 ClientServerTest(); 524 } 525 526 Finished: 527 if (debug) { 528 printf("%s\n", (failed_already) ? "FAIL" : "PASS"); 529 } 530 return ((failed_already) ? 1 : 0); 531 } /* main() */ 532 /* end instrumt.c */