-
Notifications
You must be signed in to change notification settings - Fork 603
Add portable wrapper for POSIX kill(2) #2331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| #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_) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #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_) */ | |
| /// POSIX kill(2) equivalent | |
| int xkill(pid_t, int); | |
| #if _SQUID_WINDOWS_ || _SQUID_MINGW_ | |
| inline int xkill(pid_t pid, int sig) { return kill(pid, sig); } | |
| #endif |
| /// true if pid can be sent a signal (no signal is sent) | ||
| inline bool | ||
| IsPidValid(pid_t pid); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not part of the POSIX API. We should be using that API instead of local wrappers.
| /// true if pid can be sent a signal (no signal is sent) | |
| inline bool | |
| IsPidValid(pid_t pid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that compat/signal.h should not provide IsPidValid() API.
Instead, xkill() implementation for Windows may (and probably should!) use a static helper function, hopefully with a more revealing name, to implement xkill(signal=0) support).
Old higher-level code should continue to use ProcessIsRunning() and raw xkill(signal=0) calls.
| static bool | ||
| ProcessIsRunning(const pid_t pid) | ||
| { | ||
| const auto result = kill(pid, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please continue to use the POSIX API equivalent call.
const auto result = xkill(pid, 0);
| } | ||
|
|
||
| /// true if the given pid is the current process, false otherwise | ||
| bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the caller is restored to using xkill(pid, 0) to check for validity this can be made static
| bool | |
| static bool |
| xkill(pid_t pid, int sig) | ||
| { | ||
| auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| char MyProcessName[MAX_PATH]; | ||
| GetProcessName(getpid(), MyProcessName); | ||
| char ProcessNameToCheck[MAX_PATH]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MAX_PATH is not always a small value. Please allocate these dynamically.
| 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The break; case for SIGKILL handling leaves the process handle hanging.
This whole section would be better implemented such that the handle is always closed at a single point of return.
| 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; | |
| // Windows does not support sending generic POSIX signals. | |
| // TODO: implement a signal sending and handling mechanism | |
| // using Windows messages | |
| bool result = false; | |
| switch (sig) { | |
| case SIGKILL: | |
| result = TerminateProcess(hProcess, 0); | |
| break; | |
| case 0: | |
| result = IsPidValid(pid); | |
| break; | |
| default: | |
| // Unsupported signal | |
| } | |
| CloseHandle(hProcess); | |
| return (result ? 0 : -1); |
| #ifndef SQUID_COMPAT_SIGNAL_H | ||
| #define SQUID_COMPAT_SIGNAL_H | ||
|
|
||
| #if !defined(SIGHUP) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a reference for where these values come from.
| #if !defined(SIGHUP) | |
| // Signal definitions from POSIX API. see https://www.man7.org/linux/man-pages/man7/signal.7.html | |
| // TODO: use x86 or arch-specific defines instead of these SPARC CPU values. | |
| #if !defined(SIGHUP) |
| #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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these W...() definitions are part of the POSIX sys/wait.h header. Not part of signal.h.
Please remove.
|
FYI, reference fro what symbols should be in each POSIX header file can be found at https://pubs.opengroup.org/onlinepubs/9799919799/ |
remove redundant code Co-authored-by: Amos Jeffries <yadij@users.noreply.github.com>
rousskov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a comprehensive review, but it may help you remove quite a bit of noise/distractions from this draft PR.
| /// true if pid can be sent a signal (no signal is sent) | ||
| inline bool | ||
| IsPidValid(pid_t pid); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that compat/signal.h should not provide IsPidValid() API.
Instead, xkill() implementation for Windows may (and probably should!) use a static helper function, hopefully with a more revealing name, to implement xkill(signal=0) support).
Old higher-level code should continue to use ProcessIsRunning() and raw xkill(signal=0) calls.
| GetProcessName(getpid(), MyProcessName); | ||
| char ProcessNameToCheck[MAX_PATH]; | ||
| GetProcessName(pid, ProcessNameToCheck); | ||
| if (strcmp(MyProcessName, ProcessNameToCheck) == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not clear to me why IsPidValid(getpid()) should return false. It is usually possible to send a signal to oneself, right? Please either refactor or add a C++ comment to explain why we need to compare getpid() process name with ours.
N.B. I am aware that existing Windows code has similar logic.
P.S. I am writing this change request while assuming that this or similar function is going to be preserved despite the requested removal of "public" IsPidValid() API.
| static void | ||
| GetProcessName(pid_t pid, char *ProcessName) | ||
| { | ||
| strcpy(ProcessName, "unknown"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this code survives, please return a nil name instead of using a special value to mean "we do not know what the process name is [because some system calls have failed]" (that callers do not know about!).
N.B. I am aware that official code uses this hack.
|
I adjusted PR title to highlight that PR changes are going to affect all Please note that PR description talks about |
Windows does not really offer kill() and signal(), only limited wrappers.
Refactor emulation code, rename kill() to xkill() to highlight it's a wrapper