Skip to content

Conversation

@kinkie
Copy link
Contributor

@kinkie kinkie commented Dec 26, 2025

Windows does not really offer kill() and signal(), only limited wrappers.
Refactor emulation code, rename kill() to xkill() to highlight it's a wrapper

@kinkie kinkie marked this pull request as draft December 26, 2025 15:21
@rousskov rousskov self-requested a review December 26, 2025 19:39
Comment on lines +72 to +85
#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_) */
Copy link
Contributor

@yadij yadij Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#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

Comment on lines +40 to +43
/// true if pid can be sent a signal (no signal is sent)
inline bool
IsPidValid(pid_t pid);

Copy link
Contributor

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.

Suggested change
/// true if pid can be sent a signal (no signal is sent)
inline bool
IsPidValid(pid_t pid);

Copy link
Contributor

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);
Copy link
Contributor

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
Copy link
Contributor

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

Suggested change
bool
static bool

xkill(pid_t pid, int sig)
{
auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Comment on lines +44 to +46
char MyProcessName[MAX_PATH];
GetProcessName(getpid(), MyProcessName);
char ProcessNameToCheck[MAX_PATH];
Copy link
Contributor

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.

Comment on lines +61 to +82
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;
Copy link
Contributor

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.

Suggested change
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)
Copy link
Contributor

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.

Suggested change
#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)

Comment on lines +44 to +70
#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
Copy link
Contributor

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.

@yadij
Copy link
Contributor

yadij commented Dec 26, 2025

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>
Copy link
Contributor

@rousskov rousskov left a 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.

Comment on lines +40 to +43
/// true if pid can be sent a signal (no signal is sent)
inline bool
IsPidValid(pid_t pid);

Copy link
Contributor

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)
Copy link
Contributor

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");
Copy link
Contributor

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.

@rousskov rousskov changed the title MinGW: refactor signal code Add portable wrapper for POSIX kill(2) Dec 28, 2025
@rousskov
Copy link
Contributor

I adjusted PR title to highlight that PR changes are going to affect all kill(2) callers, not just MinGW code.

Please note that PR description talks about signal() as well. I suggest removing that text from PR description. If we need a portable signal(3) alternative, we should probably use std::signal(), but we can make those decisions in a dedicated PR, when needed.

@rousskov rousskov added the S-waiting-for-author author action is expected (and usually required) label Dec 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-for-author author action is expected (and usually required)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants