anonfm.c (7199B)
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: anonfm.c 8 ** Description: Test anonymous file map 9 ** 10 ** Synopsis: anonfm [options] [dirName] 11 ** 12 ** Options: 13 ** -d enable debug mode 14 ** -h display a help message 15 ** -s <n> size of the anonymous memory map, in KBytes. default: 100KBytes. 16 ** -C 1 Operate this process as ClientOne() 17 ** -C 2 Operate this process as ClientTwo() 18 ** 19 ** anonfn.c contains two tests, corresponding to the two protocols for 20 ** passing an anonymous file map to a child process. 21 ** 22 ** ServerOne()/ClientOne() tests the passing of "raw" file map; it uses 23 ** PR_CreateProcess() [for portability of the test case] to create the 24 ** child process, but does not use the PRProcessAttr structure for 25 ** passing the file map data. 26 ** 27 ** ServerTwo()/ClientTwo() tests the passing of the file map using the 28 ** PRProcessAttr structure. 29 ** 30 */ 31 #include <plgetopt.h> 32 #include <nspr.h> 33 #include <private/primpl.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 /* 39 ** Test harness infrastructure 40 */ 41 PRLogModuleInfo* lm; 42 PRLogModuleLevel msgLevel = PR_LOG_NONE; 43 PRUint32 failed_already = 0; 44 45 PRIntn debug = 0; 46 PRIntn client = 0; /* invoke client, style */ 47 char dirName[512] = "."; /* directory name to contain anon mapped file */ 48 PRSize fmSize = (100 * 1024); 49 PRUint32 fmMode = 0600; 50 PRFileMapProtect fmProt = PR_PROT_READWRITE; 51 const char* fmEnvName = "nsprFileMapEnvVariable"; 52 53 /* 54 ** Emit help text for this test 55 */ 56 static void Help(void) { 57 printf("anonfm [options] [dirName]\n"); 58 printf("-d -- enable debug mode\n"); 59 printf( 60 "dirName is alternate directory name. Default: . (current directory)\n"); 61 exit(1); 62 } /* end Help() */ 63 64 /* 65 ** ClientOne() -- 66 */ 67 static void ClientOne(void) { 68 PRFileMap* fm; 69 char* fmString; 70 char* addr; 71 PRStatus rc; 72 73 PR_LOG(lm, msgLevel, ("ClientOne() starting")); 74 75 fmString = PR_GetEnv(fmEnvName); 76 if (NULL == fmString) { 77 failed_already = 1; 78 PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv() failed")); 79 return; 80 } 81 PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv(): found: %s", fmString)); 82 83 fm = PR_ImportFileMapFromString(fmString); 84 if (NULL == fm) { 85 failed_already = 1; 86 PR_LOG(lm, msgLevel, ("ClientOne(): PR_ImportFileMapFromString() failed")); 87 return; 88 } 89 PR_LOG(lm, msgLevel, 90 ("ClientOne(): PR_ImportFileMapFromString(): fm: %p", fm)); 91 92 addr = PR_MemMap(fm, LL_ZERO, fmSize); 93 if (NULL == addr) { 94 failed_already = 1; 95 PR_LOG(lm, msgLevel, 96 ("ClientOne(): PR_MemMap() failed, OSError: %d", PR_GetOSError())); 97 return; 98 } 99 PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemMap(): addr: %p", addr)); 100 101 /* write to memory map to release server */ 102 *addr = 1; 103 104 rc = PR_MemUnmap(addr, fmSize); 105 PR_ASSERT(rc == PR_SUCCESS); 106 PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemUnap(): success")); 107 108 rc = PR_CloseFileMap(fm); 109 if (PR_FAILURE == rc) { 110 failed_already = 1; 111 PR_LOG(lm, msgLevel, 112 ("ClientOne(): PR_MemUnap() failed, OSError: %d", PR_GetOSError())); 113 return; 114 } 115 PR_LOG(lm, msgLevel, ("ClientOne(): PR_CloseFileMap(): success")); 116 117 return; 118 } /* end ClientOne() */ 119 120 /* 121 ** ClientTwo() -- 122 */ 123 static void ClientTwo(void) { failed_already = 1; } /* end ClientTwo() */ 124 125 /* 126 ** ServerOne() -- 127 */ 128 static void ServerOne(void) { 129 PRFileMap* fm; 130 PRStatus rc; 131 PRIntn i; 132 char* addr; 133 char fmString[256]; 134 char envBuf[256]; 135 char* child_argv[8]; 136 PRProcess* proc; 137 PRInt32 exit_status; 138 139 PR_LOG(lm, msgLevel, ("ServerOne() starting")); 140 141 fm = PR_OpenAnonFileMap(dirName, fmSize, fmProt); 142 if (NULL == fm) { 143 failed_already = 1; 144 PR_LOG(lm, msgLevel, ("PR_OpenAnonFileMap() failed")); 145 return; 146 } 147 PR_LOG(lm, msgLevel, ("ServerOne(): FileMap: %p", fm)); 148 149 rc = PR_ExportFileMapAsString(fm, sizeof(fmString), fmString); 150 if (PR_FAILURE == rc) { 151 failed_already = 1; 152 PR_LOG(lm, msgLevel, ("PR_ExportFileMap() failed")); 153 return; 154 } 155 156 /* 157 ** put the string into the environment 158 */ 159 PR_snprintf(envBuf, sizeof(envBuf), "%s=%s", fmEnvName, fmString); 160 putenv(envBuf); 161 162 addr = PR_MemMap(fm, LL_ZERO, fmSize); 163 if (NULL == addr) { 164 failed_already = 1; 165 PR_LOG(lm, msgLevel, ("PR_MemMap() failed")); 166 return; 167 } 168 169 /* set initial value for client */ 170 for (i = 0; i < (PRIntn)fmSize; i++) { 171 *(addr + i) = 0x00; 172 } 173 174 PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemMap(): addr: %p", addr)); 175 176 /* 177 ** set arguments for child process 178 */ 179 child_argv[0] = "anonfm"; 180 child_argv[1] = "-C"; 181 child_argv[2] = "1"; 182 child_argv[3] = NULL; 183 184 proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); 185 PR_ASSERT(proc); 186 PR_LOG(lm, msgLevel, ("ServerOne(): PR_CreateProcess(): proc: %x", proc)); 187 188 /* 189 ** ClientOne() will set the memory to 1 190 */ 191 PR_LOG(lm, msgLevel, ("ServerOne(): waiting on Client, *addr: %x", *addr)); 192 while (*addr == 0x00) { 193 if (debug) { 194 fprintf(stderr, "."); 195 } 196 PR_Sleep(PR_MillisecondsToInterval(300)); 197 } 198 if (debug) { 199 fprintf(stderr, "\n"); 200 } 201 PR_LOG(lm, msgLevel, ("ServerOne(): Client responded")); 202 203 rc = PR_WaitProcess(proc, &exit_status); 204 PR_ASSERT(PR_FAILURE != rc); 205 206 rc = PR_MemUnmap(addr, fmSize); 207 if (PR_FAILURE == rc) { 208 failed_already = 1; 209 PR_LOG(lm, msgLevel, ("PR_MemUnmap() failed")); 210 return; 211 } 212 PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemUnmap(): success")); 213 214 rc = PR_CloseFileMap(fm); 215 if (PR_FAILURE == rc) { 216 failed_already = 1; 217 PR_LOG(lm, msgLevel, ("PR_CloseFileMap() failed")); 218 return; 219 } 220 PR_LOG(lm, msgLevel, ("ServerOne(): PR_CloseFileMap() success")); 221 222 return; 223 } /* end ServerOne() */ 224 225 /* 226 ** ServerTwo() -- 227 */ 228 static void ServerTwo(void) { 229 PR_LOG(lm, msgLevel, ("ServerTwo(): Not implemented yet")); 230 } /* end ServerTwo() */ 231 232 int main(int argc, char** argv) { 233 { 234 /* 235 ** Get command line options 236 */ 237 PLOptStatus os; 238 PLOptState* opt = PL_CreateOptState(argc, argv, "hdC:"); 239 240 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 241 if (PL_OPT_BAD == os) { 242 continue; 243 } 244 switch (opt->option) { 245 case 'C': /* Client style */ 246 client = atol(opt->value); 247 break; 248 case 's': /* file size */ 249 fmSize = atol(opt->value) * 1024; 250 break; 251 case 'd': /* debug */ 252 debug = 1; 253 msgLevel = PR_LOG_DEBUG; 254 break; 255 case 'h': /* help message */ 256 Help(); 257 break; 258 default: 259 strcpy(dirName, opt->value); 260 break; 261 } 262 } 263 PL_DestroyOptState(opt); 264 } 265 266 lm = PR_NewLogModule("Test"); /* Initialize logging */ 267 268 if (client == 1) { 269 ClientOne(); 270 } else if (client == 2) { 271 ClientTwo(); 272 } else { 273 ServerOne(); 274 if (failed_already) { 275 goto Finished; 276 } 277 ServerTwo(); 278 } 279 280 Finished: 281 if (debug) { 282 printf("%s\n", (failed_already) ? "FAIL" : "PASS"); 283 } 284 return ((failed_already == PR_TRUE) ? 1 : 0); 285 } /* main() */ 286 /* end anonfm.c */