Skip to content

MinGW: port POSIX socket compatibility layer #2046

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

Open
wants to merge 84 commits into
base: master
Choose a base branch
from

Conversation

kinkie
Copy link
Contributor

@kinkie kinkie commented Mar 29, 2025

winsock's socket-related functions are very similar
but not identical to the POSIX standard.
Make the mswindows compatibility layer
available to MinGW, and modernize it.

Implement portable wrappers around
socket-related calls, named x, and
use them in all callsites.

Error highlighting the issue:

TcpAcceptor.cc: In member function
  'bool Comm::TcpAcceptor::acceptInto(Comm::ConnectionPointer&)':
TcpAcceptor.cc:352:17: error:
  comparison of unsigned expression in '< 0'
  is always false [-Werror=type-limits]
  352 |     if (rawSock < 0) {

@kinkie
Copy link
Contributor Author

kinkie commented Mar 29, 2025

note: more socket-related functions will need to have this treatment. I wonder whether it's best
to have each have their own header and implementation or to group them all under a single xsocket.* file

@rousskov rousskov self-requested a review March 29, 2025 14:24
yadij
yadij previously requested changes Mar 30, 2025
Copy link
Contributor

@yadij yadij left a comment

Choose a reason for hiding this comment

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

I agree we should probably be planning for libcompat to present the socket.h API as compat/socket.h instead of a separate include file for each syscall.

@yadij yadij added the S-waiting-for-author author action is expected (and usually required) label Mar 30, 2025
@rousskov
Copy link
Contributor

more socket-related functions will need to have this treatment. I wonder whether it's best to have each have their own header and implementation or to group them all under a single xsocket.* file

We should group sys/socket.h wrappers (i.e. listen(2), accept(2), connect(2), shutdown(2), getsockopt(2), etc.), especially if they have similar implementations.

A more difficult question is whether introduction of xfoo() warrants conversion from legacy POSIX foo() to modern C++ API: If every foo() caller is a C++ caller and that caller has to be updated anyway, then it could be the right time to start doing proper memory management and error handling (instead of writing or preserving awkward and duplicated code). That requires a lot more/serious work though. It may also require to get rid of the remaining legacy C callers.

@yadij yadij dismissed their stale review April 9, 2025 13:41

okay, pending @rousskov review issues and final call on whether to use compat/xsocket.* filenames.

kinkie added 7 commits April 17, 2025 08:22
Windows' accept(2) has the same signature as
POSIX', but returns a SOCKET (under the hood, a
int *). This confuses error handling code
in squid, which uses POSIX return values
to detect error values.

Implement xaccept() to wrap around it, taking
the implementation from mswindows.h and using
it on MinGW as well.

Error highlighting the issue:
```
TcpAcceptor.cc: In member function
  'bool Comm::TcpAcceptor::acceptInto(Comm::ConnectionPointer&)':
TcpAcceptor.cc:352:17: error:
  comparison of unsigned expression in '< 0'
  is always false [-Werror=type-limits]
  352 |     if (rawSock < 0) {
```
@kinkie kinkie changed the title MinGW: implement xaccept() MinGW: port POSIX socket compatibility layer Apr 18, 2025
yadij

This comment was marked as resolved.

@kinkie
Copy link
Contributor Author

kinkie commented Apr 30, 2025

We are almost done here. There are more methods (WSADuplicateSocket for instance) but I'd look into them separately.

The only point of questio for me is ioctl/ioctlsocket . Windows has separate versions for files and sockets, and doesn't support fcntl. But then, in practice, we only use ioctl for sockets. My plan here would be to name the x-function xioctlsocket, to highlight that it's not meant to be used on filedescriptors, and not to have an xioctl at all.

@yadij , @rousskov , I'd like advice before committing to a path and then having to change it

@kinkie kinkie added S-waiting-for-reviewer ready for review: Set this when requesting a (re)review using GitHub PR Reviewers box and removed S-waiting-for-author author action is expected (and usually required) labels Apr 30, 2025
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.

What a fundamental effort!

Francesco: The only point of questio for me is ioctl/ioctlsocket . Windows has separate versions for files and sockets, and doesn't support fcntl. But then, in practice, we only use ioctl for sockets. My plan here would be to name the x-function xioctlsocket, to highlight that it's not meant to be used on filedescriptors, and not to have an xioctl at all.

watch_child() may call ioctl() for an open("/dev/tty") descriptor. Does that contradict the above "we only use ioctl for sockets" assertion? Similar concerns may apply to ModDevPoll.cc that uses "/dev/poll".

Win32 API: This ioctlsocket function performs only a subset of functions on a socket when compared to the ioctl function found in Berkeley sockets. The ioctlsocket function has no command parameter equivalent to the FIOASYNC of ioctl, and SIOCATMARK is the only socket-level command that is supported by ioctlsocket.

Can we use xioctl() (instead of xioctlsocket()) everywhere in high-level code? If some callers/use cases can only be supported on Windows via something other than ioctlsocket(), then perhaps our Windows-specific xioctl() implementation can detect those use cases by testing xioctl() parameters and activating special non-ioctlsocket() handling code as needed?

compat/netdb.cc Outdated

#include "squid.h"

#if (_SQUID_WINDOWS_ || _SQUID_MINGW_)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please address the usual condition consistency and "empty line at the end of the file" concerns.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in c21a151

compat/netdb.cc Outdated
struct hostent *
xgethostbyname(const char *name)
{
auto result = ::gethostbyname(name);
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 const to new variable declarations whenever possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in c21a151

compat/netdb.h Outdated
#include <netdb.h>
#endif

/// Provide POSIX gethostbyname(2) API on MinGW and Visual Studio build environments
Copy link
Contributor

Choose a reason for hiding this comment

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

Please focus on describing the function (in all environments it is present). The reasons this function was added will be clear from the commit message. For example:

Suggested change
/// Provide POSIX gethostbyname(2) API on MinGW and Visual Studio build environments
/// POSIX gethostbyname(3) equivalent

or simply

Suggested change
/// Provide POSIX gethostbyname(2) API on MinGW and Visual Studio build environments
/// gethostbyname(3) equivalent

Please add or fix other descriptions in a similar way, paying attention to the correct man page section.

compat/netdb.h Outdated
Comment on lines 21 to 22
#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)
// Windows and MinGW implementations are in compat/netdb.cc
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do not place a comment inside the if statement that is false for that comment context:

Suggested change
#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)
// Windows and MinGW implementations are in compat/netdb.cc
// Windows and MinGW implementations are in compat/netdb.cc
#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)

or

Suggested change
#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)
// Windows and MinGW implementations are in compat/netdb.cc
#if _SQUID_WINDOWS_ || _SQUID_MINGW_
// Windows and MinGW implementations are in compat/netdb.cc
#else

or simply remove this comment -- it is trivial to find those implementations, and we do not have to document the default "implementations are in foo.cc" case anyway!

Suggested change
#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)
// Windows and MinGW implementations are in compat/netdb.cc
#if !(_SQUID_WINDOWS_ || _SQUID_MINGW_)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removing the comment

compat/netdb.h Outdated
Comment on lines 27 to 33
return gethostbyname(name);
}

inline struct servent *
xgetservbyname(const char *name, const char *proto)
{
return ::getservbyname(name, proto);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please keep these trivial/forwarding implementations consistent. For example, either all of them should use :: prefix when calling the primary function or none (by default). The "none" option feels better to me because that is how most similar functions are normally called in Squid code and because these are C (rather than C++) functions, but I may be missing some good reasons to use the global namespace prefix.

@rousskov rousskov added the S-waiting-for-author author action is expected (and usually required) label Apr 30, 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) S-waiting-for-reviewer ready for review: Set this when requesting a (re)review using GitHub PR Reviewers box
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants