Skip to content
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

POSIX::dup2() creates an invalid socket on Windows #20920

Closed
xenu opened this issue Mar 10, 2023 · 0 comments · Fixed by #20922
Closed

POSIX::dup2() creates an invalid socket on Windows #20920

xenu opened this issue Mar 10, 2023 · 0 comments · Fixed by #20922

Comments

@xenu
Copy link
Member

xenu commented Mar 10, 2023

Module: POSIX

Description
I thought this was already reported, but apparently not. This happens on all Windows versions and all compilers/CRTs.

Steps to Reproduce
Taken from an IO::Socket::IP ticket:

use warnings;
use strict;
  
use POSIX 'dup2';
use Socket;
  
my ($testHost,$testPort)=('perl.org',443);
my $tcpProto=getprotobyname('tcp');
  
socket(my $sock, PF_INET6, SOCK_STREAM, $tcpProto)
  or die "Could not create IPv6 socket - $!\n";
socket(my $sock2, PF_INET, SOCK_STREAM, $tcpProto)
  or die "Could not create IPv4 socket - $!\n";
  
dup2($sock2->fileno,$sock->fileno)
  or die "Unable to dup2 IPv4 socket onto IPv6 socket - $!\n";
  
my $iaddr=inet_aton($testHost);
my $paddr=sockaddr_in($testPort,$iaddr);
connect($sock,$paddr)
  or die "Failed to connect to $testHost:$testPort - $!\n";
  
print "Successfully connected to $testHost:$testPort\n";

Expected behavior
It should connect successfully.

@xenu xenu changed the title POSIX::dup2() creates an invalid socket on WIndows POSIX::dup2() creates an invalid socket on Windows Mar 10, 2023
xenu added a commit to xenu/perl5 that referenced this issue Mar 10, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43)

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
xenu added a commit to xenu/perl5 that referenced this issue Mar 10, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
xenu added a commit to xenu/perl5 that referenced this issue Mar 17, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
xenu added a commit to xenu/perl5 that referenced this issue Mar 17, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
xenu added a commit that referenced this issue Mar 17, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes #19963)

  - _dup2 properly closes an overwritten socket (fixes #20920)
pjacklam pushed a commit to pjacklam/perl5 that referenced this issue May 20, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
pjacklam pushed a commit to pjacklam/perl5 that referenced this issue May 20, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
khwilliamson pushed a commit to khwilliamson/perl5 that referenced this issue Jul 10, 2023
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.

We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c43).

Amusingly, the author of that solution thought it's just a temporary
workaround:

  /*
   * close RTL fd while respecting sockets
   * added as temporary measure until PerlIO has real
   * Win32 native layer
   *   -- BKS, 11-11-2000
   */

To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847).

Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef). It also wouldn't work
with MinGW configured to use UCRT.

This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.

This also fixes a few issues that the original solution didn't:

  - Closing a busy pipe doesn't cause a deadlock (fixes Perl#19963)

  - _dup2 properly closes an overwritten socket (fixes Perl#20920)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant