nameshm1.c 17 KB

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