CPP-22344: UnixUtil: Reset signal handlers to default

This fixes up the screwed environment the daemon runs on when launched
using osascript on macOS.

GitOrigin-RevId: ff93a7b6967a6ba4c600cae6748c5dfcd122876c
This commit is contained in:
Eldar Abusalimov
2020-11-10 19:24:50 +00:00
committed by intellij-monorepo-bot
parent 9389a23a9a
commit 5d97e1d20f
2 changed files with 78 additions and 4 deletions
@@ -159,7 +159,11 @@ fun main(args: Array<String>) {
if (launchOptions.trampoline) {
trampoline(launchOptions) // never returns
}
if (UnixUtil.isUnix()) {
UnixUtil.setupSignals()
}
if (launchOptions.daemonize) {
require(UnixUtil.isUnix()) { "--daemonize must only be used on Unix" }
UnixUtil.daemonize()
}
@@ -3,6 +3,9 @@ package com.intellij.execution.process.mediator.daemon;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.NativeLongByReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
@@ -10,7 +13,8 @@ import java.util.Objects;
@SuppressWarnings("SpellCheckingInspection")
public final class UnixUtil {
private static final @Nullable LibC LIBC = tryLoadLibC();
private static final boolean IS_UNIX = !System.getProperty("os.name").startsWith("Windows");
private static final @Nullable LibC LIBC = IS_UNIX ? tryLoadLibC() : null;
private UnixUtil() {}
@@ -23,17 +27,59 @@ public final class UnixUtil {
}
}
public static void daemonize() {
private static @NotNull LibC checkLibc() {
if (!IS_UNIX) {
throw new IllegalStateException("Not a Unix system");
}
if (LIBC == null) {
throw new IllegalStateException("Unable to load libc");
}
return LIBC;
}
int sid = LIBC.setsid();
public static boolean isUnix() {
return IS_UNIX;
}
public static void daemonize() {
LibC libc = checkLibc();
int sid = libc.setsid();
if (sid == -1) {
throw new IllegalStateException("setsid: " + getLastErrorString());
}
}
public static void setupSignals() {
LibC libc = checkLibc();
Pointer sigsetPtr = new NativeLongByReference().getPointer();
if (libc.sigfillset(sigsetPtr) == -1) {
throw new IllegalStateException("sigfillset: " + getLastErrorString());
}
if (libc.sigprocmask(LibCConstants.SIG_UNBLOCK, sigsetPtr, Pointer.NULL) == -1) {
throw new IllegalStateException("sigprocmask: " + getLastErrorString());
}
resetSignal(LibCConstants.SIGHUP);
resetSignal(LibCConstants.SIGINT);
resetSignal(LibCConstants.SIGQUIT);
resetSignal(LibCConstants.SIGILL);
resetSignal(LibCConstants.SIGTRAP);
resetSignal(LibCConstants.SIGABRT);
resetSignal(LibCConstants.SIGFPE);
resetSignal(LibCConstants.SIGSEGV);
resetSignal(LibCConstants.SIGPIPE);
resetSignal(LibCConstants.SIGALRM);
resetSignal(LibCConstants.SIGTERM);
}
private static void resetSignal(int signo) {
LibC libc = checkLibc();
if (libc.signal(signo, LibCConstants.SIG_DFL) == LibCConstants.SIG_ERR) {
throw new IllegalStateException("signal(" + signo + "): " + getLastErrorString());
}
}
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public static void closeStdStreams() {
try {
@@ -47,12 +93,36 @@ public final class UnixUtil {
}
private static String getLastErrorString() {
return Objects.requireNonNull(LIBC).strerror(Native.getLastError());
return Objects.requireNonNull(checkLibc()).strerror(Native.getLastError());
}
private interface LibC extends Library {
int setsid();
int sigfillset(Pointer set);
int sigprocmask(int how, Pointer set, Pointer oldset);
Pointer signal(int sig, Pointer handler);
String strerror(int errno);
}
private interface LibCConstants {
int SIG_UNBLOCK = 2;
Pointer SIG_DFL = new Pointer(0);
Pointer SIG_ERR = new Pointer(-1);
int SIGHUP = 1;
int SIGINT = 2;
int SIGQUIT = 3;
int SIGILL = 4;
int SIGTRAP = 5;
int SIGABRT = 6;
int SIGFPE = 8;
int SIGSEGV = 11;
int SIGPIPE = 13;
int SIGALRM = 14;
int SIGTERM = 15;
}
}