runner.pm 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439
  1. #***************************************************************************
  2. # _ _ ____ _
  3. # Project ___| | | | _ \| |
  4. # / __| | | | |_) | |
  5. # | (__| |_| | _ <| |___
  6. # \___|\___/|_| \_\_____|
  7. #
  8. # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. #
  10. # This software is licensed as described in the file COPYING, which
  11. # you should have received as part of this distribution. The terms
  12. # are also available at https://curl.se/docs/copyright.html.
  13. #
  14. # You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. # copies of the Software, and permit persons to whom the Software is
  16. # furnished to do so, under the terms of the COPYING file.
  17. #
  18. # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. # KIND, either express or implied.
  20. #
  21. # SPDX-License-Identifier: curl
  22. #
  23. ###########################################################################
  24. # This module contains entry points to run a single test. runner_init
  25. # determines whether they will run in a separate process or in the process of
  26. # the caller. The relevant interface is asynchronous so it will work in either
  27. # case. Program arguments are marshalled and then written to the end of a pipe
  28. # (in controlleripccall) which is later read from and the arguments
  29. # unmarshalled (in ipcrecv) before the desired function is called normally.
  30. # The function return values are then marshalled and written into another pipe
  31. # (again in ipcrecv) when is later read from and unmarshalled (in runnerar)
  32. # before being returned to the caller.
  33. package runner;
  34. use strict;
  35. use warnings;
  36. use 5.006;
  37. BEGIN {
  38. use base qw(Exporter);
  39. our @EXPORT = qw(
  40. checktestcmd
  41. prepro
  42. readtestkeywords
  43. restore_test_env
  44. runner_init
  45. runnerac_clearlocks
  46. runnerac_shutdown
  47. runnerac_stopservers
  48. runnerac_test_preprocess
  49. runnerac_test_run
  50. runnerar
  51. runnerar_ready
  52. stderrfilename
  53. stdoutfilename
  54. $DBGCURL
  55. $gdb
  56. $gdbthis
  57. $gdbxwin
  58. $shallow
  59. $tortalloc
  60. $valgrind_logfile
  61. $valgrind_tool
  62. );
  63. # these are for debugging only
  64. our @EXPORT_OK = qw(
  65. singletest_preprocess
  66. );
  67. }
  68. use B qw(
  69. svref_2object
  70. );
  71. use Storable qw(
  72. freeze
  73. thaw
  74. );
  75. use pathhelp qw(
  76. exe_ext
  77. );
  78. use processhelp qw(
  79. portable_sleep
  80. );
  81. use servers qw(
  82. checkcmd
  83. clearlocks
  84. initserverconfig
  85. serverfortest
  86. stopserver
  87. stopservers
  88. subvariables
  89. );
  90. use getpart;
  91. use globalconfig;
  92. use testutil qw(
  93. clearlogs
  94. logmsg
  95. runclient
  96. shell_quote
  97. subbase64
  98. subnewlines
  99. );
  100. use valgrind;
  101. #######################################################################
  102. # Global variables set elsewhere but used only by this package
  103. # These may only be set *before* runner_init is called
  104. our $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
  105. our $valgrind_logfile="--log-file"; # the option name for valgrind >=3
  106. our $valgrind_tool="--tool=memcheck";
  107. our $gdb = checktestcmd("gdb");
  108. our $gdbthis; # run test case with gdb debugger
  109. our $gdbxwin; # use windowed gdb when using gdb
  110. # torture test variables
  111. our $shallow;
  112. our $tortalloc;
  113. # local variables
  114. my %oldenv; # environment variables before test is started
  115. my $UNITDIR="./unit";
  116. my $CURLLOG="$LOGDIR/commands.log"; # all command lines run
  117. my $defserverlogslocktimeout = 2; # timeout to await server logs lock removal
  118. my $defpostcommanddelay = 0; # delay between command and postcheck sections
  119. my $multiprocess; # nonzero with a separate test runner process
  120. # pipes
  121. my $runnerr; # pipe that runner reads from
  122. my $runnerw; # pipe that runner writes to
  123. # per-runner variables, indexed by runner ID; these are used by controller only
  124. my %controllerr; # pipe that controller reads from
  125. my %controllerw; # pipe that controller writes to
  126. # redirected stdout/stderr to these files
  127. sub stdoutfilename {
  128. my ($logdir, $testnum)=@_;
  129. return "$logdir/stdout$testnum";
  130. }
  131. sub stderrfilename {
  132. my ($logdir, $testnum)=@_;
  133. return "$logdir/stderr$testnum";
  134. }
  135. #######################################################################
  136. # Initialize the runner and prepare it to run tests
  137. # The runner ID returned by this function must be passed into the other
  138. # runnerac_* functions
  139. # Called by controller
  140. sub runner_init {
  141. my ($logdir, $jobs)=@_;
  142. $multiprocess = !!$jobs;
  143. # enable memory debugging if curl is compiled with it
  144. $ENV{'CURL_MEMDEBUG'} = "$logdir/$MEMDUMP";
  145. $ENV{'CURL_ENTROPY'}="12345678";
  146. $ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
  147. $ENV{'CURL_GLOBAL_INIT'}=1; # debug curl_global_init/cleanup use
  148. $ENV{'HOME'}=$pwd;
  149. $ENV{'CURL_HOME'}=$ENV{'HOME'};
  150. $ENV{'XDG_CONFIG_HOME'}=$ENV{'HOME'};
  151. $ENV{'COLUMNS'}=79; # screen width!
  152. # Incorporate the $logdir into the random seed and re-seed the PRNG.
  153. # This gives each runner a unique yet consistent seed which provides
  154. # more unique port number selection in each runner, yet is deterministic
  155. # across runs.
  156. $randseed += unpack('%16C*', $logdir);
  157. srand $randseed;
  158. # create pipes for communication with runner
  159. my ($thisrunnerr, $thiscontrollerw, $thiscontrollerr, $thisrunnerw);
  160. pipe $thisrunnerr, $thiscontrollerw;
  161. pipe $thiscontrollerr, $thisrunnerw;
  162. my $thisrunnerid;
  163. if($multiprocess) {
  164. # Create a separate process in multiprocess mode
  165. my $child = fork();
  166. if(0 == $child) {
  167. # TODO: set up better signal handlers
  168. $SIG{INT} = 'IGNORE';
  169. $SIG{TERM} = 'IGNORE';
  170. eval {
  171. # some msys2 perl versions don't define SIGUSR1
  172. $SIG{USR1} = 'IGNORE';
  173. };
  174. $thisrunnerid = $$;
  175. print "Runner $thisrunnerid starting\n" if($verbose);
  176. # Here we are the child (runner).
  177. close($thiscontrollerw);
  178. close($thiscontrollerr);
  179. $runnerr = $thisrunnerr;
  180. $runnerw = $thisrunnerw;
  181. # Set this directory as ours
  182. $LOGDIR = $logdir;
  183. mkdir("$LOGDIR/$PIDDIR", 0777);
  184. mkdir("$LOGDIR/$LOCKDIR", 0777);
  185. # Initialize various server variables
  186. initserverconfig();
  187. # handle IPC calls
  188. event_loop();
  189. # Can't rely on logmsg here in case it's buffered
  190. print "Runner $thisrunnerid exiting\n" if($verbose);
  191. # To reach this point, either the controller has sent
  192. # runnerac_stopservers() and runnerac_shutdown() or we have called
  193. # runnerabort(). In both cases, there are no more of our servers
  194. # running and we can safely exit.
  195. exit 0;
  196. }
  197. # Here we are the parent (controller).
  198. close($thisrunnerw);
  199. close($thisrunnerr);
  200. $thisrunnerid = $child;
  201. } else {
  202. # Create our pid directory
  203. mkdir("$LOGDIR/$PIDDIR", 0777);
  204. # Don't create a separate process
  205. $thisrunnerid = "integrated";
  206. }
  207. $controllerw{$thisrunnerid} = $thiscontrollerw;
  208. $runnerr = $thisrunnerr;
  209. $runnerw = $thisrunnerw;
  210. $controllerr{$thisrunnerid} = $thiscontrollerr;
  211. return $thisrunnerid;
  212. }
  213. #######################################################################
  214. # Loop to execute incoming IPC calls until the shutdown call
  215. sub event_loop {
  216. while () {
  217. if(ipcrecv()) {
  218. last;
  219. }
  220. }
  221. }
  222. #######################################################################
  223. # Check for a command in the PATH of the machine running curl.
  224. #
  225. sub checktestcmd {
  226. my ($cmd)=@_;
  227. my @testpaths=("$LIBDIR/.libs", "$LIBDIR");
  228. return checkcmd($cmd, @testpaths);
  229. }
  230. # See if Valgrind should actually be used
  231. sub use_valgrind {
  232. if($valgrind) {
  233. my @valgrindoption = getpart("verify", "valgrind");
  234. if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
  235. return 1;
  236. }
  237. }
  238. return 0;
  239. }
  240. # Massage the command result code into a useful form
  241. sub normalize_cmdres {
  242. my $cmdres = $_[0];
  243. my $signal_num = $cmdres & 127;
  244. my $dumped_core = $cmdres & 128;
  245. if(!$anyway && ($signal_num || $dumped_core)) {
  246. $cmdres = 1000;
  247. }
  248. else {
  249. $cmdres >>= 8;
  250. $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres);
  251. }
  252. return ($cmdres, $dumped_core);
  253. }
  254. # 'prepro' processes the input array and replaces %-variables in the array
  255. # etc. Returns the processed version of the array
  256. sub prepro {
  257. my $testnum = shift;
  258. my (@entiretest) = @_;
  259. my $show = 1;
  260. my @out;
  261. my $data_crlf;
  262. for my $s (@entiretest) {
  263. my $f = $s;
  264. if($s =~ /^ *%if (.*)/) {
  265. my $cond = $1;
  266. my $rev = 0;
  267. if($cond =~ /^!(.*)/) {
  268. $cond = $1;
  269. $rev = 1;
  270. }
  271. $rev ^= $feature{$cond} ? 1 : 0;
  272. $show = $rev;
  273. next;
  274. }
  275. elsif($s =~ /^ *%else/) {
  276. $show ^= 1;
  277. next;
  278. }
  279. elsif($s =~ /^ *%endif/) {
  280. $show = 1;
  281. next;
  282. }
  283. if($show) {
  284. # The processor does CRLF replacements in the <data*> sections if
  285. # necessary since those parts might be read by separate servers.
  286. if($s =~ /^ *<data(.*)\>/) {
  287. if($1 =~ /crlf="yes"/ ||
  288. ($feature{"hyper"} && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
  289. $data_crlf = 1;
  290. }
  291. }
  292. elsif(($s =~ /^ *<\/data/) && $data_crlf) {
  293. $data_crlf = 0;
  294. }
  295. subvariables(\$s, $testnum, "%");
  296. subbase64(\$s);
  297. subnewlines(0, \$s) if($data_crlf);
  298. push @out, $s;
  299. }
  300. }
  301. return @out;
  302. }
  303. #######################################################################
  304. # Load test keywords into %keywords hash
  305. #
  306. sub readtestkeywords {
  307. my @info_keywords = getpart("info", "keywords");
  308. # Clear the list of keywords from the last test
  309. %keywords = ();
  310. for my $k (@info_keywords) {
  311. chomp $k;
  312. $keywords{$k} = 1;
  313. }
  314. }
  315. #######################################################################
  316. # Return a list of log locks that still exist
  317. #
  318. sub logslocked {
  319. opendir(my $lockdir, "$LOGDIR/$LOCKDIR");
  320. my @locks;
  321. foreach (readdir $lockdir) {
  322. if(/^(.*)\.lock$/) {
  323. push @locks, $1;
  324. }
  325. }
  326. return @locks;
  327. }
  328. #######################################################################
  329. # Memory allocation test and failure torture testing.
  330. #
  331. sub torture {
  332. my ($testcmd, $testnum, $gdbline) = @_;
  333. # remove memdump first to be sure we get a new nice and clean one
  334. unlink("$LOGDIR/$MEMDUMP");
  335. # First get URL from test server, ignore the output/result
  336. runclient($testcmd);
  337. logmsg " CMD: $testcmd\n" if($verbose);
  338. # memanalyze -v is our friend, get the number of allocations made
  339. my $count=0;
  340. my @out = `$memanalyze -v "$LOGDIR/$MEMDUMP"`;
  341. for(@out) {
  342. if(/^Operations: (\d+)/) {
  343. $count = $1;
  344. last;
  345. }
  346. }
  347. if(!$count) {
  348. logmsg " found no functions to make fail\n";
  349. return 0;
  350. }
  351. my @ttests = (1 .. $count);
  352. if($shallow && ($shallow < $count)) {
  353. my $discard = scalar(@ttests) - $shallow;
  354. my $percent = sprintf("%.2f%%", $shallow * 100 / scalar(@ttests));
  355. logmsg " $count functions found, but only fail $shallow ($percent)\n";
  356. while($discard) {
  357. my $rm;
  358. do {
  359. # find a test to discard
  360. $rm = rand(scalar(@ttests));
  361. } while(!$ttests[$rm]);
  362. $ttests[$rm] = undef;
  363. $discard--;
  364. }
  365. }
  366. else {
  367. logmsg " $count functions to make fail\n";
  368. }
  369. for (@ttests) {
  370. my $limit = $_;
  371. my $fail;
  372. my $dumped_core;
  373. if(!defined($limit)) {
  374. # --shallow can undefine them
  375. next;
  376. }
  377. if($tortalloc && ($tortalloc != $limit)) {
  378. next;
  379. }
  380. if($verbose) {
  381. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
  382. localtime(time());
  383. my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
  384. logmsg "Fail function no: $limit at $now\r";
  385. }
  386. # make the memory allocation function number $limit return failure
  387. $ENV{'CURL_MEMLIMIT'} = $limit;
  388. # remove memdump first to be sure we get a new nice and clean one
  389. unlink("$LOGDIR/$MEMDUMP");
  390. my $cmd = $testcmd;
  391. if($valgrind && !$gdbthis) {
  392. my @valgrindoption = getpart("verify", "valgrind");
  393. if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
  394. my $valgrindcmd = "$valgrind ";
  395. $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
  396. $valgrindcmd .= "--quiet --leak-check=yes ";
  397. $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
  398. # $valgrindcmd .= "--gen-suppressions=all ";
  399. $valgrindcmd .= "--num-callers=16 ";
  400. $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
  401. $cmd = "$valgrindcmd $testcmd";
  402. }
  403. }
  404. logmsg "*** Function number $limit is now set to fail ***\n" if($gdbthis);
  405. my $ret = 0;
  406. if($gdbthis) {
  407. runclient($gdbline);
  408. }
  409. else {
  410. $ret = runclient($cmd);
  411. }
  412. #logmsg "$_ Returned " . ($ret >> 8) . "\n";
  413. # Now clear the variable again
  414. delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
  415. if(-r "core") {
  416. # there's core file present now!
  417. logmsg " core dumped\n";
  418. $dumped_core = 1;
  419. $fail = 2;
  420. }
  421. if($valgrind) {
  422. my @e = valgrindparse("$LOGDIR/valgrind$testnum");
  423. if(@e && $e[0]) {
  424. if($automakestyle) {
  425. logmsg "FAIL: torture $testnum - valgrind\n";
  426. }
  427. else {
  428. logmsg " valgrind ERROR ";
  429. logmsg @e;
  430. }
  431. $fail = 1;
  432. }
  433. }
  434. # verify that it returns a proper error code, doesn't leak memory
  435. # and doesn't core dump
  436. if(($ret & 255) || ($ret >> 8) >= 128) {
  437. logmsg " system() returned $ret\n";
  438. $fail=1;
  439. }
  440. else {
  441. my @memdata=`$memanalyze "$LOGDIR/$MEMDUMP"`;
  442. my $leak=0;
  443. for(@memdata) {
  444. if($_ ne "") {
  445. # well it could be other memory problems as well, but
  446. # we call it leak for short here
  447. $leak=1;
  448. }
  449. }
  450. if($leak) {
  451. logmsg "** MEMORY FAILURE\n";
  452. logmsg @memdata;
  453. logmsg `$memanalyze -l "$LOGDIR/$MEMDUMP"`;
  454. $fail = 1;
  455. }
  456. }
  457. if($fail) {
  458. logmsg " $testnum: torture FAILED: function number $limit in test.\n",
  459. " invoke with \"-t$limit\" to repeat this single case.\n";
  460. stopservers($verbose);
  461. return 1;
  462. }
  463. }
  464. logmsg "\n" if($verbose);
  465. logmsg "torture OK\n";
  466. return 0;
  467. }
  468. #######################################################################
  469. # restore environment variables that were modified in test
  470. sub restore_test_env {
  471. my $deleteoldenv = $_[0]; # 1 to delete the saved contents after restore
  472. foreach my $var (keys %oldenv) {
  473. if($oldenv{$var} eq 'notset') {
  474. delete $ENV{$var} if($ENV{$var});
  475. }
  476. else {
  477. $ENV{$var} = $oldenv{$var};
  478. }
  479. if($deleteoldenv) {
  480. delete $oldenv{$var};
  481. }
  482. }
  483. }
  484. #######################################################################
  485. # Start the servers needed to run this test case
  486. sub singletest_startservers {
  487. my ($testnum, $testtimings) = @_;
  488. # remove old test server files before servers are started/verified
  489. unlink("$LOGDIR/$SERVERCMD");
  490. unlink("$LOGDIR/$SERVERIN");
  491. unlink("$LOGDIR/$PROXYIN");
  492. # timestamp required servers verification start
  493. $$testtimings{"timesrvrini"} = Time::HiRes::time();
  494. my $why;
  495. my $error;
  496. if (!$listonly) {
  497. my @what = getpart("client", "server");
  498. if(!$what[0]) {
  499. warn "Test case $testnum has no server(s) specified";
  500. $why = "no server specified";
  501. $error = -1;
  502. } else {
  503. my $err;
  504. ($why, $err) = serverfortest(@what);
  505. if($err == 1) {
  506. # Error indicates an actual problem starting the server
  507. $error = -2;
  508. } else {
  509. $error = -1;
  510. }
  511. }
  512. }
  513. # timestamp required servers verification end
  514. $$testtimings{"timesrvrend"} = Time::HiRes::time();
  515. return ($why, $error);
  516. }
  517. #######################################################################
  518. # Generate preprocessed test file
  519. sub singletest_preprocess {
  520. my $testnum = $_[0];
  521. # Save a preprocessed version of the entire test file. This allows more
  522. # "basic" test case readers to enjoy variable replacements.
  523. my @entiretest = fulltest();
  524. my $otest = "$LOGDIR/test$testnum";
  525. @entiretest = prepro($testnum, @entiretest);
  526. # save the new version
  527. open(my $fulltesth, ">", "$otest") || die "Failure writing test file";
  528. foreach my $bytes (@entiretest) {
  529. print $fulltesth pack('a*', $bytes) or die "Failed to print '$bytes': $!";
  530. }
  531. close($fulltesth) || die "Failure writing test file";
  532. # in case the process changed the file, reload it
  533. loadtest("$LOGDIR/test${testnum}");
  534. }
  535. #######################################################################
  536. # Set up the test environment to run this test case
  537. sub singletest_setenv {
  538. my @setenv = getpart("client", "setenv");
  539. foreach my $s (@setenv) {
  540. chomp $s;
  541. if($s =~ /([^=]*)=(.*)/) {
  542. my ($var, $content) = ($1, $2);
  543. # remember current setting, to restore it once test runs
  544. $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
  545. # set new value
  546. if(!$content) {
  547. delete $ENV{$var} if($ENV{$var});
  548. }
  549. else {
  550. if($var =~ /^LD_PRELOAD/) {
  551. if(exe_ext('TOOL') && (exe_ext('TOOL') eq '.exe')) {
  552. logmsg "Skipping LD_PRELOAD due to lack of OS support\n" if($verbose);
  553. next;
  554. }
  555. if($feature{"debug"} || !$has_shared) {
  556. logmsg "Skipping LD_PRELOAD due to no release shared build\n" if($verbose);
  557. next;
  558. }
  559. }
  560. $ENV{$var} = "$content";
  561. logmsg "setenv $var = $content\n" if($verbose);
  562. }
  563. }
  564. }
  565. if($proxy_address) {
  566. $ENV{http_proxy} = $proxy_address;
  567. $ENV{HTTPS_PROXY} = $proxy_address;
  568. }
  569. }
  570. #######################################################################
  571. # Check that test environment is fine to run this test case
  572. sub singletest_precheck {
  573. my $testnum = $_[0];
  574. my $why;
  575. my @precheck = getpart("client", "precheck");
  576. if(@precheck) {
  577. my $cmd = $precheck[0];
  578. chomp $cmd;
  579. if($cmd) {
  580. my @p = split(/ /, $cmd);
  581. if($p[0] !~ /\//) {
  582. # the first word, the command, does not contain a slash so
  583. # we will scan the "improved" PATH to find the command to
  584. # be able to run it
  585. my $fullp = checktestcmd($p[0]);
  586. if($fullp) {
  587. $p[0] = $fullp;
  588. }
  589. $cmd = join(" ", @p);
  590. }
  591. my @o = `$cmd 2> $LOGDIR/precheck-$testnum`;
  592. if($o[0]) {
  593. $why = $o[0];
  594. $why =~ s/[\r\n]//g;
  595. }
  596. elsif($?) {
  597. $why = "precheck command error";
  598. }
  599. logmsg "prechecked $cmd\n" if($verbose);
  600. }
  601. }
  602. return $why;
  603. }
  604. #######################################################################
  605. # Prepare the test environment to run this test case
  606. sub singletest_prepare {
  607. my ($testnum) = @_;
  608. if($feature{"TrackMemory"}) {
  609. unlink("$LOGDIR/$MEMDUMP");
  610. }
  611. unlink("core");
  612. # remove server output logfiles after servers are started/verified
  613. unlink("$LOGDIR/$SERVERIN");
  614. unlink("$LOGDIR/$PROXYIN");
  615. # if this section exists, it might be FTP server instructions:
  616. my @ftpservercmd = getpart("reply", "servercmd");
  617. push @ftpservercmd, "Testnum $testnum\n";
  618. # write the instructions to file
  619. writearray("$LOGDIR/$SERVERCMD", \@ftpservercmd);
  620. # create (possibly-empty) files before starting the test
  621. for my $partsuffix (('', '1', '2', '3', '4')) {
  622. my @inputfile=getpart("client", "file".$partsuffix);
  623. my %fileattr = getpartattr("client", "file".$partsuffix);
  624. my $filename=$fileattr{'name'};
  625. if(@inputfile || $filename) {
  626. if(!$filename) {
  627. logmsg " $testnum: IGNORED: section client=>file has no name attribute\n";
  628. return -1;
  629. }
  630. my $fileContent = join('', @inputfile);
  631. # make directories if needed
  632. my $path = $filename;
  633. # cut off the file name part
  634. $path =~ s/^(.*)\/[^\/]*/$1/;
  635. my $nparts = scalar(split(/\//, $LOGDIR));
  636. my @parts = split(/\//, $path);
  637. if(join("/", @parts[0..$nparts-1]) eq $LOGDIR) {
  638. # the file is in $LOGDIR/
  639. my $d = shift @parts;
  640. for(@parts) {
  641. $d .= "/$_";
  642. mkdir $d; # 0777
  643. }
  644. }
  645. if (open(my $outfile, ">", "$filename")) {
  646. binmode $outfile; # for crapage systems, use binary
  647. if($fileattr{'nonewline'}) {
  648. # cut off the final newline
  649. chomp($fileContent);
  650. }
  651. print $outfile $fileContent;
  652. close($outfile);
  653. } else {
  654. logmsg "ERROR: cannot write $filename\n";
  655. }
  656. }
  657. }
  658. return 0;
  659. }
  660. #######################################################################
  661. # Run the test command
  662. sub singletest_run {
  663. my ($testnum, $testtimings) = @_;
  664. # get the command line options to use
  665. my ($cmd, @blaha)= getpart("client", "command");
  666. if($cmd) {
  667. # make some nice replace operations
  668. $cmd =~ s/\n//g; # no newlines please
  669. # substitute variables in the command line
  670. }
  671. else {
  672. # there was no command given, use something silly
  673. $cmd="-";
  674. }
  675. my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
  676. # if stdout section exists, we verify that the stdout contained this:
  677. my $out="";
  678. my %cmdhash = getpartattr("client", "command");
  679. if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) {
  680. #We may slap on --output!
  681. if (!partexists("verify", "stdout") ||
  682. ($cmdhash{'option'} && $cmdhash{'option'} =~ /force-output/)) {
  683. $out=" --output $CURLOUT ";
  684. }
  685. }
  686. my @codepieces = getpart("client", "tool");
  687. my $tool="";
  688. if(@codepieces) {
  689. $tool = $codepieces[0];
  690. chomp $tool;
  691. $tool .= exe_ext('TOOL');
  692. }
  693. my $disablevalgrind;
  694. my $CMDLINE="";
  695. my $cmdargs;
  696. my $cmdtype = $cmdhash{'type'} || "default";
  697. my $fail_due_event_based = $run_event_based;
  698. if($cmdtype eq "perl") {
  699. # run the command line prepended with "perl"
  700. $cmdargs ="$cmd";
  701. $CMDLINE = "$perl ";
  702. $tool=$CMDLINE;
  703. $disablevalgrind=1;
  704. }
  705. elsif($cmdtype eq "shell") {
  706. # run the command line prepended with "/bin/sh"
  707. $cmdargs ="$cmd";
  708. $CMDLINE = "/bin/sh ";
  709. $tool=$CMDLINE;
  710. $disablevalgrind=1;
  711. }
  712. elsif(!$tool && !$keywords{"unittest"}) {
  713. # run curl, add suitable command line options
  714. my $inc="";
  715. if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
  716. $inc = " --include";
  717. }
  718. $cmdargs = "$out$inc ";
  719. if($cmdhash{'option'} && ($cmdhash{'option'} =~ /binary-trace/)) {
  720. $cmdargs .= "--trace $LOGDIR/trace$testnum ";
  721. }
  722. else {
  723. $cmdargs .= "--trace-ascii $LOGDIR/trace$testnum ";
  724. }
  725. $cmdargs .= "--trace-time ";
  726. if($run_event_based) {
  727. $cmdargs .= "--test-event ";
  728. $fail_due_event_based--;
  729. }
  730. $cmdargs .= $cmd;
  731. if ($proxy_address) {
  732. $cmdargs .= " --proxy $proxy_address ";
  733. }
  734. }
  735. else {
  736. $cmdargs = " $cmd"; # $cmd is the command line for the test file
  737. $CURLOUT = stdoutfilename($LOGDIR, $testnum); # sends received data to stdout
  738. # Default the tool to a unit test with the same name as the test spec
  739. if($keywords{"unittest"} && !$tool) {
  740. $tool="unit$testnum";
  741. }
  742. if($tool =~ /^lib/) {
  743. $CMDLINE="$LIBDIR/$tool";
  744. }
  745. elsif($tool =~ /^unit/) {
  746. $CMDLINE="$UNITDIR/$tool";
  747. }
  748. if(! -f $CMDLINE) {
  749. logmsg " $testnum: IGNORED: The tool set in the test case for this: '$tool' does not exist\n";
  750. return (-1, 0, 0, "", "", 0);
  751. }
  752. $DBGCURL=$CMDLINE;
  753. }
  754. if($fail_due_event_based) {
  755. logmsg " $testnum: IGNORED: This test cannot run event based\n";
  756. return (-1, 0, 0, "", "", 0);
  757. }
  758. if($gdbthis) {
  759. # gdb is incompatible with valgrind, so disable it when debugging
  760. # Perhaps a better approach would be to run it under valgrind anyway
  761. # with --db-attach=yes or --vgdb=yes.
  762. $disablevalgrind=1;
  763. }
  764. my @stdintest = getpart("client", "stdin");
  765. if(@stdintest) {
  766. my $stdinfile="$LOGDIR/stdin-for-$testnum";
  767. my %hash = getpartattr("client", "stdin");
  768. if($hash{'nonewline'}) {
  769. # cut off the final newline from the final line of the stdin data
  770. chomp($stdintest[-1]);
  771. }
  772. writearray($stdinfile, \@stdintest);
  773. $cmdargs .= " <$stdinfile";
  774. }
  775. if(!$tool) {
  776. $CMDLINE=shell_quote($CURL);
  777. }
  778. if(use_valgrind() && !$disablevalgrind) {
  779. my $valgrindcmd = "$valgrind ";
  780. $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
  781. $valgrindcmd .= "--quiet --leak-check=yes ";
  782. $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
  783. # $valgrindcmd .= "--gen-suppressions=all ";
  784. $valgrindcmd .= "--num-callers=16 ";
  785. $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
  786. $CMDLINE = "$valgrindcmd $CMDLINE";
  787. }
  788. $CMDLINE .= "$cmdargs > " . stdoutfilename($LOGDIR, $testnum) .
  789. " 2> " . stderrfilename($LOGDIR, $testnum);
  790. if($verbose) {
  791. logmsg "$CMDLINE\n";
  792. }
  793. open(my $cmdlog, ">", $CURLLOG) || die "Failure writing log file";
  794. print $cmdlog "$CMDLINE\n";
  795. close($cmdlog) || die "Failure writing log file";
  796. my $dumped_core;
  797. my $cmdres;
  798. if($gdbthis) {
  799. my $gdbinit = "$TESTDIR/gdbinit$testnum";
  800. open(my $gdbcmd, ">", "$LOGDIR/gdbcmd") || die "Failure writing gdb file";
  801. print $gdbcmd "set args $cmdargs\n";
  802. print $gdbcmd "show args\n";
  803. print $gdbcmd "source $gdbinit\n" if -e $gdbinit;
  804. close($gdbcmd) || die "Failure writing gdb file";
  805. }
  806. # Flush output.
  807. $| = 1;
  808. # timestamp starting of test command
  809. $$testtimings{"timetoolini"} = Time::HiRes::time();
  810. # run the command line we built
  811. if ($torture) {
  812. $cmdres = torture($CMDLINE,
  813. $testnum,
  814. "$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " -x $LOGDIR/gdbcmd");
  815. }
  816. elsif($gdbthis) {
  817. my $GDBW = ($gdbxwin) ? "-w" : "";
  818. runclient("$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " $GDBW -x $LOGDIR/gdbcmd");
  819. $cmdres=0; # makes it always continue after a debugged run
  820. }
  821. else {
  822. # Convert the raw result code into a more useful one
  823. ($cmdres, $dumped_core) = normalize_cmdres(runclient("$CMDLINE"));
  824. }
  825. # timestamp finishing of test command
  826. $$testtimings{"timetoolend"} = Time::HiRes::time();
  827. return (0, $cmdres, $dumped_core, $CURLOUT, $tool, use_valgrind() && !$disablevalgrind);
  828. }
  829. #######################################################################
  830. # Clean up after test command
  831. sub singletest_clean {
  832. my ($testnum, $dumped_core, $testtimings)=@_;
  833. if(!$dumped_core) {
  834. if(-r "core") {
  835. # there's core file present now!
  836. $dumped_core = 1;
  837. }
  838. }
  839. if($dumped_core) {
  840. logmsg "core dumped\n";
  841. if(0 && $gdb) {
  842. logmsg "running gdb for post-mortem analysis:\n";
  843. open(my $gdbcmd, ">", "$LOGDIR/gdbcmd2") || die "Failure writing gdb file";
  844. print $gdbcmd "bt\n";
  845. close($gdbcmd) || die "Failure writing gdb file";
  846. runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch " . shell_quote($DBGCURL) . " core ");
  847. # unlink("$LOGDIR/gdbcmd2");
  848. }
  849. }
  850. # If a server logs advisor read lock file exists, it is an indication
  851. # that the server has not yet finished writing out all its log files,
  852. # including server request log files used for protocol verification.
  853. # So, if the lock file exists the script waits here a certain amount
  854. # of time until the server removes it, or the given time expires.
  855. my $serverlogslocktimeout = $defserverlogslocktimeout;
  856. my %cmdhash = getpartattr("client", "command");
  857. if($cmdhash{'timeout'}) {
  858. # test is allowed to override default server logs lock timeout
  859. if($cmdhash{'timeout'} =~ /(\d+)/) {
  860. $serverlogslocktimeout = $1 if($1 >= 0);
  861. }
  862. }
  863. if($serverlogslocktimeout) {
  864. my $lockretry = $serverlogslocktimeout * 20;
  865. my @locks;
  866. while((@locks = logslocked()) && $lockretry--) {
  867. portable_sleep(0.05);
  868. }
  869. if(($lockretry < 0) &&
  870. ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
  871. logmsg "Warning: server logs lock timeout ",
  872. "($serverlogslocktimeout seconds) expired (locks: " .
  873. join(", ", @locks) . ")\n";
  874. }
  875. }
  876. # Test harness ssh server does not have this synchronization mechanism,
  877. # this implies that some ssh server based tests might need a small delay
  878. # once that the client command has run to avoid false test failures.
  879. #
  880. # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv
  881. # based tests might need a small delay once that the client command has
  882. # run to avoid false test failures.
  883. my $postcommanddelay = $defpostcommanddelay;
  884. if($cmdhash{'delay'}) {
  885. # test is allowed to specify a delay after command is executed
  886. if($cmdhash{'delay'} =~ /(\d+)/) {
  887. $postcommanddelay = $1 if($1 > 0);
  888. }
  889. }
  890. portable_sleep($postcommanddelay) if($postcommanddelay);
  891. # timestamp removal of server logs advisor read lock
  892. $$testtimings{"timesrvrlog"} = Time::HiRes::time();
  893. # test definition might instruct to stop some servers
  894. # stop also all servers relative to the given one
  895. my @killtestservers = getpart("client", "killserver");
  896. if(@killtestservers) {
  897. foreach my $server (@killtestservers) {
  898. chomp $server;
  899. if(stopserver($server)) {
  900. logmsg " $testnum: killserver FAILED\n";
  901. return 1; # normal error if asked to fail on unexpected alive
  902. }
  903. }
  904. }
  905. return 0;
  906. }
  907. #######################################################################
  908. # Verify that the postcheck succeeded
  909. sub singletest_postcheck {
  910. my ($testnum)=@_;
  911. # run the postcheck command
  912. my @postcheck= getpart("client", "postcheck");
  913. if(@postcheck) {
  914. my $cmd = join("", @postcheck);
  915. chomp $cmd;
  916. if($cmd) {
  917. logmsg "postcheck $cmd\n" if($verbose);
  918. my $rc = runclient("$cmd");
  919. # Must run the postcheck command in torture mode in order
  920. # to clean up, but the result can't be relied upon.
  921. if($rc != 0 && !$torture) {
  922. logmsg " $testnum: postcheck FAILED\n";
  923. return -1;
  924. }
  925. }
  926. }
  927. return 0;
  928. }
  929. ###################################################################
  930. # Get ready to run a single test case
  931. sub runner_test_preprocess {
  932. my ($testnum)=@_;
  933. my %testtimings;
  934. if(clearlogs()) {
  935. logmsg "Warning: log messages were lost\n";
  936. }
  937. # timestamp test preparation start
  938. # TODO: this metric now shows only a portion of the prep time; better would
  939. # be to time singletest_preprocess below instead
  940. $testtimings{"timeprepini"} = Time::HiRes::time();
  941. ###################################################################
  942. # Load test metadata
  943. # ignore any error here--if there were one, it would have been
  944. # caught during the selection phase and this test would not be
  945. # running now
  946. loadtest("${TESTDIR}/test${testnum}");
  947. readtestkeywords();
  948. ###################################################################
  949. # Restore environment variables that were modified in a previous run.
  950. # Test definition may instruct to (un)set environment vars.
  951. restore_test_env(1);
  952. ###################################################################
  953. # Start the servers needed to run this test case
  954. my ($why, $error) = singletest_startservers($testnum, \%testtimings);
  955. if(!$why) {
  956. ###############################################################
  957. # Generate preprocessed test file
  958. # This must be done after the servers are started so server
  959. # variables are available for substitution.
  960. singletest_preprocess($testnum);
  961. ###############################################################
  962. # Set up the test environment to run this test case
  963. singletest_setenv();
  964. ###############################################################
  965. # Check that the test environment is fine to run this test case
  966. if (!$listonly) {
  967. $why = singletest_precheck($testnum);
  968. $error = -1;
  969. }
  970. }
  971. return ($why, $error, clearlogs(), \%testtimings);
  972. }
  973. ###################################################################
  974. # Run a single test case with an environment that already been prepared
  975. # Returns 0=success, -1=skippable failure, -2=permanent error,
  976. # 1=unskippable test failure, as first integer, plus any log messages,
  977. # plus more return values when error is 0
  978. sub runner_test_run {
  979. my ($testnum)=@_;
  980. if(clearlogs()) {
  981. logmsg "Warning: log messages were lost\n";
  982. }
  983. #######################################################################
  984. # Prepare the test environment to run this test case
  985. my $error = singletest_prepare($testnum);
  986. if($error) {
  987. return (-2, clearlogs());
  988. }
  989. #######################################################################
  990. # Run the test command
  991. my %testtimings;
  992. my $cmdres;
  993. my $dumped_core;
  994. my $CURLOUT;
  995. my $tool;
  996. my $usedvalgrind;
  997. ($error, $cmdres, $dumped_core, $CURLOUT, $tool, $usedvalgrind) = singletest_run($testnum, \%testtimings);
  998. if($error) {
  999. return (-2, clearlogs(), \%testtimings);
  1000. }
  1001. #######################################################################
  1002. # Clean up after test command
  1003. $error = singletest_clean($testnum, $dumped_core, \%testtimings);
  1004. if($error) {
  1005. return ($error, clearlogs(), \%testtimings);
  1006. }
  1007. #######################################################################
  1008. # Verify that the postcheck succeeded
  1009. $error = singletest_postcheck($testnum);
  1010. if($error) {
  1011. return ($error, clearlogs(), \%testtimings);
  1012. }
  1013. #######################################################################
  1014. # restore environment variables that were modified
  1015. restore_test_env(0);
  1016. return (0, clearlogs(), \%testtimings, $cmdres, $CURLOUT, $tool, $usedvalgrind);
  1017. }
  1018. # Async call runner_clearlocks
  1019. # Called by controller
  1020. sub runnerac_clearlocks {
  1021. return controlleripccall(\&runner_clearlocks, @_);
  1022. }
  1023. # Async call runner_shutdown
  1024. # This call does NOT generate an IPC response and must be the last IPC call
  1025. # received.
  1026. # Called by controller
  1027. sub runnerac_shutdown {
  1028. my ($runnerid)=$_[0];
  1029. my $err = controlleripccall(\&runner_shutdown, @_);
  1030. # These have no more use
  1031. close($controllerw{$runnerid});
  1032. undef $controllerw{$runnerid};
  1033. close($controllerr{$runnerid});
  1034. undef $controllerr{$runnerid};
  1035. return $err;
  1036. }
  1037. # Async call of runner_stopservers
  1038. # Called by controller
  1039. sub runnerac_stopservers {
  1040. return controlleripccall(\&runner_stopservers, @_);
  1041. }
  1042. # Async call of runner_test_preprocess
  1043. # Called by controller
  1044. sub runnerac_test_preprocess {
  1045. return controlleripccall(\&runner_test_preprocess, @_);
  1046. }
  1047. # Async call of runner_test_run
  1048. # Called by controller
  1049. sub runnerac_test_run {
  1050. return controlleripccall(\&runner_test_run, @_);
  1051. }
  1052. ###################################################################
  1053. # Call an arbitrary function via IPC
  1054. # The first argument is the function reference, the second is the runner ID
  1055. # Returns 0 on success, -1 on error writing to runner
  1056. # Called by controller (indirectly, via a more specific function)
  1057. sub controlleripccall {
  1058. my $funcref = shift @_;
  1059. my $runnerid = shift @_;
  1060. # Get the name of the function from the reference
  1061. my $cv = svref_2object($funcref);
  1062. my $gv = $cv->GV;
  1063. # Prepend the name to the function arguments so it's marshalled along with them
  1064. unshift @_, $gv->NAME;
  1065. # Marshall the arguments into a flat string
  1066. my $margs = freeze \@_;
  1067. # Send IPC call via pipe
  1068. my $err;
  1069. while(! defined ($err = syswrite($controllerw{$runnerid}, (pack "L", length($margs)) . $margs)) || $err <= 0) {
  1070. if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
  1071. # Runner has likely died
  1072. return -1;
  1073. }
  1074. # system call was interrupted, probably by ^C; restart it so we stay in sync
  1075. }
  1076. if(!$multiprocess) {
  1077. # Call the remote function here in single process mode
  1078. ipcrecv();
  1079. }
  1080. return 0;
  1081. }
  1082. ###################################################################
  1083. # Receive async response of a previous call via IPC
  1084. # The first return value is the runner ID or undef on error
  1085. # Called by controller
  1086. sub runnerar {
  1087. my ($runnerid) = @_;
  1088. my $err;
  1089. my $datalen;
  1090. while(! defined ($err = sysread($controllerr{$runnerid}, $datalen, 4)) || $err <= 0) {
  1091. if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
  1092. # Runner is likely dead and closed the pipe
  1093. return undef;
  1094. }
  1095. # system call was interrupted, probably by ^C; restart it so we stay in sync
  1096. }
  1097. my $len=unpack("L", $datalen);
  1098. my $buf;
  1099. while(! defined ($err = sysread($controllerr{$runnerid}, $buf, $len)) || $err <= 0) {
  1100. if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
  1101. # Runner is likely dead and closed the pipe
  1102. return undef;
  1103. }
  1104. # system call was interrupted, probably by ^C; restart it so we stay in sync
  1105. }
  1106. # Decode response values
  1107. my $resarrayref = thaw $buf;
  1108. # First argument is runner ID
  1109. # TODO: remove this; it's unneeded since it's passed in
  1110. unshift @$resarrayref, $runnerid;
  1111. return @$resarrayref;
  1112. }
  1113. ###################################################################
  1114. # Returns runner ID if a response from an async call is ready or error
  1115. # First value is ready, second is error, however an error case shows up
  1116. # as ready in Linux, so you can't trust it.
  1117. # argument is 0 for nonblocking, undef for blocking, anything else for timeout
  1118. # Called by controller
  1119. sub runnerar_ready {
  1120. my ($blocking) = @_;
  1121. my $rin = "";
  1122. my %idbyfileno;
  1123. my $maxfileno=0;
  1124. foreach my $p (keys(%controllerr)) {
  1125. my $fd = fileno($controllerr{$p});
  1126. vec($rin, $fd, 1) = 1;
  1127. $idbyfileno{$fd} = $p; # save the runner ID for each pipe fd
  1128. if($fd > $maxfileno) {
  1129. $maxfileno = $fd;
  1130. }
  1131. }
  1132. $maxfileno || die "Internal error: no runners are available to wait on\n";
  1133. # Wait for any pipe from any runner to be ready
  1134. # This may be interrupted and return EINTR, but this is ignored and the
  1135. # caller will need to later call this function again.
  1136. # TODO: this is relatively slow with hundreds of fds
  1137. my $ein = $rin;
  1138. if(select(my $rout=$rin, undef, my $eout=$ein, $blocking) >= 1) {
  1139. for my $fd (0..$maxfileno) {
  1140. # Return an error condition first in case it's both
  1141. if(vec($eout, $fd, 1)) {
  1142. return (undef, $idbyfileno{$fd});
  1143. }
  1144. if(vec($rout, $fd, 1)) {
  1145. return ($idbyfileno{$fd}, undef);
  1146. }
  1147. }
  1148. die "Internal pipe readiness inconsistency\n";
  1149. }
  1150. return (undef, undef);
  1151. }
  1152. ###################################################################
  1153. # Cleanly abort and exit the runner
  1154. # This uses print since there is no longer any controller to write logs.
  1155. sub runnerabort{
  1156. print "Controller is gone: runner $$ for $LOGDIR exiting\n";
  1157. my ($error, $logs) = runner_stopservers();
  1158. print $logs;
  1159. runner_shutdown();
  1160. }
  1161. ###################################################################
  1162. # Receive an IPC call in the runner and execute it
  1163. # The IPC is read from the $runnerr pipe and the response is
  1164. # written to the $runnerw pipe
  1165. # Returns 0 if more IPC calls are expected or 1 if the runner should exit
  1166. sub ipcrecv {
  1167. my $err;
  1168. my $datalen;
  1169. while(! defined ($err = sysread($runnerr, $datalen, 4)) || $err <= 0) {
  1170. if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
  1171. # pipe has closed; controller is gone and we must exit
  1172. runnerabort();
  1173. # Special case: no response will be forthcoming
  1174. return 1;
  1175. }
  1176. # system call was interrupted, probably by ^C; restart it so we stay in sync
  1177. }
  1178. my $len=unpack("L", $datalen);
  1179. my $buf;
  1180. while(! defined ($err = sysread($runnerr, $buf, $len)) || $err <= 0) {
  1181. if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
  1182. # pipe has closed; controller is gone and we must exit
  1183. runnerabort();
  1184. # Special case: no response will be forthcoming
  1185. return 1;
  1186. }
  1187. # system call was interrupted, probably by ^C; restart it so we stay in sync
  1188. }
  1189. # Decode the function name and arguments
  1190. my $argsarrayref = thaw $buf;
  1191. # The name of the function to call is the frist argument
  1192. my $funcname = shift @$argsarrayref;
  1193. # print "ipcrecv $funcname\n";
  1194. # Synchronously call the desired function
  1195. my @res;
  1196. if($funcname eq "runner_clearlocks") {
  1197. @res = runner_clearlocks(@$argsarrayref);
  1198. }
  1199. elsif($funcname eq "runner_shutdown") {
  1200. runner_shutdown(@$argsarrayref);
  1201. # Special case: no response will be forthcoming
  1202. return 1;
  1203. }
  1204. elsif($funcname eq "runner_stopservers") {
  1205. @res = runner_stopservers(@$argsarrayref);
  1206. }
  1207. elsif($funcname eq "runner_test_preprocess") {
  1208. @res = runner_test_preprocess(@$argsarrayref);
  1209. }
  1210. elsif($funcname eq "runner_test_run") {
  1211. @res = runner_test_run(@$argsarrayref);
  1212. } else {
  1213. die "Unknown IPC function $funcname\n";
  1214. }
  1215. # print "ipcrecv results\n";
  1216. # Marshall the results to return
  1217. $buf = freeze \@res;
  1218. while(! defined ($err = syswrite($runnerw, (pack "L", length($buf)) . $buf)) || $err <= 0) {
  1219. if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
  1220. # pipe has closed; controller is gone and we must exit
  1221. runnerabort();
  1222. # Special case: no response will be forthcoming
  1223. return 1;
  1224. }
  1225. # system call was interrupted, probably by ^C; restart it so we stay in sync
  1226. }
  1227. return 0;
  1228. }
  1229. ###################################################################
  1230. # Kill the server processes that still have lock files in a directory
  1231. sub runner_clearlocks {
  1232. my ($lockdir)=@_;
  1233. if(clearlogs()) {
  1234. logmsg "Warning: log messages were lost\n";
  1235. }
  1236. clearlocks($lockdir);
  1237. return clearlogs();
  1238. }
  1239. ###################################################################
  1240. # Kill all server processes
  1241. sub runner_stopservers {
  1242. my $error = stopservers($verbose);
  1243. my $logs = clearlogs();
  1244. return ($error, $logs);
  1245. }
  1246. ###################################################################
  1247. # Shut down this runner
  1248. sub runner_shutdown {
  1249. close($runnerr);
  1250. undef $runnerr;
  1251. close($runnerw);
  1252. undef $runnerw;
  1253. }
  1254. 1;