mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Configure PR_SET_PDEATHSIG on Linux and Job Objects on Windows to prevent orphaned subprocesses on program crash
This commit is contained in:
parent
0ca7c65049
commit
6b46e08a1f
4 changed files with 76 additions and 7 deletions
|
|
@ -70,12 +70,9 @@ dnl Checks for header files.
|
|||
AC_HEADER_ASSERT
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h time.h sys/time.h])
|
||||
AC_CHECK_HEADERS([unistd.h getopt.h io.h inttypes.h byteswap.h])
|
||||
AC_CHECK_HEADERS([pthread.h math.h syslog.h grp.h pwd.h])
|
||||
AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/sysmacros.h sys/mkdev.h sys/mount.h])
|
||||
AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/btrfs.h execinfo.h])
|
||||
AC_CHECK_HEADERS([mach/mach_time.h sys/sysctl.h])
|
||||
AC_CHECK_HEADERS([stdint.h inttypes.h unistd.h math.h execinfo.h strings.h getopt.h syslog.h grp.h pwd.h io.h])
|
||||
AC_CHECK_HEADERS([sys/file.h sys/sysctl.h sys/ioctl.h sys/time.h sys/types.h sys/mkdev.h sys/sysmacros.h sys/stat.h sys/prctl.h sys/sysinfo.h sys/utsname.h])
|
||||
AC_CHECK_HEADERS([linux/fs.h linux/btrfs.h linux/fiemap.h mach/mach_time.h])
|
||||
|
||||
# Check for the close_range(...,CLOSE_RANGE_CLOEXEC)
|
||||
AC_CHECK_HEADERS([linux/close_range.h])
|
||||
|
|
|
|||
30
os/mingw.c
30
os/mingw.c
|
|
@ -2531,6 +2531,8 @@ static int argcat(WCHAR* cmd, int size, int pos, const WCHAR* arg)
|
|||
return pos;
|
||||
}
|
||||
|
||||
static HANDLE os_job_handle = 0;
|
||||
|
||||
pid_t os_spawn(char** argv, int* stdout_read_int, int* stderr_read_int, const char* run_as_user)
|
||||
{
|
||||
wchar_t conv[CONV_MAX];
|
||||
|
|
@ -2743,6 +2745,17 @@ pid_t os_spawn(char** argv, int* stdout_read_int, int* stderr_read_int, const ch
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign spawned process to Job Object configured with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
|
||||
* This ensures Windows automatically terminates child processes if the daemon crashes unexpectedly.
|
||||
*/
|
||||
if (os_job_handle != 0) {
|
||||
if (!AssignProcessToJobObject(os_job_handle, pi.hProcess)) {
|
||||
windows_errno(GetLastError());
|
||||
os_syslog(OS_LVL_INFO, "failed to assign process to job object, errno=%s(%d)", strerror(errno), errno);
|
||||
}
|
||||
}
|
||||
|
||||
/* close the write end of the pipes in the parent */
|
||||
if (has_out) {
|
||||
CloseHandle(stdout_write_handle);
|
||||
|
|
@ -3550,6 +3563,18 @@ void os_init(unsigned opt)
|
|||
os_exit();
|
||||
}
|
||||
|
||||
/* initialize job object to terminate child processes if daemon dies */
|
||||
os_job_handle = CreateJobObjectW(0, 0);
|
||||
if (os_job_handle != 0) {
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
if (!SetInformationJobObject(os_job_handle, JobObjectExtendedLimitInformation, &info, sizeof(info))) {
|
||||
CloseHandle(os_job_handle);
|
||||
os_job_handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for Wine presence */
|
||||
is_wine = GetProcAddress(ntdll, "wine_get_version") != 0;
|
||||
|
||||
|
|
@ -3572,6 +3597,11 @@ void os_init(unsigned opt)
|
|||
|
||||
void os_done(void)
|
||||
{
|
||||
if (os_job_handle != 0) {
|
||||
CloseHandle(os_job_handle);
|
||||
os_job_handle = 0;
|
||||
}
|
||||
|
||||
/* delete the thread local storage for strerror() */
|
||||
windows_key_delete(last_error);
|
||||
|
||||
|
|
|
|||
|
|
@ -217,6 +217,10 @@
|
|||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
|
@ -309,4 +313,3 @@
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
39
os/unix.c
39
os/unix.c
|
|
@ -765,6 +765,10 @@ int os_script(char** argv, char** envp, const char* run_as_user)
|
|||
|
||||
start = os_tick_sec();
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
pid_t ppid = getpid();
|
||||
#endif
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
os_syslog(OS_LVL_INFO, "failed to fork script=%s, errno=%s(%d)", resolved_path, strerror(errno), errno);
|
||||
|
|
@ -802,6 +806,15 @@ int os_script(char** argv, char** envp, const char* run_as_user)
|
|||
_exit(126);
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
/* Send SIGKILL to child if parent daemon dies unexpectedly */
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
/* exit if parent died before prctl to avoid becoming orphaned */
|
||||
if (getppid() != ppid) {
|
||||
_exit(127);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* io sandboxing */
|
||||
int null_fd = open("/dev/null", O_RDWR);
|
||||
if (null_fd == -1)
|
||||
|
|
@ -933,6 +946,10 @@ int os_command(const char* command, const char* run_as_user, const char* stdin_t
|
|||
|
||||
start = os_tick_sec();
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
pid_t ppid = getpid();
|
||||
#endif
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
os_syslog(OS_LVL_INFO, "failed to fork command=%s, errno=%s(%d)", command, strerror(errno), errno);
|
||||
|
|
@ -976,6 +993,15 @@ int os_command(const char* command, const char* run_as_user, const char* stdin_t
|
|||
_exit(126);
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
/* Send SIGKILL to child if parent daemon dies unexpectedly */
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
/* exit if parent died before prctl to avoid becoming orphaned */
|
||||
if (getppid() != ppid) {
|
||||
_exit(127);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* io sandboxing */
|
||||
int null_fd = open("/dev/null", O_RDWR);
|
||||
if (null_fd == -1)
|
||||
|
|
@ -1157,6 +1183,10 @@ pid_t os_spawn(char** argv, int* stdout_read_fd, int* stderr_read_fd, const char
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
pid_t ppid = getpid();
|
||||
#endif
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
os_syslog(OS_LVL_INFO, "failed to fork path=%s, errno=%s(%d)", resolved_path, strerror(errno), errno);
|
||||
|
|
@ -1195,6 +1225,15 @@ pid_t os_spawn(char** argv, int* stdout_read_fd, int* stderr_read_fd, const char
|
|||
_exit(126);
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
/* Send SIGKILL to child if parent daemon dies unexpectedly */
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
/* exit if parent died before prctl to avoid becoming orphaned */
|
||||
if (getppid() != ppid) {
|
||||
_exit(127);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* io sandboxing */
|
||||
int null_fd = open("/dev/null", O_RDWR | O_CLOEXEC);
|
||||
if (null_fd < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue