diff --git a/compat/Makefile.am b/compat/Makefile.am index f7875117d0c..1824c27e286 100644 --- a/compat/Makefile.am +++ b/compat/Makefile.am @@ -69,6 +69,8 @@ libcompatsquid_la_SOURCES = \ select.h \ shm.cc \ shm.h \ + signal.cc \ + signal.h \ socket.cc \ socket.h \ statvfs.cc \ diff --git a/compat/mswindows.cc b/compat/mswindows.cc index 6ce80cd3797..50fda2413d8 100644 --- a/compat/mswindows.cc +++ b/compat/mswindows.cc @@ -61,52 +61,6 @@ chroot(const char *dirname) return GetLastError(); } -void -GetProcessName(pid_t pid, char *ProcessName) -{ - strcpy(ProcessName, "unknown"); -#if defined(PSAPI_VERSION) - /* Get a handle to the process. */ - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - /* Get the process name. */ - if (hProcess) { - HMODULE hMod; - DWORD cbNeeded; - - if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) - GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName)); - else { - CloseHandle(hProcess); - return; - } - } else - return; - CloseHandle(hProcess); -#endif -} - -int -kill(pid_t pid, int sig) -{ - HANDLE hProcess; - char MyProcessName[MAX_PATH]; - char ProcessNameToCheck[MAX_PATH]; - - if (sig == 0) { - if (!(hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid))) - return -1; - else { - CloseHandle(hProcess); - GetProcessName(getpid(), MyProcessName); - GetProcessName(pid, ProcessNameToCheck); - if (strcmp(MyProcessName, ProcessNameToCheck) == 0) - return 0; - return -1; - } - } else - return 0; -} - #if !HAVE_GETTIMEOFDAY int gettimeofday(struct timeval *pcur_time, void *tzp) diff --git a/compat/os/mswindows.h b/compat/os/mswindows.h index 96a0faa9ba9..3e29eef802e 100644 --- a/compat/os/mswindows.h +++ b/compat/os/mswindows.h @@ -220,14 +220,6 @@ setenv(const char * const name, const char * const value, const int overwrite) #define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR) #endif -#define SIGHUP 1 /* hangup */ -#define SIGKILL 9 /* kill (cannot be caught or ignored) */ -#define SIGBUS 10 /* bus error */ -#define SIGPIPE 13 /* write on a pipe with no one to read it */ -#define SIGCHLD 20 /* to parent on child stop or exit */ -#define SIGUSR1 30 /* user defined signal 1 */ -#define SIGUSR2 31 /* user defined signal 2 */ - #if defined(_MSC_VER) typedef int uid_t; typedef int gid_t; @@ -534,7 +526,6 @@ struct rusage { #undef ACL SQUIDCEXTERN int chroot(const char *dirname); -SQUIDCEXTERN int kill(pid_t, int); SQUIDCEXTERN struct passwd * getpwnam(char *unused); SQUIDCEXTERN struct group * getgrnam(char *unused); diff --git a/compat/signal.cc b/compat/signal.cc new file mode 100644 index 00000000000..ca86e12eed1 --- /dev/null +++ b/compat/signal.cc @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1996-2025 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#include "squid.h" +#include "compat/signal.h" + +#if _SQUID_WINDOWS_ || _SQUID_MINGW_ + +#ifdef HAVE_PSAPI_H +#include +#endif + +static void +GetProcessName(pid_t pid, char *ProcessName) +{ + strcpy(ProcessName, "unknown"); + + auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!hProcess) // If we cannot open the process, we cannot get its name. + return; + + /* Get the process name. */ + HMODULE hMod; + DWORD cbNeeded; + + if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { + GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName)); + } + CloseHandle(hProcess); +} + +/// true if the given pid is the current process, false otherwise +bool +IsPidValid(pid_t pid) +{ + char MyProcessName[MAX_PATH]; + GetProcessName(getpid(), MyProcessName); + char ProcessNameToCheck[MAX_PATH]; + GetProcessName(pid, ProcessNameToCheck); + if (strcmp(MyProcessName, ProcessNameToCheck) == 0) + return true; + return false; +} + +int +xkill(pid_t pid, int sig) +{ + auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + + if (!hProcess) + return -1; + + switch (sig) { +// Windows does not support sending generic POSIX signals. +// TODO: implement a signal sending and handling mechanism +// using Windows messages + case SIGKILL: + if (TerminateProcess(hProcess, 0)) { + CloseHandle(hProcess); + return 0; + } + break; + case 0: + CloseHandle(hProcess); + if (IsPidValid(pid)) + return 0; + return -1; + break; + default: + // Unsupported signal + CloseHandle(hProcess); + } + + return -1; +} + +#endif /* _SQUID_WINDOWS_ || _SQUID_MINGW_ */ \ No newline at end of file diff --git a/compat/signal.h b/compat/signal.h new file mode 100644 index 00000000000..ed80ef58f9f --- /dev/null +++ b/compat/signal.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 1996-2025 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#ifndef SQUID_COMPAT_SIGNAL_H +#define SQUID_COMPAT_SIGNAL_H + +#if !defined(SIGHUP) +#define SIGHUP 1 /* hangup */ +#endif +#if !defined(SIGKILL) +#define SIGKILL 9 /* kill (cannot be caught or ignored) */ +#endif +#if !defined(SIGBUS) +#define SIGBUS 10 /* bus error */ +#endif +#if !defined(SIGPIPE) +#define SIGPIPE 13 /* write on a pipe with no one to read it */ +#endif +#if !defined(SIGALRM) +#define SIGALRM 14 /* real-time timer expired */ +#endif +#if !defined(SIGCHLD) +#define SIGCHLD 20 /* to parent on child stop or exit */ +#endif +#if !defined(SIGUSR1) +#define SIGUSR1 30 /* user defined signal 1 */ +#endif +#if !defined(SIGUSR2) +#define SIGUSR2 31 /* user defined signal 2 */ +#endif + +/// POSIX kill(2) equivalent +int xkill(pid_t pid, int sig); + +/// true if pid can be sent a signal (no signal is sent) +inline bool +IsPidValid(pid_t pid); + +#if !defined(WIFEXITED) +inline int +WIFEXITED(int status) { + return (status & 0x7f) == 0; +} +#endif + +#if !defined(WEXITSTATUS) +inline int +WEXITSTATUS(int status) { + return (status & 0xff00) >> 8; +} +#endif + +#if !defined(WIFSIGNALED) +inline int +WIFSIGNALED(int status) { + return (status & 0x7f) != 0; +} +#endif + +#if !defined(WTERMSIG) +inline int +WTERMSIG(int status) { + return (status & 0x7f); +} +#endif + +#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_) + +inline int xkill(pid_t pid, int sig) +{ + return kill(pid, sig); +} + +inline bool +IsPidValid(pid_t pid) +{ + return kill(pid, 0) == 0; +} + +#endif /* !(_SQUID_WINDOWS_ || _SQUID_MINGW_) */ + +#endif /* SQUID_COMPAT_SIGNAL_H */ diff --git a/src/Instance.cc b/src/Instance.cc index e8d7dd52b80..d960150642b 100644 --- a/src/Instance.cc +++ b/src/Instance.cc @@ -8,6 +8,7 @@ #include "squid.h" #include "base/File.h" +#include "compat/signal.h" #include "debug/Messages.h" #include "fs_io.h" #include "Instance.h" @@ -95,7 +96,7 @@ GetOtherPid(File &pidFile) static bool ProcessIsRunning(const pid_t pid) { - const auto result = kill(pid, 0); + const auto result = IsPidValid(pid); const auto savedErrno = errno; if (result != 0) debugs(50, 3, "kill(" << pid << ", 0) failed: " << xstrerr(savedErrno)); diff --git a/src/cache_cf.cc b/src/cache_cf.cc index c0af0b6d14d..947a64a2e7b 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -29,6 +29,7 @@ #include "CachePeer.h" #include "CachePeers.h" #include "compat/netdb.h" +#include "compat/signal.h" #include "compat/socket.h" #include "ConfigOption.h" #include "ConfigParser.h" diff --git a/src/ipc/Coordinator.cc b/src/ipc/Coordinator.cc index 7f5aba55ae9..811e3ba28b4 100644 --- a/src/ipc/Coordinator.cc +++ b/src/ipc/Coordinator.cc @@ -14,6 +14,7 @@ #include "CacheManager.h" #include "comm.h" #include "comm/Connection.h" +#include "compat/signal.h" #include "compat/unistd.h" #include "ipc/Coordinator.h" #include "ipc/SharedListen.h" @@ -289,7 +290,7 @@ void Ipc::Coordinator::broadcastSignal(int sig) const for (SCI iter = strands_.begin(); iter != strands_.end(); ++iter) { debugs(54, 5, "signal " << sig << " to kid" << iter->kidId << ", PID=" << iter->pid); - kill(iter->pid, sig); + xkill(iter->pid, sig); } } diff --git a/src/ipc/Kid.cc b/src/ipc/Kid.cc index dd147e7ffd1..9ddf64cc484 100644 --- a/src/ipc/Kid.cc +++ b/src/ipc/Kid.cc @@ -9,6 +9,7 @@ /* DEBUG: section 54 Interprocess Communication */ #include "squid.h" +#include "compat/signal.h" #include "globals.h" #include "ipc/Kid.h" #include "SquidConfig.h" diff --git a/src/log/ModDaemon.cc b/src/log/ModDaemon.cc index d0b77b3c95b..a5715d2f534 100644 --- a/src/log/ModDaemon.cc +++ b/src/log/ModDaemon.cc @@ -11,6 +11,7 @@ #include "squid.h" #include "cbdata.h" #include "comm/Loops.h" +#include "compat/signal.h" #include "fatal.h" #include "fde.h" #include "globals.h" @@ -261,7 +262,7 @@ logfile_mod_daemon_close(Logfile * lf) comm_close(ll->rfd); comm_close(ll->wfd); } - kill(ll->pid, SIGTERM); + xkill(ll->pid, SIGTERM); eventDelete(logfileFlushEvent, lf); xfree(ll); lf->data = nullptr; diff --git a/src/main.cc b/src/main.cc index c18dde60d71..f2671f107b1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -25,6 +25,7 @@ #include "client_side.h" #include "comm.h" #include "CommandLine.h" +#include "compat/signal.h" #include "compat/unistd.h" #include "ConfigParser.h" #include "CpuAffinity.h" @@ -1666,7 +1667,7 @@ sendSignal(void) WIN32_sendSignal(opt_send_signal); #else const auto pid = Instance::Other(); - if (kill(pid, opt_send_signal) && + if (xkill(pid, opt_send_signal) && /* ignore permissions if just running check */ !(opt_send_signal == 0 && errno == EPERM)) { const auto savedErrno = errno; diff --git a/src/mgr/BasicActions.cc b/src/mgr/BasicActions.cc index 2471f7d68ed..8755b2afd3f 100644 --- a/src/mgr/BasicActions.cc +++ b/src/mgr/BasicActions.cc @@ -11,6 +11,7 @@ #include "squid.h" #include "base/TextException.h" #include "CacheManager.h" +#include "compat/signal.h" #include "mgr/ActionCreator.h" #include "mgr/ActionProfile.h" #include "mgr/BasicActions.h" diff --git a/src/tools.cc b/src/tools.cc index 5361b759a9c..69ab62ffef5 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -12,6 +12,7 @@ #include "anyp/PortCfg.h" #include "base/Subscription.h" #include "client_side.h" +#include "compat/signal.h" #include "compat/unistd.h" #include "fatal.h" #include "fde.h" @@ -423,7 +424,7 @@ BroadcastSignalIfAny(int& sig) for (int i = TheKids.count() - 1; i >= 0; --i) { const auto &kid = TheKids.get(i); if (kid.running()) - kill(kid.getPid(), sig); + xkill(kid.getPid(), sig); } } sig = -1; diff --git a/src/windows_service.cc b/src/windows_service.cc index 861b4b38f40..e4f2e4b77f2 100644 --- a/src/windows_service.cc +++ b/src/windows_service.cc @@ -9,6 +9,7 @@ /* Inspired by previous work by Romeo Anghelache & Eric Stern. */ #include "squid.h" +#include "compat/signal.h" #include "debug/Stream.h" #include "globals.h" #include "protos.h"