mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -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
9a1987e024
commit
cf2196a90f
4 changed files with 70 additions and 10 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])
|
||||
|
|
|
|||
27
os/mingw.c
27
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,14 @@ 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) {
|
||||
AssignProcessToJobObject(os_job_handle, pi.hProcess);
|
||||
}
|
||||
|
||||
/* close the write end of the pipes in the parent */
|
||||
if (has_out) {
|
||||
CloseHandle(stdout_write_handle);
|
||||
|
|
@ -3531,6 +3541,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;
|
||||
|
||||
|
|
@ -3553,6 +3575,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
|
|
@ -748,7 +748,7 @@ int os_validate_exec_input(const char* str)
|
|||
int os_script(char** argv, char** envp, const char* run_as_user)
|
||||
{
|
||||
char resolved_path[PATH_MAX];
|
||||
pid_t pid;
|
||||
pid_t pid, ppid;
|
||||
int ret;
|
||||
int status;
|
||||
int64_t start, stop;
|
||||
|
|
@ -765,6 +765,8 @@ int os_script(char** argv, char** envp, const char* run_as_user)
|
|||
|
||||
start = os_tick_sec();
|
||||
|
||||
ppid = getpid();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
os_syslog(OS_LVL_INFO, "failed to fork script=%s, errno=%s(%d)", resolved_path, strerror(errno), errno);
|
||||
|
|
@ -783,6 +785,15 @@ int os_script(char** argv, char** envp, const char* run_as_user)
|
|||
*/
|
||||
setpgid(0, 0);
|
||||
|
||||
#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
|
||||
|
||||
/* drop privileges first (if configured) */
|
||||
if (run_as_user && run_as_user[0] != 0) {
|
||||
errno = 0;
|
||||
|
|
@ -917,7 +928,7 @@ int os_script(char** argv, char** envp, const char* run_as_user)
|
|||
|
||||
int os_command(const char* command, const char* run_as_user, const char* stdin_text)
|
||||
{
|
||||
pid_t pid;
|
||||
pid_t pid, ppid;
|
||||
int ret;
|
||||
int status;
|
||||
int pipe_fds[2] = { -1, -1 };
|
||||
|
|
@ -933,6 +944,8 @@ int os_command(const char* command, const char* run_as_user, const char* stdin_t
|
|||
|
||||
start = os_tick_sec();
|
||||
|
||||
ppid = getpid();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
os_syslog(OS_LVL_INFO, "failed to fork command=%s, errno=%s(%d)", command, strerror(errno), errno);
|
||||
|
|
@ -954,6 +967,15 @@ int os_command(const char* command, const char* run_as_user, const char* stdin_t
|
|||
*/
|
||||
setpgid(0, 0);
|
||||
|
||||
#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
|
||||
|
||||
if (pipe_fds[1] != -1)
|
||||
close(pipe_fds[1]); /* Close unused write end */
|
||||
|
||||
|
|
@ -1130,7 +1152,7 @@ pid_t os_spawn(char** argv, int* stdout_read_fd, int* stderr_read_fd, const char
|
|||
int err_pipe[2];
|
||||
int has_out = (stdout_read_fd != NULL);
|
||||
int has_err = (stderr_read_fd != NULL);
|
||||
pid_t pid;
|
||||
pid_t pid, ppid;
|
||||
|
||||
int fd = verify_executable(argv[0], resolved_path, 0);
|
||||
if (fd < 0) {
|
||||
|
|
@ -1157,6 +1179,8 @@ pid_t os_spawn(char** argv, int* stdout_read_fd, int* stderr_read_fd, const char
|
|||
}
|
||||
}
|
||||
|
||||
ppid = getpid();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
os_syslog(OS_LVL_INFO, "failed to fork path=%s, errno=%s(%d)", resolved_path, strerror(errno), errno);
|
||||
|
|
@ -1177,6 +1201,15 @@ pid_t os_spawn(char** argv, int* stdout_read_fd, int* stderr_read_fd, const char
|
|||
|
||||
setpgid(0, 0);
|
||||
|
||||
#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
|
||||
|
||||
/* drop privileges first (if configured) */
|
||||
if (run_as_user && run_as_user[0] != 0) {
|
||||
errno = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue