Skip to content

Commit 39d62d7

Browse files
aleck099aleck099
andauthored
vfork and execve must be in the same function (#1141)
even system_call() is not allowed, or stack will get corrupted when subprocess runs Co-authored-by: aleck099 <aleck099@outlook.com>
1 parent c66535e commit 39d62d7

File tree

1 file changed

+29
-27
lines changed
  • include/fast_io_hosted/process/process

1 file changed

+29
-27
lines changed

include/fast_io_hosted/process/process/posix.h

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,34 @@ struct fd_remapper
469469
};
470470

471471
// 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
473473
{
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+
474500
#if defined(__linux__) && defined(__NR_execveat)
475501
auto ret{system_call<__NR_execveat, int>(dirfd, cstr, args, envp, AT_SYMLINK_NOFOLLOW)};
476502
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
506532
__builtin_unreachable();
507533
}
508534

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-
524535
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)
525536
{
526537
pid_t pid{};
@@ -530,18 +541,9 @@ inline pid_t vfork_execveat_common_impl(int dirfd, char const *cstr, char const
530541
fm.map(0, pio.in);
531542
fm.map(1, pio.out);
532543
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
543545
}
544-
// resume from vfork
546+
545547
if (t_errno)
546548
{
547549
posix_waitpid(pid);

0 commit comments

Comments
 (0)