@@ -278,90 +278,51 @@ class SubProcessFunctionExecutorImpl
278
278
return FD;
279
279
}
280
280
281
- Error createSubProcessAndRunBenchmark (
282
- StringRef CounterName, SmallVectorImpl<int64_t > &CounterValues,
283
- ArrayRef<const char *> ValidationCounters,
284
- SmallVectorImpl<int64_t > &ValidationCounterValues) const {
285
- int PipeFiles[2 ];
286
- int PipeSuccessOrErr = socketpair (AF_UNIX, SOCK_DGRAM, 0 , PipeFiles);
287
- if (PipeSuccessOrErr != 0 ) {
288
- return make_error<Failure>(
289
- " Failed to create a pipe for interprocess communication between "
290
- " llvm-exegesis and the benchmarking subprocess: " +
291
- Twine (strerror (errno)));
292
- }
293
-
294
- SubprocessMemory SPMemory;
295
- Error MemoryInitError = SPMemory.initializeSubprocessMemory (getpid ());
296
- if (MemoryInitError)
297
- return MemoryInitError;
298
-
299
- Error AddMemDefError =
300
- SPMemory.addMemoryDefinition (Key.MemoryValues , getpid ());
301
- if (AddMemDefError)
302
- return AddMemDefError;
303
-
304
- pid_t ParentOrChildPID = fork ();
305
-
306
- if (ParentOrChildPID == -1 ) {
307
- return make_error<Failure>(" Failed to create child process: " +
308
- Twine (strerror (errno)));
309
- }
310
-
311
- if (ParentOrChildPID == 0 ) {
312
- // We are in the child process, close the write end of the pipe.
313
- close (PipeFiles[1 ]);
314
- // Unregister handlers, signal handling is now handled through ptrace in
315
- // the host process.
316
- sys::unregisterHandlers ();
317
- prepareAndRunBenchmark (PipeFiles[0 ], Key);
318
- // The child process terminates in the above function, so we should never
319
- // get to this point.
320
- llvm_unreachable (" Child process didn't exit when expected." );
321
- }
322
-
281
+ Error
282
+ runParentProcess (pid_t ChildPID, int WriteFD, StringRef CounterName,
283
+ SmallVectorImpl<int64_t > &CounterValues,
284
+ ArrayRef<const char *> ValidationCounters,
285
+ SmallVectorImpl<int64_t > &ValidationCounterValues) const {
323
286
const ExegesisTarget &ET = State.getExegesisTarget ();
324
- auto CounterOrError = ET. createCounter (
325
- CounterName, State, ValidationCounters, ParentOrChildPID );
287
+ auto CounterOrError =
288
+ ET. createCounter ( CounterName, State, ValidationCounters, ChildPID );
326
289
327
290
if (!CounterOrError)
328
291
return CounterOrError.takeError ();
329
292
330
293
pfm::CounterGroup *Counter = CounterOrError.get ().get ();
331
294
332
- close (PipeFiles[0 ]);
333
-
334
295
// Make sure to attach to the process (and wait for the sigstop to be
335
296
// delivered and for the process to continue) before we write to the counter
336
297
// file descriptor. Attaching to the process before writing to the socket
337
298
// ensures that the subprocess at most has blocked on the read call. If we
338
299
// attach afterwards, the subprocess might exit before we get to the attach
339
300
// call due to effects like scheduler contention, introducing transient
340
301
// failures.
341
- if (ptrace (PTRACE_ATTACH, ParentOrChildPID , NULL , NULL ) != 0 )
302
+ if (ptrace (PTRACE_ATTACH, ChildPID , NULL , NULL ) != 0 )
342
303
return make_error<Failure>(" Failed to attach to the child process: " +
343
304
Twine (strerror (errno)));
344
305
345
- if (waitpid (ParentOrChildPID , NULL , 0 ) == -1 ) {
306
+ if (waitpid (ChildPID , NULL , 0 ) == -1 ) {
346
307
return make_error<Failure>(
347
308
" Failed to wait for child process to stop after attaching: " +
348
309
Twine (strerror (errno)));
349
310
}
350
311
351
- if (ptrace (PTRACE_CONT, ParentOrChildPID , NULL , NULL ) != 0 )
312
+ if (ptrace (PTRACE_CONT, ChildPID , NULL , NULL ) != 0 )
352
313
return make_error<Failure>(
353
314
" Failed to continue execution of the child process: " +
354
315
Twine (strerror (errno)));
355
316
356
317
int CounterFileDescriptor = Counter->getFileDescriptor ();
357
318
Error SendError =
358
- sendFileDescriptorThroughSocket (PipeFiles[ 1 ] , CounterFileDescriptor);
319
+ sendFileDescriptorThroughSocket (WriteFD , CounterFileDescriptor);
359
320
360
321
if (SendError)
361
322
return SendError;
362
323
363
324
int ChildStatus;
364
- if (waitpid (ParentOrChildPID , &ChildStatus, 0 ) == -1 ) {
325
+ if (waitpid (ChildPID , &ChildStatus, 0 ) == -1 ) {
365
326
return make_error<Failure>(
366
327
" Waiting for the child process to complete failed: " +
367
328
Twine (strerror (errno)));
@@ -395,8 +356,7 @@ class SubProcessFunctionExecutorImpl
395
356
396
357
// An error was encountered running the snippet, process it
397
358
siginfo_t ChildSignalInfo;
398
- if (ptrace (PTRACE_GETSIGINFO, ParentOrChildPID, NULL , &ChildSignalInfo) ==
399
- -1 ) {
359
+ if (ptrace (PTRACE_GETSIGINFO, ChildPID, NULL , &ChildSignalInfo) == -1 ) {
400
360
return make_error<Failure>(" Getting signal info from the child failed: " +
401
361
Twine (strerror (errno)));
402
362
}
@@ -405,13 +365,13 @@ class SubProcessFunctionExecutorImpl
405
365
// handlers to run, and calling SIGTERM would mean that ptrace will force
406
366
// it to block in the signal-delivery-stop for the SIGSEGV/other signals,
407
367
// and upon exit.
408
- if (kill (ParentOrChildPID , SIGKILL) == -1 )
368
+ if (kill (ChildPID , SIGKILL) == -1 )
409
369
return make_error<Failure>(" Failed to kill child benchmarking proces: " +
410
370
Twine (strerror (errno)));
411
371
412
372
// Wait for the process to exit so that there are no zombie processes left
413
373
// around.
414
- if (waitpid (ParentOrChildPID , NULL , 0 ) == -1 )
374
+ if (waitpid (ChildPID , NULL , 0 ) == -1 )
415
375
return make_error<Failure>(" Failed to wait for process to die: " +
416
376
Twine (strerror (errno)));
417
377
@@ -422,15 +382,65 @@ class SubProcessFunctionExecutorImpl
422
382
return make_error<SnippetSignal>(ChildSignalInfo.si_signo );
423
383
}
424
384
385
+ Error createSubProcessAndRunBenchmark (
386
+ StringRef CounterName, SmallVectorImpl<int64_t > &CounterValues,
387
+ ArrayRef<const char *> ValidationCounters,
388
+ SmallVectorImpl<int64_t > &ValidationCounterValues) const {
389
+ int PipeFiles[2 ];
390
+ int PipeSuccessOrErr = socketpair (AF_UNIX, SOCK_DGRAM, 0 , PipeFiles);
391
+ if (PipeSuccessOrErr != 0 ) {
392
+ return make_error<Failure>(
393
+ " Failed to create a pipe for interprocess communication between "
394
+ " llvm-exegesis and the benchmarking subprocess: " +
395
+ Twine (strerror (errno)));
396
+ }
397
+
398
+ SubprocessMemory SPMemory;
399
+ Error MemoryInitError = SPMemory.initializeSubprocessMemory (getpid ());
400
+ if (MemoryInitError)
401
+ return MemoryInitError;
402
+
403
+ Error AddMemDefError =
404
+ SPMemory.addMemoryDefinition (Key.MemoryValues , getpid ());
405
+ if (AddMemDefError)
406
+ return AddMemDefError;
407
+
408
+ pid_t ParentOrChildPID = fork ();
409
+
410
+ if (ParentOrChildPID == -1 ) {
411
+ return make_error<Failure>(" Failed to create child process: " +
412
+ Twine (strerror (errno)));
413
+ }
414
+
415
+ if (ParentOrChildPID == 0 ) {
416
+ // We are in the child process, close the write end of the pipe.
417
+ close (PipeFiles[1 ]);
418
+ // Unregister handlers, signal handling is now handled through ptrace in
419
+ // the host process.
420
+ sys::unregisterHandlers ();
421
+ runChildSubprocess (PipeFiles[0 ], Key);
422
+ // The child process terminates in the above function, so we should never
423
+ // get to this point.
424
+ llvm_unreachable (" Child process didn't exit when expected." );
425
+ }
426
+
427
+ // Close the read end of the pipe as we only need to write to the subprocess
428
+ // from the parent process.
429
+ close (PipeFiles[0 ]);
430
+ return runParentProcess (ParentOrChildPID, PipeFiles[1 ], CounterName,
431
+ CounterValues, ValidationCounters,
432
+ ValidationCounterValues);
433
+ }
434
+
425
435
void disableCoreDumps () const {
426
436
struct rlimit rlim;
427
437
428
438
rlim.rlim_cur = 0 ;
429
439
setrlimit (RLIMIT_CORE, &rlim);
430
440
}
431
441
432
- [[noreturn]] void prepareAndRunBenchmark (int Pipe,
433
- const BenchmarkKey &Key) const {
442
+ [[noreturn]] void runChildSubprocess (int Pipe,
443
+ const BenchmarkKey &Key) const {
434
444
// Disable core dumps in the child process as otherwise everytime we
435
445
// encounter an execution failure like a segmentation fault, we will create
436
446
// a core dump. We report the information directly rather than require the
0 commit comments