1# You may distribute under the terms of either the GNU General Public License 2# or the Artistic License (the same terms as Perl itself) 3# 4# (C) Paul Evans, 2012-2019 -- leonerd@leonerd.org.uk 5 6package IO::Async::OS; 7 8use strict; 9use warnings; 10 11our $VERSION = '0.800'; 12 13our @ISA = qw( IO::Async::OS::_Base ); 14 15if( eval { require "IO/Async/OS/$^O.pm" } ) { 16 @ISA = "IO::Async::OS::$^O"; 17} 18 19package # hide from CPAN 20 IO::Async::OS::_Base; 21 22use Carp; 23 24use Socket 1.95 qw( 25 AF_INET AF_INET6 AF_UNIX INADDR_LOOPBACK SOCK_DGRAM SOCK_RAW SOCK_STREAM 26 pack_sockaddr_in inet_aton 27 pack_sockaddr_in6 inet_pton 28 pack_sockaddr_un 29); 30 31use POSIX qw( sysconf _SC_OPEN_MAX ); 32 33# Win32 [and maybe other places] don't have an _SC_OPEN_MAX. About the best we 34# can do really is just make up some largeish number and hope for the best. 35use constant OPEN_MAX_FD => eval { sysconf(_SC_OPEN_MAX) } || 1024; 36 37# Some constants that define features of the OS 38 39use constant HAVE_SOCKADDR_IN6 => defined eval { pack_sockaddr_in6 0, inet_pton( AF_INET6, "2001::1" ) }; 40use constant HAVE_SOCKADDR_UN => defined eval { pack_sockaddr_un "/foo" }; 41 42# Do we have to fake S_ISREG() files read/write-ready in select()? 43use constant HAVE_FAKE_ISREG_READY => 0; 44 45# Do we have to select() for for evec to get connect() failures 46use constant HAVE_SELECT_CONNECT_EVEC => 0; 47# Ditto; do we have to poll() for POLLPRI to get connect() failures 48use constant HAVE_POLL_CONNECT_POLLPRI => 0; 49 50# Does connect() yield EWOULDBLOCK for nonblocking in progress? 51use constant HAVE_CONNECT_EWOULDBLOCK => 0; 52 53# Can we rename() files that are open? 54use constant HAVE_RENAME_OPEN_FILES => 1; 55 56# Can we reliably watch for POSIX signals, including SIGCHLD to reliably 57# inform us that a fork()ed child has exit()ed? 58use constant HAVE_SIGNALS => 1; 59 60# Do we support POSIX-style true fork()ed processes at all? 61use constant HAVE_POSIX_FORK => !$ENV{IO_ASYNC_NO_FORK}; 62# Can we potentially support threads? (would still need to 'require threads') 63use constant HAVE_THREADS => !$ENV{IO_ASYNC_NO_THREADS} && 64 eval { require Config && $Config::Config{useithreads} }; 65 66# Preferred trial order for built-in Loop classes 67use constant LOOP_BUILTIN_CLASSES => qw( Poll Select ); 68 69# Should there be any other Loop classes we try before the builtin ones? 70use constant LOOP_PREFER_CLASSES => (); 71 72=head1 NAME 73 74C<IO::Async::OS> - operating system abstractions for C<IO::Async> 75 76=head1 DESCRIPTION 77 78This module acts as a class to provide a number of utility methods whose exact 79behaviour may depend on the type of OS it is running on. It is provided as a 80class so that specific kinds of operating system can override methods in it. 81 82As well as these support functions it also provides a number of constants, all 83with names beginning C<HAVE_> which describe various features that may or may 84not be available on the OS or perl build. Most of these are either hard-coded 85per OS, or detected at runtime. 86 87The following constants may be overridden by environment variables. 88 89=over 4 90 91=item * HAVE_POSIX_FORK 92 93True if the C<fork()> call has full POSIX semantics (full process separation). 94This is true on most OSes but false on MSWin32. 95 96This may be overridden to be false by setting the environment variable 97C<IO_ASYNC_NO_FORK>. 98 99=item * HAVE_THREADS 100 101True if C<ithreads> are available, meaning that the C<threads> module can be 102used. This depends on whether perl was built with threading support. 103 104This may be overridable to be false by setting the environment variable 105C<IO_ASYNC_NO_THREADS>. 106 107=back 108 109=cut 110 111=head2 getfamilybyname 112 113 $family = IO::Async::OS->getfamilybyname( $name ) 114 115Return a protocol family value based on the given name. If C<$name> looks like 116a number it will be returned as-is. The string values C<inet>, C<inet6> and 117C<unix> will be converted to the appropriate C<AF_*> constant. 118 119=cut 120 121sub getfamilybyname 122{ 123 shift; 124 my ( $name ) = @_; 125 126 return undef unless defined $name; 127 128 return $name if $name =~ m/^\d+$/; 129 130 return AF_INET if $name eq "inet"; 131 return AF_INET6() if $name eq "inet6" and defined &AF_INET6; 132 return AF_UNIX if $name eq "unix"; 133 134 croak "Unrecognised socket family name '$name'"; 135} 136 137=head2 getsocktypebyname 138 139 $socktype = IO::Async::OS->getsocktypebyname( $name ) 140 141Return a socket type value based on the given name. If C<$name> looks like a 142number it will be returned as-is. The string values C<stream>, C<dgram> and 143C<raw> will be converted to the appropriate C<SOCK_*> constant. 144 145=cut 146 147sub getsocktypebyname 148{ 149 shift; 150 my ( $name ) = @_; 151 152 return undef unless defined $name; 153 154 return $name if $name =~ m/^\d+$/; 155 156 return SOCK_STREAM if $name eq "stream"; 157 return SOCK_DGRAM if $name eq "dgram"; 158 return SOCK_RAW if $name eq "raw"; 159 160 croak "Unrecognised socktype name '$name'"; 161} 162 163# This one isn't documented because it's not really overridable. It's largely 164# here just for completeness 165my $HAVE_IO_SOCKET_IP; 166 167sub socket 168{ 169 my $self = shift; 170 my ( $family, $socktype, $proto ) = @_; 171 172 require IO::Socket; 173 defined $HAVE_IO_SOCKET_IP or 174 $HAVE_IO_SOCKET_IP = defined eval { require IO::Socket::IP }; 175 176 croak "Cannot create a new socket without a family" unless $family; 177 # PF_UNSPEC and undef are both false 178 $family = $self->getfamilybyname( $family ) || AF_UNIX; 179 180 # SOCK_STREAM is the most likely 181 $socktype = $self->getsocktypebyname( $socktype ) || SOCK_STREAM; 182 183 defined $proto or $proto = 0; 184 185 if( $HAVE_IO_SOCKET_IP and ( $family == AF_INET || $family == AF_INET6() ) ) { 186 return IO::Socket::IP->new->socket( $family, $socktype, $proto ); 187 } 188 189 my $sock = eval { 190 IO::Socket->new( 191 Domain => $family, 192 Type => $socktype, 193 Proto => $proto, 194 ); 195 }; 196 return $sock if $sock; 197 198 # That failed. Most likely because the Domain was unrecognised. This 199 # usually happens if getaddrinfo returns an AF_INET6 address but we don't 200 # have a suitable class loaded. In this case we'll return a generic one. 201 # It won't be in the specific subclass but that's the best we can do. And 202 # it will still work as a generic socket. 203 return IO::Socket->new->socket( $family, $socktype, $proto ); 204} 205 206=head2 socketpair 207 208 ( $S1, $S2 ) = IO::Async::OS->socketpair( $family, $socktype, $proto ) 209 210An abstraction of the C<socketpair(2)> syscall, where any argument may be 211missing (or given as C<undef>). 212 213If C<$family> is not provided, a suitable value will be provided by the OS 214(likely C<AF_UNIX> on POSIX-based platforms). If C<$socktype> is not provided, 215then C<SOCK_STREAM> will be used. 216 217Additionally, this method supports building connected C<SOCK_STREAM> or 218C<SOCK_DGRAM> pairs in the C<AF_INET> family even if the underlying platform's 219C<socketpair(2)> does not, by connecting two normal sockets together. 220 221C<$family> and C<$socktype> may also be given symbolically as defined by 222C<getfamilybyname> and C<getsocktypebyname>. 223 224=cut 225 226sub socketpair 227{ 228 my $self = shift; 229 my ( $family, $socktype, $proto ) = @_; 230 231 require IO::Socket; 232 233 # PF_UNSPEC and undef are both false 234 $family = $self->getfamilybyname( $family ) || AF_UNIX; 235 236 # SOCK_STREAM is the most likely 237 $socktype = $self->getsocktypebyname( $socktype ) || SOCK_STREAM; 238 239 $proto ||= 0; 240 241 my ( $S1, $S2 ) = IO::Socket->new->socketpair( $family, $socktype, $proto ); 242 return ( $S1, $S2 ) if defined $S1; 243 244 return unless $family == AF_INET and ( $socktype == SOCK_STREAM or $socktype == SOCK_DGRAM ); 245 246 # Now lets emulate an AF_INET socketpair call 247 248 my $Stmp = IO::Async::OS->socket( $family, $socktype ) or return; 249 $Stmp->bind( pack_sockaddr_in( 0, INADDR_LOOPBACK ) ) or return; 250 251 $S1 = IO::Async::OS->socket( $family, $socktype ) or return; 252 253 if( $socktype == SOCK_STREAM ) { 254 $Stmp->listen( 1 ) or return; 255 $S1->connect( getsockname $Stmp ) or return; 256 $S2 = $Stmp->accept or return; 257 258 # There's a bug in IO::Socket here, in that $S2 's ->socktype won't 259 # yet be set. We can apply a horribly hacky fix here 260 # defined $S2->socktype and $S2->socktype == $socktype or 261 # ${*$S2}{io_socket_type} = $socktype; 262 # But for now we'll skip the test for it instead 263 } 264 else { 265 $S2 = $Stmp; 266 $S1->connect( getsockname $S2 ) or return; 267 $S2->connect( getsockname $S1 ) or return; 268 } 269 270 return ( $S1, $S2 ); 271} 272 273=head2 pipepair 274 275 ( $rd, $wr ) = IO::Async::OS->pipepair 276 277An abstraction of the C<pipe(2)> syscall, which returns the two new handles. 278 279=cut 280 281sub pipepair 282{ 283 my $self = shift; 284 285 pipe( my ( $rd, $wr ) ) or return; 286 return ( $rd, $wr ); 287} 288 289=head2 pipequad 290 291 ( $rdA, $wrA, $rdB, $wrB ) = IO::Async::OS->pipequad 292 293This method is intended for creating two pairs of filehandles that are linked 294together, suitable for passing as the STDIN/STDOUT pair to a child process. 295After this function returns, C<$rdA> and C<$wrA> will be a linked pair, as 296will C<$rdB> and C<$wrB>. 297 298On platforms that support C<socketpair(2)>, this implementation will be 299preferred, in which case C<$rdA> and C<$wrB> will actually be the same 300filehandle, as will C<$rdB> and C<$wrA>. This saves a file descriptor in the 301parent process. 302 303When creating a L<IO::Async::Stream> or subclass of it, the C<read_handle> 304and C<write_handle> parameters should always be used. 305 306 my ( $childRd, $myWr, $myRd, $childWr ) = IO::Async::OS->pipequad; 307 308 $loop->open_process( 309 stdin => $childRd, 310 stdout => $childWr, 311 ... 312 ); 313 314 my $str = IO::Async::Stream->new( 315 read_handle => $myRd, 316 write_handle => $myWr, 317 ... 318 ); 319 $loop->add( $str ); 320 321=cut 322 323sub pipequad 324{ 325 my $self = shift; 326 327 # Prefer socketpair 328 if( my ( $S1, $S2 ) = $self->socketpair ) { 329 return ( $S1, $S2, $S2, $S1 ); 330 } 331 332 # Can't do that, fallback on pipes 333 my ( $rdA, $wrA ) = $self->pipepair or return; 334 my ( $rdB, $wrB ) = $self->pipepair or return; 335 336 return ( $rdA, $wrA, $rdB, $wrB ); 337} 338 339=head2 signame2num 340 341 $signum = IO::Async::OS->signame2num( $signame ) 342 343This utility method converts a signal name (such as "TERM") into its system- 344specific signal number. This may be useful to pass to C<POSIX::SigSet> or use 345in other places which use numbers instead of symbolic names. 346 347=head2 signum2name 348 349 $signame = IO::Async::OS->signum2name( $signum ) 350 351The inverse of L<signame2num>; this method convers signal numbers into 352readable names. 353 354=cut 355 356my %sig_name2num; 357my %sig_num2name; 358 359sub _init_signum 360{ 361 my $self = shift; 362 363 require Config; 364 365 $Config::Config{sig_name} and $Config::Config{sig_num} or 366 die "No signals found"; 367 368 my @names = split ' ', $Config::Config{sig_name}; 369 my @nums = split ' ', $Config::Config{sig_num}; 370 371 @sig_name2num{ @names } = @nums; 372 @sig_num2name{ @nums } = @names; 373} 374 375sub signame2num 376{ 377 my $self = shift; 378 my ( $signame ) = @_; 379 380 %sig_name2num or $self->_init_signum; 381 382 return $sig_name2num{$signame}; 383} 384 385sub signum2name 386{ 387 my $self = shift; 388 my ( $signum ) = @_; 389 390 %sig_num2name or $self->_init_signum; 391 392 return $sig_num2name{$signum}; 393} 394 395=head2 extract_addrinfo 396 397 ( $family, $socktype, $protocol, $addr ) = IO::Async::OS->extract_addrinfo( $ai ) 398 399Given an ARRAY or HASH reference value containing an addrinfo, returns a 400family, socktype and protocol argument suitable for a C<socket> call and an 401address suitable for C<connect> or C<bind>. 402 403If given an ARRAY it should be in the following form: 404 405 [ $family, $socktype, $protocol, $addr ] 406 407If given a HASH it should contain the following keys: 408 409 family socktype protocol addr 410 411Each field in the result will be initialised to 0 (or empty string for the 412address) if not defined in the C<$ai> value. 413 414The family type may also be given as a symbolic string as defined by 415C<getfamilybyname>. 416 417The socktype may also be given as a symbolic string; C<stream>, C<dgram> or 418C<raw>; this will be converted to the appropriate C<SOCK_*> constant. 419 420Note that the C<addr> field, if provided, must be a packed socket address, 421such as returned by C<pack_sockaddr_in> or C<pack_sockaddr_un>. 422 423If the HASH form is used, rather than passing a packed socket address in the 424C<addr> field, certain other hash keys may be used instead for convenience on 425certain named families. 426 427=over 4 428 429=cut 430 431use constant ADDRINFO_FAMILY => 0; 432use constant ADDRINFO_SOCKTYPE => 1; 433use constant ADDRINFO_PROTOCOL => 2; 434use constant ADDRINFO_ADDR => 3; 435 436sub extract_addrinfo 437{ 438 my $self = shift; 439 my ( $ai, $argname ) = @_; 440 441 $argname ||= "addr"; 442 443 my @ai; 444 445 if( ref $ai eq "ARRAY" ) { 446 @ai = @$ai; 447 } 448 elsif( ref $ai eq "HASH" ) { 449 $ai = { %$ai }; # copy so we can delete from it 450 @ai = delete @{$ai}{qw( family socktype protocol addr )}; 451 452 if( defined $ai[ADDRINFO_FAMILY] and !defined $ai[ADDRINFO_ADDR] ) { 453 my $family = $ai[ADDRINFO_FAMILY]; 454 my $method = "_extract_addrinfo_$family"; 455 my $code = $self->can( $method ) or croak "Cannot determine addr for extract_addrinfo on family='$family'"; 456 457 $ai[ADDRINFO_ADDR] = $code->( $self, $ai ); 458 459 keys %$ai and croak "Unrecognised '$family' addrinfo keys: " . join( ", ", keys %$ai ); 460 } 461 } 462 else { 463 croak "Expected '$argname' to be an ARRAY or HASH reference"; 464 } 465 466 $ai[ADDRINFO_FAMILY] = $self->getfamilybyname( $ai[ADDRINFO_FAMILY] ); 467 $ai[ADDRINFO_SOCKTYPE] = $self->getsocktypebyname( $ai[ADDRINFO_SOCKTYPE] ); 468 469 # Make sure all fields are defined 470 $ai[$_] ||= 0 for ADDRINFO_FAMILY, ADDRINFO_SOCKTYPE, ADDRINFO_PROTOCOL; 471 $ai[ADDRINFO_ADDR] = "" if !defined $ai[ADDRINFO_ADDR]; 472 473 return @ai; 474} 475 476=item family => 'inet' 477 478Will pack an IP address and port number from keys called C<ip> and C<port>. 479If C<ip> is missing it will be set to "0.0.0.0". If C<port> is missing it will 480be set to 0. 481 482=cut 483 484sub _extract_addrinfo_inet 485{ 486 my $self = shift; 487 my ( $ai ) = @_; 488 489 my $port = delete $ai->{port} || 0; 490 my $ip = delete $ai->{ip} || "0.0.0.0"; 491 492 return pack_sockaddr_in( $port, inet_aton( $ip ) ); 493} 494 495=item family => 'inet6' 496 497Will pack an IP address and port number from keys called C<ip> and C<port>. 498If C<ip> is missing it will be set to "::". If C<port> is missing it will be 499set to 0. Optionally will also include values from C<scopeid> and C<flowinfo> 500keys if provided. 501 502This will only work if a C<pack_sockaddr_in6> function can be found in 503C<Socket> 504 505=cut 506 507sub _extract_addrinfo_inet6 508{ 509 my $self = shift; 510 my ( $ai ) = @_; 511 512 my $port = delete $ai->{port} || 0; 513 my $ip = delete $ai->{ip} || "::"; 514 my $scopeid = delete $ai->{scopeid} || 0; 515 my $flowinfo = delete $ai->{flowinfo} || 0; 516 517 if( HAVE_SOCKADDR_IN6 ) { 518 return pack_sockaddr_in6( $port, inet_pton( AF_INET6, $ip ), $scopeid, $flowinfo ); 519 } 520 else { 521 croak "Cannot pack_sockaddr_in6"; 522 } 523} 524 525=item family => 'unix' 526 527Will pack a UNIX socket path from a key called C<path>. 528 529=cut 530 531sub _extract_addrinfo_unix 532{ 533 my $self = shift; 534 my ( $ai ) = @_; 535 536 defined( my $path = delete $ai->{path} ) or croak "Expected 'path' for extract_addrinfo on family='unix'"; 537 538 return pack_sockaddr_un( $path ); 539} 540 541=pod 542 543=back 544 545=cut 546 547=head2 make_addr_for_peer 548 549 $connectaddr = IO::Async::OS->make_addr_for_peer( $family, $listenaddr ) 550 551Given the C<sockdomain> and C<sockname> of a listening socket. creates an 552address suitable to C<connect()> to it. 553 554This method will handle specially any C<AF_INET> address bound to 555C<INADDR_ANY> or any C<AF_INET6> address bound to C<IN6ADDR_ANY>, as some OSes 556do not allow C<connect(2)>ing to those and would instead insist on receiving 557C<INADDR_LOOPBACK> or C<IN6ADDR_LOOPBACK> respectively. 558 559This method is used by the C<< ->connect( peer => $sock ) >> parameter of 560handle and loop connect methods. 561 562=cut 563 564sub make_addr_for_peer 565{ 566 shift; 567 my ( $p_family, $p_addr ) = @_; 568 569 if( $p_family == Socket::AF_INET ) { 570 my @params = Socket::unpack_sockaddr_in $p_addr; 571 $params[1] = Socket::INADDR_LOOPBACK if $params[1] eq Socket::INADDR_ANY; 572 return Socket::pack_sockaddr_in @params; 573 } 574 if( HAVE_SOCKADDR_IN6 and $p_family == Socket::AF_INET6 ) { 575 my @params = Socket::unpack_sockaddr_in6 $p_addr; 576 $params[1] = Socket::IN6ADDR_LOOPBACK if $params[1] eq Socket::IN6ADDR_ANY; 577 return Socket::pack_sockaddr_in6 @params; 578 } 579 580 # Most other cases should be fine 581 return $p_addr; 582} 583 584=head1 LOOP IMPLEMENTATION METHODS 585 586The following methods are provided on C<IO::Async::OS> because they are likely 587to require OS-specific implementations, but are used by L<IO::Async::Loop> to 588implement its functionality. It can use the HASH reference C<< $loop->{os} >> 589to store other data it requires. 590 591=cut 592 593=head2 loop_watch_signal 594 595=head2 loop_unwatch_signal 596 597 IO::Async::OS->loop_watch_signal( $loop, $signal, $code ) 598 599 IO::Async::OS->loop_unwatch_signal( $loop, $signal ) 600 601Used to implement the C<watch_signal> / C<unwatch_signal> Loop pair. 602 603=cut 604 605sub _setup_sigpipe 606{ 607 my $self = shift; 608 my ( $loop ) = @_; 609 610 require IO::Async::Handle; 611 612 my ( $reader, $sigpipe ) = $self->pipepair or croak "Cannot pipe() - $!"; 613 $_->blocking( 0 ) for $reader, $sigpipe; 614 615 $loop->{os}{sigpipe} = $sigpipe; 616 617 my $sigwatch = $loop->{os}{sigwatch}; 618 619 $loop->add( $loop->{os}{sigpipe_reader} = IO::Async::Handle->new( 620 notifier_name => "sigpipe", 621 read_handle => $reader, 622 on_read_ready => sub { 623 sysread $reader, my $buffer, 8192 or return; 624 foreach my $signum ( unpack "I*", $buffer ) { 625 $sigwatch->{$signum}->() if $sigwatch->{$signum}; 626 } 627 }, 628 ) ); 629 630 return $sigpipe; 631} 632 633sub loop_watch_signal 634{ 635 my $self = shift; 636 my ( $loop, $signal, $code ) = @_; 637 638 exists $SIG{$signal} or croak "Unrecognised signal name $signal"; 639 ref $code or croak 'Expected $code as a reference'; 640 641 my $signum = $self->signame2num( $signal ); 642 my $sigwatch = $loop->{os}{sigwatch} ||= {}; # {$num} = $code 643 644 my $sigpipe = $loop->{os}{sigpipe} // $self->_setup_sigpipe( $loop ); 645 646 my $signum_str = pack "I", $signum; 647 $SIG{$signal} = sub { syswrite $sigpipe, $signum_str }; 648 649 $sigwatch->{$signum} = $code; 650} 651 652sub loop_unwatch_signal 653{ 654 my $self = shift; 655 my ( $loop, $signal ) = @_; 656 657 my $signum = $self->signame2num( $signal ); 658 my $sigwatch = $loop->{os}{sigwatch} or return; 659 660 delete $sigwatch->{$signum}; 661 undef $SIG{$signal}; 662} 663 664=head2 potentially_open_fds 665 666 @fds = IO::Async::OS->potentially_open_fds 667 668Returns a list of filedescriptors which might need closing. By default this 669will return C<0 .. _SC_OPEN_MAX>. OS-specific subclasses may have a better 670guess. 671 672=cut 673 674sub potentially_open_fds 675{ 676 return 0 .. OPEN_MAX_FD; 677} 678 679sub post_fork 680{ 681 my $self = shift; 682 my ( $loop ) = @_; 683 684 if( $loop->{os}{sigpipe} ) { 685 $loop->remove( $loop->{os}{sigpipe_reader} ); 686 undef $loop->{os}{sigpipe}; 687 688 my $sigwatch = $loop->{os}{sigwatch}; 689 690 foreach my $signal ( keys %SIG ) { 691 my $signum = $self->signame2num( $signal ) or next; 692 my $code = $sigwatch->{$signum} or next; 693 694 $self->loop_watch_signal( $loop, $signal, $code ); 695 } 696 } 697} 698 699=head1 AUTHOR 700 701Paul Evans <leonerd@leonerd.org.uk> 702 703=cut 704 7050x55AA; 706