2
0

runner.pm 48 KB

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