@@ -278,28 +278,67 @@ class SubProcessFunctionExecutorImpl
278
278
return FD;
279
279
}
280
280
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 {
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
+
286
323
const ExegesisTarget &ET = State.getExegesisTarget ();
287
- auto CounterOrError =
288
- ET. createCounter ( CounterName, State, ValidationCounters, ChildPID );
324
+ auto CounterOrError = ET. createCounter (
325
+ CounterName, State, ValidationCounters, ParentOrChildPID );
289
326
290
327
if (!CounterOrError)
291
328
return CounterOrError.takeError ();
292
329
293
330
pfm::CounterGroup *Counter = CounterOrError.get ().get ();
294
331
332
+ close (PipeFiles[0 ]);
333
+
295
334
// Make sure to attach to the process (and wait for the sigstop to be
296
335
// delivered and for the process to continue) before we write to the counter
297
336
// file descriptor. Attaching to the process before writing to the socket
298
337
// ensures that the subprocess at most has blocked on the read call. If we
299
338
// attach afterwards, the subprocess might exit before we get to the attach
300
339
// call due to effects like scheduler contention, introducing transient
301
340
// failures.
302
- if (ptrace (PTRACE_ATTACH, ChildPID , NULL , NULL ) != 0 )
341
+ if (ptrace (PTRACE_ATTACH, ParentOrChildPID , NULL , NULL ) != 0 )
303
342
return make_error<Failure>(" Failed to attach to the child process: " +
304
343
Twine (strerror (errno)));
305
344
@@ -309,14 +348,14 @@ class SubProcessFunctionExecutorImpl
309
348
Twine (strerror (errno)));
310
349
}
311
350
312
- if (ptrace (PTRACE_CONT, ChildPID , NULL , NULL ) != 0 )
351
+ if (ptrace (PTRACE_CONT, ParentOrChildPID , NULL , NULL ) != 0 )
313
352
return make_error<Failure>(
314
353
" Failed to continue execution of the child process: " +
315
354
Twine (strerror (errno)));
316
355
317
356
int CounterFileDescriptor = Counter->getFileDescriptor ();
318
357
Error SendError =
319
- sendFileDescriptorThroughSocket (WriteFD , CounterFileDescriptor);
358
+ sendFileDescriptorThroughSocket (PipeFiles[ 1 ] , CounterFileDescriptor);
320
359
321
360
if (SendError)
322
361
return SendError;
@@ -356,7 +395,8 @@ class SubProcessFunctionExecutorImpl
356
395
357
396
// An error was encountered running the snippet, process it
358
397
siginfo_t ChildSignalInfo;
359
- if (ptrace (PTRACE_GETSIGINFO, ChildPID, NULL , &ChildSignalInfo) == -1 ) {
398
+ if (ptrace (PTRACE_GETSIGINFO, ParentOrChildPID, NULL , &ChildSignalInfo) ==
399
+ -1 ) {
360
400
return make_error<Failure>(" Getting signal info from the child failed: " +
361
401
Twine (strerror (errno)));
362
402
}
@@ -382,65 +422,15 @@ class SubProcessFunctionExecutorImpl
382
422
return make_error<SnippetSignal>(ChildSignalInfo.si_signo );
383
423
}
384
424
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
-
435
425
void disableCoreDumps () const {
436
426
struct rlimit rlim;
437
427
438
428
rlim.rlim_cur = 0 ;
439
429
setrlimit (RLIMIT_CORE, &rlim);
440
430
}
441
431
442
- [[noreturn]] void runChildSubprocess (int Pipe,
443
- const BenchmarkKey &Key) const {
432
+ [[noreturn]] void prepareAndRunBenchmark (int Pipe,
433
+ const BenchmarkKey &Key) const {
444
434
// Disable core dumps in the child process as otherwise everytime we
445
435
// encounter an execution failure like a segmentation fault, we will create
446
436
// a core dump. We report the information directly rather than require the
0 commit comments