15759b3d2Safresh1package Test2::IPC::Driver; 25759b3d2Safresh1use strict; 35759b3d2Safresh1use warnings; 45759b3d2Safresh1 5*5486feefSafresh1our $VERSION = '1.302199'; 65759b3d2Safresh1 75759b3d2Safresh1 85759b3d2Safresh1use Carp qw/confess/; 95759b3d2Safresh1use Test2::Util::HashBase qw{no_fatal no_bail}; 105759b3d2Safresh1 115759b3d2Safresh1use Test2::API qw/test2_ipc_add_driver/; 125759b3d2Safresh1 135759b3d2Safresh1my %ADDED; 145759b3d2Safresh1sub import { 155759b3d2Safresh1 my $class = shift; 165759b3d2Safresh1 return if $class eq __PACKAGE__; 175759b3d2Safresh1 return if $ADDED{$class}++; 185759b3d2Safresh1 test2_ipc_add_driver($class); 195759b3d2Safresh1} 205759b3d2Safresh1 21f3efcd01Safresh1sub pending { -1 } 22f3efcd01Safresh1sub set_pending { -1 } 235759b3d2Safresh1 245759b3d2Safresh1for my $meth (qw/send cull add_hub drop_hub waiting is_viable/) { 255759b3d2Safresh1 no strict 'refs'; 265759b3d2Safresh1 *$meth = sub { 275759b3d2Safresh1 my $thing = shift; 285759b3d2Safresh1 confess "'$thing' did not define the required method '$meth'." 295759b3d2Safresh1 }; 305759b3d2Safresh1} 315759b3d2Safresh1 325759b3d2Safresh1# Print the error and call exit. We are not using 'die' cause this is a 335759b3d2Safresh1# catastrophic error that should never be caught. If we get here it 345759b3d2Safresh1# means some serious shit has happened in a child process, the only way 355759b3d2Safresh1# to inform the parent may be to exit false. 365759b3d2Safresh1 375759b3d2Safresh1sub abort { 385759b3d2Safresh1 my $self = shift; 395759b3d2Safresh1 chomp(my ($msg) = @_); 405759b3d2Safresh1 415759b3d2Safresh1 $self->driver_abort($msg) if $self->can('driver_abort'); 425759b3d2Safresh1 435759b3d2Safresh1 print STDERR "IPC Fatal Error: $msg\n"; 445759b3d2Safresh1 print STDOUT "Bail out! IPC Fatal Error: $msg\n" unless $self->no_bail; 455759b3d2Safresh1 465759b3d2Safresh1 CORE::exit(255) unless $self->no_fatal; 475759b3d2Safresh1} 485759b3d2Safresh1 495759b3d2Safresh1sub abort_trace { 505759b3d2Safresh1 my $self = shift; 515759b3d2Safresh1 my ($msg) = @_; 525759b3d2Safresh1 # Older versions of Carp do not export longmess() function, so it needs to be called with package name 535759b3d2Safresh1 $self->abort(Carp::longmess($msg)); 545759b3d2Safresh1} 555759b3d2Safresh1 565759b3d2Safresh11; 575759b3d2Safresh1 585759b3d2Safresh1__END__ 595759b3d2Safresh1 605759b3d2Safresh1=pod 615759b3d2Safresh1 625759b3d2Safresh1=encoding UTF-8 635759b3d2Safresh1 645759b3d2Safresh1=head1 NAME 655759b3d2Safresh1 665759b3d2Safresh1Test2::IPC::Driver - Base class for Test2 IPC drivers. 675759b3d2Safresh1 685759b3d2Safresh1=head1 SYNOPSIS 695759b3d2Safresh1 705759b3d2Safresh1 package Test2::IPC::Driver::MyDriver; 715759b3d2Safresh1 725759b3d2Safresh1 use base 'Test2::IPC::Driver'; 735759b3d2Safresh1 745759b3d2Safresh1 ... 755759b3d2Safresh1 765759b3d2Safresh1=head1 METHODS 775759b3d2Safresh1 785759b3d2Safresh1=over 4 795759b3d2Safresh1 805759b3d2Safresh1=item $self->abort($msg) 815759b3d2Safresh1 825759b3d2Safresh1If an IPC encounters a fatal error it should use this. This will print the 835759b3d2Safresh1message to STDERR with C<'IPC Fatal Error: '> prefixed to it, then it will 845759b3d2Safresh1forcefully exit 255. IPC errors may occur in threads or processes other than 855759b3d2Safresh1the main one, this method provides the best chance of the harness noticing the 865759b3d2Safresh1error. 875759b3d2Safresh1 885759b3d2Safresh1=item $self->abort_trace($msg) 895759b3d2Safresh1 905759b3d2Safresh1This is the same as C<< $ipc->abort($msg) >> except that it uses 915759b3d2Safresh1C<Carp::longmess> to add a stack trace to the message. 925759b3d2Safresh1 935759b3d2Safresh1=back 945759b3d2Safresh1 955759b3d2Safresh1=head1 LOADING DRIVERS 965759b3d2Safresh1 975759b3d2Safresh1Test2::IPC::Driver has an C<import()> method. All drivers inherit this import 985759b3d2Safresh1method. This import method registers the driver. 995759b3d2Safresh1 1005759b3d2Safresh1In most cases you just need to load the desired IPC driver to make it work. You 1015759b3d2Safresh1should load this driver as early as possible. A warning will be issued if you 1025759b3d2Safresh1load it too late for it to be effective. 1035759b3d2Safresh1 1045759b3d2Safresh1 use Test2::IPC::Driver::MyDriver; 1055759b3d2Safresh1 ... 1065759b3d2Safresh1 1075759b3d2Safresh1=head1 WRITING DRIVERS 1085759b3d2Safresh1 1095759b3d2Safresh1 package Test2::IPC::Driver::MyDriver; 1105759b3d2Safresh1 use strict; 1115759b3d2Safresh1 use warnings; 1125759b3d2Safresh1 1135759b3d2Safresh1 use base 'Test2::IPC::Driver'; 1145759b3d2Safresh1 1155759b3d2Safresh1 sub is_viable { 1165759b3d2Safresh1 return 0 if $^O eq 'win32'; # Will not work on windows. 1175759b3d2Safresh1 return 1; 1185759b3d2Safresh1 } 1195759b3d2Safresh1 1205759b3d2Safresh1 sub add_hub { 1215759b3d2Safresh1 my $self = shift; 1225759b3d2Safresh1 my ($hid) = @_; 1235759b3d2Safresh1 1245759b3d2Safresh1 ... # Make it possible to contact the hub 1255759b3d2Safresh1 } 1265759b3d2Safresh1 1275759b3d2Safresh1 sub drop_hub { 1285759b3d2Safresh1 my $self = shift; 1295759b3d2Safresh1 my ($hid) = @_; 1305759b3d2Safresh1 1315759b3d2Safresh1 ... # Nothing should try to reach the hub anymore. 1325759b3d2Safresh1 } 1335759b3d2Safresh1 1345759b3d2Safresh1 sub send { 1355759b3d2Safresh1 my $self = shift; 1365759b3d2Safresh1 my ($hid, $e, $global) = @_; 1375759b3d2Safresh1 1385759b3d2Safresh1 ... # Send the event to the proper hub. 1395759b3d2Safresh1 140f3efcd01Safresh1 # This may notify other procs/threads that there is a pending event. 1415759b3d2Safresh1 Test2::API::test2_ipc_set_pending($uniq_val); 1425759b3d2Safresh1 } 1435759b3d2Safresh1 1445759b3d2Safresh1 sub cull { 1455759b3d2Safresh1 my $self = shift; 1465759b3d2Safresh1 my ($hid) = @_; 1475759b3d2Safresh1 1485759b3d2Safresh1 my @events = ...; # Here is where you get the events for the hub 1495759b3d2Safresh1 1505759b3d2Safresh1 return @events; 1515759b3d2Safresh1 } 1525759b3d2Safresh1 1535759b3d2Safresh1 sub waiting { 1545759b3d2Safresh1 my $self = shift; 1555759b3d2Safresh1 1565759b3d2Safresh1 ... # Notify all listening procs and threads that the main 1575759b3d2Safresh1 ... # process/thread is waiting for them to finish. 1585759b3d2Safresh1 } 1595759b3d2Safresh1 1605759b3d2Safresh1 1; 1615759b3d2Safresh1 1625759b3d2Safresh1=head2 METHODS SUBCLASSES MUST IMPLEMENT 1635759b3d2Safresh1 1645759b3d2Safresh1=over 4 1655759b3d2Safresh1 1665759b3d2Safresh1=item $ipc->is_viable 1675759b3d2Safresh1 1685759b3d2Safresh1This should return true if the driver works in the current environment. This 1695759b3d2Safresh1should return false if it does not. This is a CLASS method. 1705759b3d2Safresh1 1715759b3d2Safresh1=item $ipc->add_hub($hid) 1725759b3d2Safresh1 1735759b3d2Safresh1This is used to alert the driver that a new hub is expecting events. The driver 1745759b3d2Safresh1should keep track of the process and thread ids, the hub should only be dropped 1755759b3d2Safresh1by the proc+thread that started it. 1765759b3d2Safresh1 1775759b3d2Safresh1 sub add_hub { 1785759b3d2Safresh1 my $self = shift; 1795759b3d2Safresh1 my ($hid) = @_; 1805759b3d2Safresh1 1815759b3d2Safresh1 ... # Make it possible to contact the hub 1825759b3d2Safresh1 } 1835759b3d2Safresh1 1845759b3d2Safresh1=item $ipc->drop_hub($hid) 1855759b3d2Safresh1 1865759b3d2Safresh1This is used to alert the driver that a hub is no longer accepting events. The 1875759b3d2Safresh1driver should keep track of the process and thread ids, the hub should only be 1885759b3d2Safresh1dropped by the proc+thread that started it (This is the drivers responsibility 1895759b3d2Safresh1to enforce). 1905759b3d2Safresh1 1915759b3d2Safresh1 sub drop_hub { 1925759b3d2Safresh1 my $self = shift; 1935759b3d2Safresh1 my ($hid) = @_; 1945759b3d2Safresh1 1955759b3d2Safresh1 ... # Nothing should try to reach the hub anymore. 1965759b3d2Safresh1 } 1975759b3d2Safresh1 1985759b3d2Safresh1=item $ipc->send($hid, $event); 1995759b3d2Safresh1 2005759b3d2Safresh1=item $ipc->send($hid, $event, $global); 2015759b3d2Safresh1 2025759b3d2Safresh1Used to send events from the current process/thread to the specified hub in its 2035759b3d2Safresh1process+thread. 2045759b3d2Safresh1 2055759b3d2Safresh1 sub send { 2065759b3d2Safresh1 my $self = shift; 2075759b3d2Safresh1 my ($hid, $e) = @_; 2085759b3d2Safresh1 2095759b3d2Safresh1 ... # Send the event to the proper hub. 2105759b3d2Safresh1 211f3efcd01Safresh1 # This may notify other procs/threads that there is a pending event. 2125759b3d2Safresh1 Test2::API::test2_ipc_set_pending($uniq_val); 2135759b3d2Safresh1 } 2145759b3d2Safresh1 2155759b3d2Safresh1If C<$global> is true then the driver should send the event to all hubs in all 2165759b3d2Safresh1processes and threads. 2175759b3d2Safresh1 2185759b3d2Safresh1=item @events = $ipc->cull($hid) 2195759b3d2Safresh1 2205759b3d2Safresh1Used to collect events that have been sent to the specified hub. 2215759b3d2Safresh1 2225759b3d2Safresh1 sub cull { 2235759b3d2Safresh1 my $self = shift; 2245759b3d2Safresh1 my ($hid) = @_; 2255759b3d2Safresh1 2265759b3d2Safresh1 my @events = ...; # Here is where you get the events for the hub 2275759b3d2Safresh1 2285759b3d2Safresh1 return @events; 2295759b3d2Safresh1 } 2305759b3d2Safresh1 2315759b3d2Safresh1=item $ipc->waiting() 2325759b3d2Safresh1 2335759b3d2Safresh1This is called in the parent process when it is complete and waiting for all 2345759b3d2Safresh1child processes and threads to complete. 2355759b3d2Safresh1 2365759b3d2Safresh1 sub waiting { 2375759b3d2Safresh1 my $self = shift; 2385759b3d2Safresh1 2395759b3d2Safresh1 ... # Notify all listening procs and threads that the main 2405759b3d2Safresh1 ... # process/thread is waiting for them to finish. 2415759b3d2Safresh1 } 2425759b3d2Safresh1 2435759b3d2Safresh1=back 2445759b3d2Safresh1 2455759b3d2Safresh1=head2 METHODS SUBCLASSES MAY IMPLEMENT OR OVERRIDE 2465759b3d2Safresh1 2475759b3d2Safresh1=over 4 2485759b3d2Safresh1 2495759b3d2Safresh1=item $ipc->driver_abort($msg) 2505759b3d2Safresh1 2515759b3d2Safresh1This is a hook called by C<< Test2::IPC::Driver->abort() >>. This is your 2525759b3d2Safresh1chance to cleanup when an abort happens. You cannot prevent the abort, but you 2535759b3d2Safresh1can gracefully except it. 2545759b3d2Safresh1 2555759b3d2Safresh1=back 2565759b3d2Safresh1 2575759b3d2Safresh1=head1 SOURCE 2585759b3d2Safresh1 2595759b3d2Safresh1The source code repository for Test2 can be found at 260*5486feefSafresh1L<https://github.com/Test-More/test-more/>. 2615759b3d2Safresh1 2625759b3d2Safresh1=head1 MAINTAINERS 2635759b3d2Safresh1 2645759b3d2Safresh1=over 4 2655759b3d2Safresh1 2665759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt> 2675759b3d2Safresh1 2685759b3d2Safresh1=back 2695759b3d2Safresh1 2705759b3d2Safresh1=head1 AUTHORS 2715759b3d2Safresh1 2725759b3d2Safresh1=over 4 2735759b3d2Safresh1 2745759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt> 2755759b3d2Safresh1 2765759b3d2Safresh1=back 2775759b3d2Safresh1 2785759b3d2Safresh1=head1 COPYRIGHT 2795759b3d2Safresh1 280256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>. 2815759b3d2Safresh1 2825759b3d2Safresh1This program is free software; you can redistribute it and/or 2835759b3d2Safresh1modify it under the same terms as Perl itself. 2845759b3d2Safresh1 285*5486feefSafresh1See L<https://dev.perl.org/licenses/> 2865759b3d2Safresh1 2875759b3d2Safresh1=cut 288