@@ -469,8 +469,34 @@ struct fd_remapper
469
469
};
470
470
471
471
// only used in vfork_execveat_common_impl()
472
- inline void execveat_inside_vfork ( int dirfd, char const *cstr, char const *const *args, char const *const *envp, int volatile &t_errno) noexcept
472
+ inline void vfork_and_execveat ( pid_t &pid, int dirfd, char const *cstr, char const *const *args, char const *const *envp, int volatile &t_errno, process_mode mode ) noexcept
473
473
{
474
+ #if defined(__linux__) && defined(__NR_vfork)
475
+ // NOTE: vfork and exec must be in the same function!!!
476
+ // system_call can't be used here
477
+ __asm__ __volatile__ (" syscall"
478
+ : " =a" (pid)
479
+ : " 0" (__NR_vfork)
480
+ : " memory" , " cc" , " r11" , " cx" );
481
+ system_call_throw_error (pid);
482
+ #else
483
+ pid = ::fast_io::posix::libc_vfork ();
484
+ if (pid == -1 ) [[unlikely]]
485
+ {
486
+ throw_posix_error ();
487
+ }
488
+ #endif
489
+ if (pid != 0 )
490
+ {
491
+ return ;
492
+ }
493
+ // parent process ends here
494
+ // subprocess begin
495
+ if ((mode & process_mode::new_session) == process_mode::new_session)
496
+ {
497
+ posix_setsid ();
498
+ }
499
+
474
500
#if defined(__linux__) && defined(__NR_execveat)
475
501
auto ret{system_call<__NR_execveat, int >(dirfd, cstr, args, envp, AT_SYMLINK_NOFOLLOW)};
476
502
if (::fast_io::linux_system_call_fails (ret))
@@ -506,21 +532,6 @@ inline void execveat_inside_vfork(int dirfd, char const *cstr, char const *const
506
532
__builtin_unreachable ();
507
533
}
508
534
509
- inline pid_t posix_vfork ()
510
- {
511
- #if defined(__linux__) && defined(__NR_vfork)
512
- pid_t pid{system_call<__NR_vfork, pid_t >()};
513
- system_call_throw_error (pid);
514
- #else
515
- pid_t pid{::fast_io::posix::libc_vfork ()};
516
- if (pid == -1 ) [[unlikely]]
517
- {
518
- throw_posix_error ();
519
- }
520
- #endif
521
- return pid;
522
- }
523
-
524
535
inline pid_t vfork_execveat_common_impl (int dirfd, char const *cstr, char const *const *args, char const *const *envp, posix_process_io const &pio, process_mode mode)
525
536
{
526
537
pid_t pid{};
@@ -530,18 +541,9 @@ inline pid_t vfork_execveat_common_impl(int dirfd, char const *cstr, char const
530
541
fm.map (0 , pio.in );
531
542
fm.map (1 , pio.out );
532
543
fm.map (2 , pio.err );
533
-
534
- pid = ::fast_io::details::posix_vfork ();
535
- if (pid == 0 )
536
- {
537
- if ((mode & process_mode::new_session) == process_mode::new_session)
538
- {
539
- posix_setsid ();
540
- }
541
- execveat_inside_vfork (dirfd, cstr, args, envp, t_errno); // never return
542
- }
544
+ vfork_and_execveat (pid, dirfd, cstr, args, envp, t_errno, mode); // never return
543
545
}
544
- // resume from vfork
546
+
545
547
if (t_errno)
546
548
{
547
549
posix_waitpid (pid);
0 commit comments