tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */