123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- ** File: nameshm1.c -- Test Named Shared Memory
- **
- ** Description:
- ** nameshm1 tests Named Shared Memory. nameshm1 performs two tests of
- ** named shared memory.
- **
- ** The first test is a basic test. The basic test operates as a single
- ** process. The process exercises all the API elements of the facility.
- ** This test also attempts to write to all locations in the shared
- ** memory.
- **
- ** The second test is a client-server test. The client-server test
- ** creates a new instance of nameshm1, passing the -C argument to the
- ** new process; this creates the client-side process. The server-side
- ** (the instance of nameshm1 created from the command line) and the
- ** client-side interact via inter-process semaphores to verify that the
- ** shared memory segment can be read and written by both sides in a
- ** synchronized maner.
- **
- ** Note: Because this test runs in two processes, the log files created
- ** by the test are not in chronological sequence; makes it hard to read.
- ** As a temporary circumvention, I changed the definition(s) of the
- ** _PUT_LOG() macro in prlog.c to force a flushall(), or equivalent.
- ** This causes the log entries to be emitted in true chronological
- ** order.
- **
- ** Synopsis: nameshm1 [options] [name]
- **
- ** Options:
- ** -d Enables debug trace via PR_LOG()
- ** -v Enables verbose mode debug trace via PR_LOG()
- ** -w Causes the basic test to attempt to write to the segment
- ** mapped as read-only. When this option is specified, the
- ** test should crash with a seg-fault; this is a destructive
- ** test and is considered successful when it seg-faults.
- **
- ** -C Causes nameshm1 to start as the client-side of a
- ** client-server pair of processes. Only the instance
- ** of nameshm1 operating as the server-side process should
- ** specify the -C option when creating the client-side process;
- ** the -C option should not be specified at the command line.
- ** The client-side uses the shared memory segment created by
- ** the server-side to communicate with the server-side
- ** process.
- **
- ** -p <n> Specify the number of iterations the client-server tests
- ** should perform. Default: 1000.
- **
- ** -s <n> Size, in KBytes (1024), of the shared memory segment.
- ** Default: (10 * 1024)
- **
- ** -i <n> Number of client-side iterations. Default: 3
- **
- ** name specifies the name of the shared memory segment to be used.
- ** Default: /tmp/xxxNSPRshm
- **
- **
- ** See also: prshm.h
- **
- ** /lth. Aug-1999.
- */
- #include <plgetopt.h>
- #include <nspr.h>
- #include <stdlib.h>
- #include <string.h>
- #include <private/primpl.h>
- #ifdef DEBUG
- #define SEM_D "D"
- #else
- #define SEM_D
- #endif
- #ifdef IS_64
- #define SEM_64 "64"
- #else
- #define SEM_64
- #endif
- #define SEM_NAME1 "/tmp/nameshmSEM1" SEM_D SEM_64
- #define SEM_NAME2 "/tmp/nameshmSEM2" SEM_D SEM_64
- #define OPT_NAME "/tmp/xxxNSPRshm" SEM_D SEM_64
- #define EXE_NAME "nameshm1"
- #define SEM_MODE 0666
- #define SHM_MODE 0666
- #define NameSize (1024)
- PRIntn debug = 0;
- PRIntn failed_already = 0;
- PRLogModuleLevel msgLevel = PR_LOG_NONE;
- PRLogModuleInfo *lm;
- /* command line options */
- PRIntn optDebug = 0;
- PRIntn optVerbose = 0;
- PRUint32 optWriteRO = 0; /* test write to read-only memory. should crash */
- PRUint32 optClient = 0;
- PRUint32 optCreate = 1;
- PRUint32 optAttachRW = 1;
- PRUint32 optAttachRO = 1;
- PRUint32 optClose = 1;
- PRUint32 optDelete = 1;
- PRInt32 optPing = 1000;
- PRUint32 optSize = (10 * 1024 );
- PRInt32 optClientIterations = 3;
- char optName[NameSize] = OPT_NAME;
- char buf[1024] = "";
- static void BasicTest( void )
- {
- PRSharedMemory *shm;
- char *addr; /* address of shared memory segment */
- PRUint32 i;
- PRInt32 rc;
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Begin BasicTest" ));
- if ( PR_FAILURE == PR_DeleteSharedMemory( optName )) {
- PR_LOG( lm, msgLevel,
- ("nameshm1: Initial PR_DeleteSharedMemory() failed. No problem"));
- } else
- PR_LOG( lm, msgLevel,
- ("nameshm1: Initial PR_DeleteSharedMemory() success"));
- shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE );
- if ( NULL == shm )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Create: success: %p", shm ));
- addr = PR_AttachSharedMemory( shm, 0 );
- if ( NULL == addr )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Attach: success: %p", addr ));
- /* fill memory with i */
- for ( i = 0; i < optSize ; i++ )
- {
- *(addr + i) = i;
- }
- rc = PR_DetachSharedMemory( shm, addr );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Detach: success: " ));
- rc = PR_CloseSharedMemory( shm );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Close: success: " ));
- rc = PR_DeleteSharedMemory( optName );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Delete: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RW Delete: success: " ));
- PR_LOG( lm, msgLevel,
- ("nameshm1: BasicTest(): Passed"));
- return;
- } /* end BasicTest() */
- static void ReadOnlyTest( void )
- {
- PRSharedMemory *shm;
- char *roAddr; /* read-only address of shared memory segment */
- PRInt32 rc;
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Begin ReadOnlyTest" ));
- shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE);
- if ( NULL == shm )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Create: success: %p", shm ));
- roAddr = PR_AttachSharedMemory( shm, PR_SHM_READONLY );
- if ( NULL == roAddr )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Attach: success: %p", roAddr ));
- if ( optWriteRO )
- {
- *roAddr = 0x00; /* write to read-only memory */
- failed_already = 1;
- PR_LOG( lm, msgLevel, ("nameshm1: Wrote to read-only memory segment!"));
- return;
- }
- rc = PR_DetachSharedMemory( shm, roAddr );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Detach: success: " ));
- rc = PR_CloseSharedMemory( shm );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Close: success: " ));
- rc = PR_DeleteSharedMemory( optName );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Destroy: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: RO Destroy: success: " ));
- PR_LOG( lm, msgLevel,
- ("nameshm1: ReadOnlyTest(): Passed"));
- return;
- } /* end ReadOnlyTest() */
- static void DoClient( void )
- {
- PRStatus rc;
- PRSem *sem1, *sem2;
- PRSharedMemory *shm;
- PRUint32 *addr;
- PRInt32 i;
- PR_LOG( lm, msgLevel,
- ("nameshm1: DoClient(): Starting"));
- sem1 = PR_OpenSemaphore( SEM_NAME1, 0, 0, 0 );
- PR_ASSERT( sem1 );
- sem2 = PR_OpenSemaphore( SEM_NAME2, 0, 0, 0 );
- PR_ASSERT( sem1 );
- shm = PR_OpenSharedMemory( optName, optSize, 0, SHM_MODE );
- if ( NULL == shm )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Create: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Create: success: %p", shm ));
- addr = PR_AttachSharedMemory( shm, 0 );
- if ( NULL == addr )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Attach: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Attach: success: %p", addr ));
- PR_LOG( lm, msgLevel,
- ( "Client found: %s", addr));
- PR_Sleep(PR_SecondsToInterval(4));
- for ( i = 0 ; i < optPing ; i++ )
- {
- rc = PR_WaitSemaphore( sem2 );
- PR_ASSERT( PR_FAILURE != rc );
- (*addr)++;
- PR_ASSERT( (*addr % 2) == 0 );
- if ( optVerbose )
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Client ping: %d, i: %d", *addr, i));
- rc = PR_PostSemaphore( sem1 );
- PR_ASSERT( PR_FAILURE != rc );
- }
- rc = PR_CloseSemaphore( sem1 );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_CloseSemaphore( sem2 );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_DetachSharedMemory( shm, addr );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Detach: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Detach: success: " ));
- rc = PR_CloseSharedMemory( shm );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Close: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: DoClient(): Close: success: " ));
- return;
- } /* end DoClient() */
- static void ClientServerTest( void )
- {
- PRStatus rc;
- PRSem *sem1, *sem2;
- PRProcess *proc;
- PRInt32 exit_status;
- PRSharedMemory *shm;
- PRUint32 *addr;
- PRInt32 i;
- char *child_argv[8];
- char buf[24];
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Begin ClientServerTest" ));
- rc = PR_DeleteSharedMemory( optName );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Destroy: failed. No problem"));
- } else
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Destroy: success" ));
- shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE);
- if ( NULL == shm )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Create: success: %p", shm ));
- addr = PR_AttachSharedMemory( shm, 0 );
- if ( NULL == addr )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Attach: success: %p", addr ));
- sem1 = PR_OpenSemaphore( SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0 );
- PR_ASSERT( sem1 );
- sem2 = PR_OpenSemaphore( SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 1 );
- PR_ASSERT( sem1 );
- strcpy( (char*)addr, "FooBar" );
- child_argv[0] = EXE_NAME;
- child_argv[1] = "-C";
- child_argv[2] = "-p";
- sprintf( buf, "%d", optPing );
- child_argv[3] = buf;
- child_argv[4] = optName;
- child_argv[5] = NULL;
- proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
- PR_ASSERT( proc );
- PR_Sleep( PR_SecondsToInterval(4));
- *addr = 1;
- for ( i = 0 ; i < optPing ; i++ )
- {
- rc = PR_WaitSemaphore( sem1 );
- PR_ASSERT( PR_FAILURE != rc );
- (*addr)++;
- PR_ASSERT( (*addr % 2) == 1 );
- if ( optVerbose )
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server pong: %d, i: %d", *addr, i));
- rc = PR_PostSemaphore( sem2 );
- PR_ASSERT( PR_FAILURE != rc );
- }
- rc = PR_WaitProcess( proc, &exit_status );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_CloseSemaphore( sem1 );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_CloseSemaphore( sem2 );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_DeleteSemaphore( SEM_NAME1 );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_DeleteSemaphore( SEM_NAME2 );
- PR_ASSERT( PR_FAILURE != rc );
- rc = PR_DetachSharedMemory( shm, addr );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Detach: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Detach: success: " ));
- rc = PR_CloseSharedMemory( shm );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Close: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Close: success: " ));
- rc = PR_DeleteSharedMemory( optName );
- if ( PR_FAILURE == rc )
- {
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Destroy: Error: %ld. OSError: %ld",
- PR_GetError(), PR_GetOSError()));
- failed_already = 1;
- return;
- }
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Server: Destroy: success" ));
- return;
- } /* end ClientServerTest() */
- int main(int argc, char **argv)
- {
- {
- /*
- ** Get command line options
- */
- PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "Cdvw:s:p:i:");
- while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
- {
- if (PL_OPT_BAD == os) {
- continue;
- }
- switch (opt->option)
- {
- case 'v': /* debug mode */
- optVerbose = 1;
- /* no break! fall into debug option */
- case 'd': /* debug mode */
- debug = 1;
- msgLevel = PR_LOG_DEBUG;
- break;
- case 'w': /* try writing to memory mapped read-only */
- optWriteRO = 1;
- break;
- case 'C':
- optClient = 1;
- break;
- case 's':
- optSize = atol(opt->value) * 1024;
- break;
- case 'p':
- optPing = atol(opt->value);
- break;
- case 'i':
- optClientIterations = atol(opt->value);
- break;
- default:
- strcpy( optName, opt->value );
- break;
- }
- }
- PL_DestroyOptState(opt);
- }
- lm = PR_NewLogModule("Test"); /* Initialize logging */
- PR_LOG( lm, msgLevel,
- ( "nameshm1: Starting" ));
- if ( optClient )
- {
- DoClient();
- } else {
- BasicTest();
- if ( failed_already != 0 ) {
- goto Finished;
- }
- ReadOnlyTest();
- if ( failed_already != 0 ) {
- goto Finished;
- }
- ClientServerTest();
- }
- Finished:
- if ( debug ) {
- printf("%s\n", (failed_already)? "FAIL" : "PASS" );
- }
- return( (failed_already)? 1 : 0 );
- } /* main() */
- /* end instrumt.c */
|