From: Tim Beale Date: Thu, 23 May 2019 04:35:07 +0000 (+1200) Subject: selftest: Add common fork_and_exec() function X-Git-Tag: ldb-2.0.5~644 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b976502d496cca0e8e04a2e5f2c72383efb296a7;p=thirdparty%2Fsamba.git selftest: Add common fork_and_exec() function Now the code has been refactored, we can move it into a common function. This reduces code duplication and means we have a common place where we start samba daemons from. Note that some daemons behave slightly different, but the $daemon_ctx allows us to customize their behaviour a bit. Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett --- diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index 5a359fe6970..6fd8d01da06 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -620,6 +620,66 @@ sub get_env_for_process return $proc_envs; } +sub fork_and_exec +{ + my ($self, $env_vars, $daemon_ctx, $STDIN_READER) = @_; + + unlink($daemon_ctx->{LOG_FILE}); + print "STARTING $daemon_ctx->{NAME} for $ENV{ENVNAME}..."; + + my $pid = fork(); + + # exec the daemon in the child process + if ($pid == 0) { + # redirect the daemon's stdout/stderr to a log file + if (defined($daemon_ctx->{TEE_STDOUT})) { + # in some cases, we want out from samba to go to the log file, + # but also to the users terminal when running 'make test' on the + # command line. This puts it on stderr on the terminal + open STDOUT, "| tee $daemon_ctx->{LOG_FILE} 1>&2"; + } else { + open STDOUT, ">$daemon_ctx->{LOG_FILE}"; + } + open STDERR, '>&STDOUT'; + + SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE}); + if (defined($daemon_ctx->{PCAP_FILE})) { + SocketWrapper::setup_pcap($daemon_ctx->{PCAP_FILE}); + } + + # setup ENV variables in the child process + set_env_for_process($daemon_ctx->{NAME}, $env_vars, + $daemon_ctx->{ENV_VARS}); + + # not all s3 daemons run in all testenvs (e.g. fileserver doesn't + # run winbindd). In which case, the child process just sleeps + if (defined($daemon_ctx->{SKIP_DAEMON})) { + $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { + my $signame = shift; + print("Skip $daemon_ctx->{NAME} received signal $signame"); + exit 0; + }; + sleep($self->{server_maxtime}); + exit 0; + } + + $ENV{MAKE_TEST_BINARY} = $daemon_ctx->{BINARY_PATH}; + + # we close the child's write-end of the pipe and redirect the read-end + # to its stdin. That way the daemon will receive an EOF on stdin when + # parent selftest process closes its write-end. + close($env_vars->{STDIN_PIPE}); + open STDIN, ">&", $STDIN_READER or die "can't dup STDIN_READER to STDIN: $!"; + + # the command args are stored as an array reference (because...Perl), + # so convert the reference back to an array + my @full_cmd = @{ $daemon_ctx->{FULL_CMD} }; + exec(@full_cmd) or die("Unable to start $ENV{MAKE_TEST_BINARY}: $!"); + } + print "DONE ($pid)\n"; + return $pid; +} + my @exported_envvars = ( # domain stuff "DOMAIN", diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index d165588b325..4abd5177cba 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1260,11 +1260,12 @@ sub make_bin_cmd sub check_or_start($$$$$) { my ($self, $env_vars, $nmbd, $winbindd, $smbd) = @_; + my $STDIN_READER; # use a pipe for stdin in the child processes. This allows # those processes to monitor the pipe for EOF to ensure they # exit when the test script exits - pipe(STDIN_READER, $env_vars->{STDIN_PIPE}); + pipe($STDIN_READER, $env_vars->{STDIN_PIPE}); my $binary = Samba::bindir_path($self, "nmbd"); my @full_cmd = $self->make_bin_cmd($binary, $env_vars, @@ -1273,6 +1274,8 @@ sub check_or_start($$$$$) { my $nmbd_envs = Samba::get_env_for_process("nmbd", $env_vars); delete $nmbd_envs->{RESOLV_WRAPPER_CONF}; delete $nmbd_envs->{RESOLV_WRAPPER_HOSTS}; + + # fork and exec() nmbd in the child process my %daemon_ctx = ( NAME => "nmbd", BINARY_PATH => $binary, @@ -1283,39 +1286,10 @@ sub check_or_start($$$$$) { if ($nmbd ne "yes") { $daemon_ctx{SKIP_DAEMON} = 1; } + my $pid = Samba::fork_and_exec($self, $env_vars, \%daemon_ctx, $STDIN_READER); - unlink($daemon_ctx{LOG_FILE}); - print "STARTING NMBD..."; - my $pid = fork(); - if ($pid == 0) { - open STDOUT, ">$daemon_ctx{LOG_FILE}"; - open STDERR, '>&STDOUT'; - - SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE}); - - Samba::set_env_for_process($daemon_ctx{NAME}, $env_vars, $daemon_ctx{ENV_VARS}); - - if (defined($daemon_ctx{SKIP_DAEMON})) { - $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { - my $signame = shift; - print("Skip $daemon_ctx{NAME} received signal $signame"); - exit 0; - }; - sleep($self->{server_maxtime}); - exit 0; - } - - $ENV{MAKE_TEST_BINARY} = $daemon_ctx{BINARY_PATH}; - - close($env_vars->{STDIN_PIPE}); - open STDIN, ">&", \*STDIN_READER or die "can't dup STDIN_READER to STDIN: $!"; - - exec(@{ $daemon_ctx{FULL_CMD} }) - or die("Unable to start $ENV{MAKE_TEST_BINARY}: $!"); - } $env_vars->{NMBD_TL_PID} = $pid; write_pid($env_vars, "nmbd", $pid); - print "DONE\n"; $binary = Samba::bindir_path($self, "winbindd"); @full_cmd = $self->make_bin_cmd($binary, $env_vars, @@ -1324,6 +1298,8 @@ sub check_or_start($$$$$) { if (not defined($ENV{WINBINDD_DONT_LOG_STDOUT})) { push(@full_cmd, "--stdout"); } + + # fork and exec() winbindd in the child process %daemon_ctx = ( NAME => "winbindd", BINARY_PATH => $binary, @@ -1333,44 +1309,17 @@ sub check_or_start($$$$$) { if ($winbindd ne "yes") { $daemon_ctx{SKIP_DAEMON} = 1; } + my $pid = Samba::fork_and_exec($self, $env_vars, \%daemon_ctx, $STDIN_READER); - unlink($daemon_ctx{LOG_FILE}); - print "STARTING WINBINDD..."; - $pid = fork(); - if ($pid == 0) { - open STDOUT, ">$daemon_ctx{LOG_FILE}"; - open STDERR, '>&STDOUT'; - - SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE}); - - Samba::set_env_for_process($daemon_ctx{NAME}, $env_vars, $daemon_ctx{ENV_VARS}); - - if (defined($daemon_ctx{SKIP_DAEMON})) { - $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { - my $signame = shift; - print("Skip $daemon_ctx{NAME} received signal $signame"); - exit 0; - }; - sleep($self->{server_maxtime}); - exit 0; - } - - $ENV{MAKE_TEST_BINARY} = $daemon_ctx{BINARY_PATH}; - - close($env_vars->{STDIN_PIPE}); - open STDIN, ">&", \*STDIN_READER or die "can't dup STDIN_READER to STDIN: $!"; - - exec(@{ $daemon_ctx{FULL_CMD} }) - or die("Unable to start $ENV{MAKE_TEST_BINARY}: $!"); - } $env_vars->{WINBINDD_TL_PID} = $pid; write_pid($env_vars, "winbindd", $pid); - print "DONE\n"; $binary = Samba::bindir_path($self, "smbd"); @full_cmd = $self->make_bin_cmd($binary, $env_vars, $ENV{SMBD_OPTIONS}, $ENV{SMBD_VALGRIND}, $ENV{SMBD_DONT_LOG_STDOUT}); + + # fork and exec() smbd in the child process %daemon_ctx = ( NAME => "smbd", BINARY_PATH => $binary, @@ -1381,39 +1330,12 @@ sub check_or_start($$$$$) { $daemon_ctx{SKIP_DAEMON} = 1; } - unlink($daemon_ctx{LOG_FILE}); - print "STARTING SMBD..."; - $pid = fork(); - if ($pid == 0) { - open STDOUT, ">$daemon_ctx{LOG_FILE}"; - open STDERR, '>&STDOUT'; - - SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE}); + my $pid = Samba::fork_and_exec($self, $env_vars, \%daemon_ctx, $STDIN_READER); - Samba::set_env_for_process($daemon_ctx{NAME}, $env_vars, $daemon_ctx{ENV_VARS}); - - if (defined($daemon_ctx{SKIP_DAEMON})) { - $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { - my $signame = shift; - print("Skip $daemon_ctx{NAME} received signal $signame"); - exit 0; - }; - sleep($self->{server_maxtime}); - exit 0; - } - - $ENV{MAKE_TEST_BINARY} = $daemon_ctx{BINARY_PATH}; - - close($env_vars->{STDIN_PIPE}); - open STDIN, ">&", \*STDIN_READER or die "can't dup STDIN_READER to STDIN: $!"; - - exec(@{ $daemon_ctx{FULL_CMD} }) - or die("Unable to start $ENV{MAKE_TEST_BINARY}: $!"); - } $env_vars->{SMBD_TL_PID} = $pid; write_pid($env_vars, "smbd", $pid); - print "DONE\n"; + # close the parent's read-end of the pipe close(STDIN_READER); return $self->wait_for_start($env_vars, $nmbd, $winbindd, $smbd); diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 883a8c8b585..0593a21c353 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -141,6 +141,7 @@ sub check_or_start($$$) $samba_envs->{KRB5_KDC_PROFILE} = $env_vars->{MITKDC_CONFIG}; } + # fork a child process and exec() samba my %daemon_ctx = ( NAME => "samba", BINARY_PATH => $binary, @@ -149,30 +150,11 @@ sub check_or_start($$$) TEE_STDOUT => 1, ENV_VARS => $samba_envs, ); + my $pid = Samba::fork_and_exec($self, $env_vars, \%daemon_ctx, $STDIN_READER); - print "STARTING SAMBA...\n"; - my $pid = fork(); - if ($pid == 0) { - # we want out from samba to go to the log file, but also - # to the users terminal when running 'make test' on the command - # line. This puts it on stderr on the terminal - open STDOUT, "| tee $daemon_ctx{LOG_FILE} 1>&2"; - open STDERR, '>&STDOUT'; - - SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE}); - - Samba::set_env_for_process($daemon_ctx{NAME}, $env_vars, $daemon_ctx{ENV_VARS}); - - $ENV{MAKE_TEST_BINARY} = $daemon_ctx{BINARY_PATH}; - - close($env_vars->{STDIN_PIPE}); - open STDIN, ">&", $STDIN_READER or die "can't dup STDIN_READER to STDIN: $!"; - - exec(@{ $daemon_ctx{FULL_CMD} }) or die("Unable to start $daemon_ctx{BINARY_NAME}: $!"); - } $env_vars->{SAMBA_PID} = $pid; - print "DONE ($pid)\n"; + # close the parent's read-end of the pipe close($STDIN_READER); if ($self->wait_for_start($env_vars) != 0) { @@ -415,6 +397,7 @@ sub setup_dns_hub_internal($$$) push (@args, "$env->{SERVER_IP}"); push (@args, Samba::realm_to_ip_mappings()); my @full_cmd = (@preargs, $binary, @args); + my %daemon_ctx = ( NAME => "dnshub", BINARY_PATH => $binary, @@ -430,33 +413,14 @@ sub setup_dns_hub_internal($$$) # exit when the test script exits pipe($STDIN_READER, $env->{STDIN_PIPE}); - print "STARTING rootdnsforwarder...\n"; - my $pid = fork(); - if ($pid == 0) { - # we want out from samba to go to the log file, but also - # to the users terminal when running 'make test' on the command - # line. This puts it on stderr on the terminal - open STDOUT, "| tee $daemon_ctx{LOG_FILE} 1>&2"; - open STDERR, '>&STDOUT'; - - SocketWrapper::set_default_iface($env->{SOCKET_WRAPPER_DEFAULT_IFACE}); - SocketWrapper::setup_pcap($daemon_ctx{PCAP_FILE}); - - Samba::set_env_for_process($daemon_ctx{NAME}, $env, $daemon_ctx{ENV_VARS}); + my $pid = Samba::fork_and_exec($self, $env, \%daemon_ctx, $STDIN_READER); - $ENV{MAKE_TEST_BINARY} = $daemon_ctx{BINARY_PATH}; - - close($env->{STDIN_PIPE}); - open STDIN, ">&", $STDIN_READER or die "can't dup STDIN_READER to STDIN: $!"; - - exec(@{ $daemon_ctx{FULL_CMD} }) - or die("Unable to start $daemon_ctx{NAME}: $!"); - } $env->{SAMBA_PID} = $pid; $env->{KRB5_CONFIG} = "$prefix_abs/no_krb5.conf"; + + # close the parent's read-end of the pipe close($STDIN_READER); - print "DONE\n"; return $env; }