arvados-cli 0.1.20141006182226 → 0.1.20141006212502

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/crunch-job +227 -155
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dda195888cf5d8edd4cd36823fa416d43ceefd6a
4
- data.tar.gz: 7de92aa09c4f47fc65704a4aecf48b568e82d73c
3
+ metadata.gz: b84e06d6def466e49e5c53c836efe17babcc9267
4
+ data.tar.gz: 957bec18268b60540dd207a9b53d3b1bb45164de
5
5
  SHA512:
6
- metadata.gz: 3e4bc3c2153dd7a015976950935b338bbe796df5839f7d2073f342ff0c3f54ef5b21b9c7f7ad289f0bde5864ab9e11a1d0cb2149d74c1d880308ac3f88f38111
7
- data.tar.gz: a9fd3975250cc52032538fc740ac8b48acd223e2a9b603a9c2198b64f51608cafefe0fb513a1548b135d2068aecd7888d43989ed08b63cf52cd1c8ff4c2f217d
6
+ metadata.gz: a6dd627d31352cdb3a0958516090466fc0bcf1e5b2d85f66189023642a7258f89d25dce7b90d4b53223b5bf3176e716bbe2082a7ecc6adafa9edfc4f6ce22bcd
7
+ data.tar.gz: 9a2321cb216a5c8bd596137a78e4c846cee688eacde21322486a81986fd46c799c0f765816f8effbb2467296cfefd0d7b397a5e408ae6e035df379ea75fea54c
data/bin/crunch-job CHANGED
@@ -83,7 +83,7 @@ use IPC::Open2;
83
83
  use IO::Select;
84
84
  use File::Temp;
85
85
  use Fcntl ':flock';
86
- use File::Path qw( make_path );
86
+ use File::Path qw( make_path remove_tree );
87
87
 
88
88
  use constant EX_TEMPFAIL => 75;
89
89
 
@@ -125,8 +125,7 @@ if (defined $job_api_token) {
125
125
  }
126
126
 
127
127
  my $have_slurm = exists $ENV{SLURM_JOBID} && exists $ENV{SLURM_NODELIST};
128
- my $job_has_uuid = $jobspec =~ /^[-a-z\d]+$/;
129
- my $local_job = !$job_has_uuid;
128
+ my $local_job = 0;
130
129
 
131
130
 
132
131
  $SIG{'USR1'} = sub
@@ -144,12 +143,13 @@ my $arv = Arvados->new('apiVersion' => 'v1');
144
143
 
145
144
  my $User = $arv->{'users'}->{'current'}->execute;
146
145
 
147
- my $Job = {};
146
+ my $Job;
148
147
  my $job_id;
149
148
  my $dbh;
150
149
  my $sth;
151
- if ($job_has_uuid)
150
+ if ($jobspec =~ /^[-a-z\d]+$/)
152
151
  {
152
+ # $jobspec is an Arvados UUID, not a JSON job specification
153
153
  $Job = $arv->{'jobs'}->{'get'}->execute('uuid' => $jobspec);
154
154
  if (!$force_unlock) {
155
155
  # Claim this job, and make sure nobody else does
@@ -175,10 +175,9 @@ else
175
175
 
176
176
  $Job->{'is_locked_by_uuid'} = $User->{'uuid'};
177
177
  $Job->{'started_at'} = gmtime;
178
+ $Job->{'state'} = 'Running';
178
179
 
179
180
  $Job = $arv->{'jobs'}->{'create'}->execute('job' => $Job);
180
-
181
- $job_has_uuid = 1;
182
181
  }
183
182
  $job_id = $Job->{'uuid'};
184
183
 
@@ -330,137 +329,202 @@ if (!$have_slurm)
330
329
 
331
330
 
332
331
  my $build_script;
332
+ do {
333
+ local $/ = undef;
334
+ $build_script = <DATA>;
335
+ };
336
+ my $nodelist = join(",", @node);
333
337
 
338
+ if (!defined $no_clear_tmp) {
339
+ # Clean out crunch_tmp/work, crunch_tmp/opt, crunch_tmp/src*
340
+ Log (undef, "Clean work dirs");
334
341
 
335
- $ENV{"CRUNCH_SRC_COMMIT"} = $Job->{script_version};
336
-
337
- my $skip_install = ($local_job && $Job->{script_version} =~ m{^/});
338
- if ($skip_install)
339
- {
340
- if (!defined $no_clear_tmp) {
341
- my $clear_tmp_cmd = 'rm -rf $JOB_WORK $CRUNCH_TMP/opt $CRUNCH_TMP/src*';
342
- system($clear_tmp_cmd) == 0
343
- or croak ("`$clear_tmp_cmd` failed: ".($?>>8));
344
- }
345
- $ENV{"CRUNCH_SRC"} = $Job->{script_version};
346
- for my $src_path ("$ENV{CRUNCH_SRC}/arvados/sdk/python") {
347
- if (-d $src_path) {
348
- system("virtualenv", "$ENV{CRUNCH_TMP}/opt") == 0
349
- or croak ("virtualenv $ENV{CRUNCH_TMP}/opt failed: exit ".($?>>8));
350
- system ("cd $src_path && ./build.sh && \$CRUNCH_TMP/opt/bin/python setup.py install")
351
- == 0
352
- or croak ("setup.py in $src_path failed: exit ".($?>>8));
353
- }
342
+ my $cleanpid = fork();
343
+ if ($cleanpid == 0)
344
+ {
345
+ srun (["srun", "--nodelist=$nodelist", "-D", $ENV{'TMPDIR'}],
346
+ ['bash', '-c', 'if mount | grep -q $JOB_WORK/; then for i in $JOB_WORK/*keep; do /bin/fusermount -z -u $i; done; fi; sleep 1; rm -rf $JOB_WORK $CRUNCH_TMP/opt $CRUNCH_TMP/src*']);
347
+ exit (1);
354
348
  }
349
+ while (1)
350
+ {
351
+ last if $cleanpid == waitpid (-1, WNOHANG);
352
+ freeze_if_want_freeze ($cleanpid);
353
+ select (undef, undef, undef, 0.1);
354
+ }
355
+ Log (undef, "Cleanup command exited ".exit_status_s($?));
355
356
  }
356
- else
357
- {
358
- do {
359
- local $/ = undef;
360
- $build_script = <DATA>;
361
- };
362
- Log (undef, "Install revision ".$Job->{script_version});
363
- my $nodelist = join(",", @node);
364
357
 
365
- if (!defined $no_clear_tmp) {
366
- # Clean out crunch_tmp/work, crunch_tmp/opt, crunch_tmp/src*
367
358
 
368
- my $cleanpid = fork();
369
- if ($cleanpid == 0)
370
- {
371
- srun (["srun", "--nodelist=$nodelist", "-D", $ENV{'TMPDIR'}],
372
- ['bash', '-c', 'if mount | grep -q $JOB_WORK/; then for i in $JOB_WORK/*keep; do /bin/fusermount -z -u $i; done; fi; sleep 1; rm -rf $JOB_WORK $CRUNCH_TMP/opt $CRUNCH_TMP/src*']);
373
- exit (1);
374
- }
375
- while (1)
376
- {
377
- last if $cleanpid == waitpid (-1, WNOHANG);
378
- freeze_if_want_freeze ($cleanpid);
379
- select (undef, undef, undef, 0.1);
380
- }
381
- Log (undef, "Clean-work-dir exited $?");
382
- }
359
+ my $git_archive;
360
+ if (!defined $git_dir && $Job->{'script_version'} =~ m{^/}) {
361
+ # If we're in user-land (i.e., not called from crunch-dispatch)
362
+ # script_version can be an absolute directory path, signifying we
363
+ # should work straight out of that directory instead of using a git
364
+ # commit.
365
+ $ENV{"CRUNCH_SRC_COMMIT"} = $Job->{'script_version'};
366
+ $ENV{"CRUNCH_SRC"} = $Job->{'script_version'};
367
+ }
368
+ else {
369
+ $ENV{"CRUNCH_SRC"} = "$ENV{CRUNCH_TMP}/src";
383
370
 
384
371
  # Install requested code version
385
-
386
- my @execargs;
387
- my @srunargs = ("srun",
388
- "--nodelist=$nodelist",
389
- "-D", $ENV{'TMPDIR'}, "--job-name=$job_id");
372
+ Log (undef, "Looking for version ".$Job->{script_version}." from repository ".$Job->{repository});
390
373
 
391
374
  $ENV{"CRUNCH_SRC_COMMIT"} = $Job->{script_version};
392
- $ENV{"CRUNCH_SRC"} = "$ENV{CRUNCH_TMP}/src";
393
-
394
- my $commit;
395
- my $git_archive;
396
- my $treeish = $Job->{'script_version'};
397
375
 
398
- # If we're running under crunch-dispatch, it will have pulled the
399
- # appropriate source tree into its own repository, and given us that
400
- # repo's path as $git_dir. If we're running a "local" job, and a
401
- # script_version was specified, it's up to the user to provide the
402
- # full path to a local repository in Job->{repository}.
376
+ # If we're running under crunch-dispatch, it will have already
377
+ # pulled the appropriate source tree into its own repository, and
378
+ # given us that repo's path as $git_dir.
403
379
  #
404
- # TODO: Accept URLs too, not just local paths. Use git-ls-remote and
405
- # git-archive --remote where appropriate.
380
+ # If we're running a "local" job, we might have to fetch content
381
+ # from a remote repository.
406
382
  #
407
- # TODO: Accept a locally-hosted Arvados repository by name or
408
- # UUID. Use arvados.v1.repositories.list or .get to figure out the
409
- # appropriate fetch-url.
410
- my $repo = $git_dir || $ENV{'CRUNCH_DEFAULT_GIT_DIR'} || $Job->{'repository'};
411
-
383
+ # (Currently crunch-dispatch gives a local path with --git-dir, but
384
+ # we might as well accept URLs there too in case it changes its
385
+ # mind.)
386
+ my $repo = $git_dir || $Job->{'repository'};
387
+
388
+ # Repository can be remote or local. If remote, we'll need to fetch it
389
+ # to a local dir before doing `git log` et al.
390
+ my $repo_location;
391
+
392
+ if ($repo =~ m{://|^[^/]*:}) {
393
+ # $repo is a git url we can clone, like git:// or https:// or
394
+ # file:/// or [user@]host:repo.git. Note "user/name@host:foo" is
395
+ # not recognized here because distinguishing that from a local
396
+ # path is too fragile. If you really need something strange here,
397
+ # use the ssh:// form.
398
+ $repo_location = 'remote';
399
+ } elsif ($repo =~ m{^\.*/}) {
400
+ # $repo is a local path to a git index. We'll also resolve ../foo
401
+ # to ../foo/.git if the latter is a directory. To help
402
+ # disambiguate local paths from named hosted repositories, this
403
+ # form must be given as ./ or ../ if it's a relative path.
404
+ if (-d "$repo/.git") {
405
+ $repo = "$repo/.git";
406
+ }
407
+ $repo_location = 'local';
408
+ } else {
409
+ # $repo is none of the above. It must be the name of a hosted
410
+ # repository.
411
+ my $arv_repo_list = $arv->{'repositories'}->{'list'}->execute(
412
+ 'filters' => [['name','=',$repo]]
413
+ )->{'items'};
414
+ my $n_found = scalar @{$arv_repo_list};
415
+ if ($n_found > 0) {
416
+ Log(undef, "Repository '$repo' -> "
417
+ . join(", ", map { $_->{'uuid'} } @{$arv_repo_list}));
418
+ }
419
+ if ($n_found != 1) {
420
+ croak("Error: Found $n_found repositories with name '$repo'.");
421
+ }
422
+ $repo = $arv_repo_list->[0]->{'fetch_url'};
423
+ $repo_location = 'remote';
424
+ }
425
+ Log(undef, "Using $repo_location repository '$repo'");
412
426
  $ENV{"CRUNCH_SRC_URL"} = $repo;
413
427
 
414
- if (-d "$repo/.git") {
415
- # We were given a working directory, but we are only interested in
416
- # the index.
417
- $repo = "$repo/.git";
418
- }
428
+ # Resolve given script_version (we'll call that $treeish here) to a
429
+ # commit sha1 ($commit).
430
+ my $treeish = $Job->{'script_version'};
431
+ my $commit;
432
+ if ($repo_location eq 'remote') {
433
+ # We minimize excess object-fetching by re-using the same bare
434
+ # repository in CRUNCH_TMP/.git for multiple crunch-jobs -- we
435
+ # just keep adding remotes to it as needed.
436
+ my $local_repo = $ENV{'CRUNCH_TMP'}."/.git";
437
+ my $gitcmd = "git --git-dir=\Q$local_repo\E";
438
+
439
+ # Set up our local repo for caching remote objects, making
440
+ # archives, etc.
441
+ if (!-d $local_repo) {
442
+ make_path($local_repo) or croak("Error: could not create $local_repo");
443
+ }
444
+ # This works (exits 0 and doesn't delete fetched objects) even
445
+ # if $local_repo is already initialized:
446
+ `$gitcmd init --bare`;
447
+ if ($?) {
448
+ croak("Error: $gitcmd init --bare exited ".exit_status_s($?));
449
+ }
450
+
451
+ # If $treeish looks like a hash (or abbrev hash) we look it up in
452
+ # our local cache first, since that's cheaper. (We don't want to
453
+ # do that with tags/branches though -- those change over time, so
454
+ # they should always be resolved by the remote repo.)
455
+ if ($treeish =~ /^[0-9a-f]{3,40}$/s) {
456
+ # Hide stderr because it's normal for this to fail:
457
+ my $sha1 = `$gitcmd rev-list -n1 ''\Q$treeish\E 2>/dev/null`;
458
+ if ($? == 0 &&
459
+ $sha1 =~ /^$treeish/ && # Don't use commit 123 @ branch abc!
460
+ $sha1 =~ /^([0-9a-f]{40})$/s) {
461
+ $commit = $1;
462
+ Log(undef, "Commit $commit already present in $local_repo");
463
+ }
464
+ }
465
+
466
+ if (!defined $commit) {
467
+ # If $treeish isn't just a hash or abbrev hash, or isn't here
468
+ # yet, we need to fetch the remote to resolve it correctly.
419
469
 
420
- # If this looks like a subversion r#, look for it in git-svn commit messages
470
+ # First, remove all local heads. This prevents a name that does
471
+ # not exist on the remote from resolving to (or colliding with)
472
+ # a previously fetched branch or tag (possibly from a different
473
+ # remote).
474
+ remove_tree("$local_repo/refs/heads", {keep_root => 1});
421
475
 
422
- if ($treeish =~ m{^\d{1,4}$}) {
423
- my $gitlog = `git --git-dir=\Q$repo\E log --pretty="format:%H" --grep="git-svn-id:.*\@"\Q$treeish\E" " master`;
424
- chomp $gitlog;
425
- Log(undef, "git Subversion search exited $?");
426
- if (($? == 0) && ($gitlog =~ /^[a-f0-9]{40}$/)) {
427
- $commit = $gitlog;
428
- Log(undef, "Using commit $commit for Subversion revision $treeish");
476
+ Log(undef, "Fetching objects from $repo to $local_repo");
477
+ `$gitcmd fetch --no-progress --tags ''\Q$repo\E \Q+refs/heads/*:refs/heads/*\E`;
478
+ if ($?) {
479
+ croak("Error: `$gitcmd fetch` exited ".exit_status_s($?));
480
+ }
429
481
  }
482
+
483
+ # Now that the data is all here, we will use our local repo for
484
+ # the rest of our git activities.
485
+ $repo = $local_repo;
430
486
  }
431
487
 
432
- # If that didn't work, try asking git to look it up as a tree-ish.
433
-
434
- if (!defined $commit) {
435
- my $found = `git --git-dir=\Q$repo\E rev-list -1 ''\Q$treeish\E`;
436
- chomp $found;
437
- Log(undef, "git rev-list exited $? with result '$found'");
438
- if (($? == 0) && ($found =~ /^[0-9a-f]{40}$/s)) {
439
- $commit = $found;
440
- Log(undef, "Using commit $commit for tree-ish $treeish");
441
- if ($commit ne $treeish) {
442
- # Make sure we record the real commit id in the database,
443
- # frozentokey, logs, etc. -- instead of an abbreviation or a
444
- # branch name which can become ambiguous or point to a
445
- # different commit in the future.
446
- $Job->{'script_version'} = $commit;
447
- !$job_has_uuid or
448
- $Job->update_attributes('script_version' => $commit) or
449
- croak("Error while updating job");
450
- }
488
+ my $gitcmd = "git --git-dir=\Q$repo\E";
489
+ my $sha1 = `$gitcmd rev-list -n1 ''\Q$treeish\E`;
490
+ unless ($? == 0 && $sha1 =~ /^([0-9a-f]{40})$/) {
491
+ croak("`$gitcmd rev-list` exited "
492
+ .exit_status_s($?)
493
+ .", '$treeish' not found. Giving up.");
494
+ }
495
+ $commit = $1;
496
+ Log(undef, "Version $treeish is commit $commit");
497
+
498
+ if ($commit ne $Job->{'script_version'}) {
499
+ # Record the real commit id in the database, frozentokey, logs,
500
+ # etc. -- instead of an abbreviation or a branch name which can
501
+ # become ambiguous or point to a different commit in the future.
502
+ if (!$Job->update_attributes('script_version' => $commit)) {
503
+ croak("Error: failed to update job's script_version attribute");
451
504
  }
452
505
  }
453
506
 
454
- if (defined $commit) {
455
- $ENV{"CRUNCH_SRC_COMMIT"} = $commit;
456
- @execargs = ("sh", "-c",
457
- "mkdir -p $ENV{CRUNCH_INSTALL} && cd $ENV{CRUNCH_TMP} && perl -");
458
- $git_archive = `git --git-dir=\Q$repo\E archive ''\Q$commit\E`;
459
- croak("git archive failed: exit " . ($? >> 8)) if ($? != 0);
507
+ $ENV{"CRUNCH_SRC_COMMIT"} = $commit;
508
+ $git_archive = `$gitcmd archive ''\Q$commit\E`;
509
+ if ($?) {
510
+ croak("Error: $gitcmd archive exited ".exit_status_s($?));
460
511
  }
461
- else {
462
- croak ("could not figure out commit id for $treeish");
512
+ }
513
+
514
+ if (!defined $git_archive) {
515
+ Log(undef, "Skip install phase (no git archive)");
516
+ if ($have_slurm) {
517
+ Log(undef, "Warning: This probably means workers have no source tree!");
463
518
  }
519
+ }
520
+ else {
521
+ Log(undef, "Run install script on all workers");
522
+
523
+ my @srunargs = ("srun",
524
+ "--nodelist=$nodelist",
525
+ "-D", $ENV{'TMPDIR'}, "--job-name=$job_id");
526
+ my @execargs = ("sh", "-c",
527
+ "mkdir -p $ENV{CRUNCH_INSTALL} && cd $ENV{CRUNCH_TMP} && perl -");
464
528
 
465
529
  # Note: this section is almost certainly unnecessary if we're
466
530
  # running tasks in docker containers.
@@ -476,7 +540,7 @@ else
476
540
  freeze_if_want_freeze ($installpid);
477
541
  select (undef, undef, undef, 0.1);
478
542
  }
479
- Log (undef, "Install exited $?");
543
+ Log (undef, "Install script exited ".exit_status_s($?));
480
544
  }
481
545
 
482
546
  if (!$have_slurm)
@@ -515,7 +579,8 @@ fi
515
579
  }
516
580
  if ($? != 0)
517
581
  {
518
- croak("Installing Docker image from $docker_locator returned exit code $?");
582
+ croak("Installing Docker image from $docker_locator exited "
583
+ .exit_status_s($?));
519
584
  }
520
585
  }
521
586
 
@@ -838,7 +903,7 @@ else {
838
903
  });
839
904
  Log(undef, "output uuid " . $output->{uuid});
840
905
  Log(undef, "output hash " . $output->{portable_data_hash});
841
- $Job->update_attributes('output' => $output->{portable_data_hash}) if $job_has_uuid;
906
+ $Job->update_attributes('output' => $output->{portable_data_hash});
842
907
  };
843
908
  if ($@) {
844
909
  Log (undef, "Failed to register output manifest: $@");
@@ -849,15 +914,15 @@ Log (undef, "finish");
849
914
 
850
915
  save_meta();
851
916
 
852
- if ($job_has_uuid) {
853
- if ($collated_output && $main::success) {
854
- $Job->update_attributes('state' => 'Complete')
855
- } else {
856
- $Job->update_attributes('state' => 'Failed')
857
- }
917
+ my $final_state;
918
+ if ($collated_output && $main::success) {
919
+ $final_state = 'Complete';
920
+ } else {
921
+ $final_state = 'Failed';
858
922
  }
923
+ $Job->update_attributes('state' => $final_state);
859
924
 
860
- exit ($Job->{'state'} != 'Complete' ? 1 : 0);
925
+ exit (($final_state eq 'Complete') ? 0 : 1);
861
926
 
862
927
 
863
928
 
@@ -872,9 +937,7 @@ sub update_progress_stats
872
937
  $Job->{'tasks_summary'}->{'todo'} = $todo;
873
938
  $Job->{'tasks_summary'}->{'done'} = $done;
874
939
  $Job->{'tasks_summary'}->{'running'} = $running;
875
- if ($job_has_uuid) {
876
- $Job->update_attributes('tasks_summary' => $Job->{'tasks_summary'});
877
- }
940
+ $Job->update_attributes('tasks_summary' => $Job->{'tasks_summary'});
878
941
  Log (undef, "status: $done done, $running running, $todo todo");
879
942
  $progress_is_dirty = 0;
880
943
  }
@@ -895,10 +958,7 @@ sub reapchildren
895
958
 
896
959
  my $childstatus = $?;
897
960
  my $exitvalue = $childstatus >> 8;
898
- my $exitinfo = sprintf("exit %d signal %d%s",
899
- $exitvalue,
900
- $childstatus & 127,
901
- ($childstatus & 128 ? ' core dump' : ''));
961
+ my $exitinfo = "exit ".exit_status_s($childstatus);
902
962
  $Jobstep->{'arvados_task'}->reload;
903
963
  my $task_success = $Jobstep->{'arvados_task'}->{success};
904
964
 
@@ -944,10 +1004,8 @@ sub reapchildren
944
1004
  $main::success = 0;
945
1005
  $main::please_freeze = 1;
946
1006
  }
947
- else {
948
- # Put this task back on the todo queue
949
- push @jobstep_todo, $jobstepid;
950
- }
1007
+ # Put this task back on the todo queue
1008
+ push @jobstep_todo, $jobstepid;
951
1009
  $Job->{'tasks_summary'}->{'failed'}++;
952
1010
  }
953
1011
  else
@@ -1005,23 +1063,21 @@ sub check_refresh_wanted
1005
1063
  my @stat = stat $ENV{"CRUNCH_REFRESH_TRIGGER"};
1006
1064
  if (@stat && $stat[9] > $latest_refresh) {
1007
1065
  $latest_refresh = scalar time;
1008
- if ($job_has_uuid) {
1009
- my $Job2 = $arv->{'jobs'}->{'get'}->execute('uuid' => $jobspec);
1010
- for my $attr ('cancelled_at',
1011
- 'cancelled_by_user_uuid',
1012
- 'cancelled_by_client_uuid',
1013
- 'state') {
1014
- $Job->{$attr} = $Job2->{$attr};
1015
- }
1016
- if ($Job->{'state'} ne "Running") {
1017
- if ($Job->{'state'} eq "Cancelled") {
1018
- Log (undef, "Job cancelled at " . $Job->{'cancelled_at'} . " by user " . $Job->{'cancelled_by_user_uuid'});
1019
- } else {
1020
- Log (undef, "Job state unexpectedly changed to " . $Job->{'state'});
1021
- }
1022
- $main::success = 0;
1023
- $main::please_freeze = 1;
1066
+ my $Job2 = $arv->{'jobs'}->{'get'}->execute('uuid' => $jobspec);
1067
+ for my $attr ('cancelled_at',
1068
+ 'cancelled_by_user_uuid',
1069
+ 'cancelled_by_client_uuid',
1070
+ 'state') {
1071
+ $Job->{$attr} = $Job2->{$attr};
1072
+ }
1073
+ if ($Job->{'state'} ne "Running") {
1074
+ if ($Job->{'state'} eq "Cancelled") {
1075
+ Log (undef, "Job cancelled at " . $Job->{'cancelled_at'} . " by user " . $Job->{'cancelled_by_user_uuid'});
1076
+ } else {
1077
+ Log (undef, "Job state unexpectedly changed to " . $Job->{'state'});
1024
1078
  }
1079
+ $main::success = 0;
1080
+ $main::please_freeze = 1;
1025
1081
  }
1026
1082
  }
1027
1083
  }
@@ -1223,10 +1279,13 @@ sub collate_output
1223
1279
  if ($s->can_read(120)) {
1224
1280
  sysread($child_out, $joboutput, 64 * 1024 * 1024);
1225
1281
  chomp($joboutput);
1282
+ # TODO: Ensure exit status == 0.
1226
1283
  } else {
1227
1284
  Log (undef, "timed out reading from 'arv-put'");
1228
1285
  }
1229
1286
  }
1287
+ # TODO: kill $pid instead of waiting, now that we've decided to
1288
+ # ignore further output.
1230
1289
  waitpid($pid, 0);
1231
1290
 
1232
1291
  return $joboutput;
@@ -1331,7 +1390,7 @@ sub log_writer_finish()
1331
1390
  waitpid($log_pipe_pid, 0);
1332
1391
  $log_pipe_pid = $log_pipe_in = $log_pipe_out = undef;
1333
1392
  if ($?) {
1334
- Log("log_writer_finish: arv-put returned error $?")
1393
+ Log("log_writer_finish: arv-put exited ".exit_status_s($?))
1335
1394
  }
1336
1395
 
1337
1396
  return $arv_put_output;
@@ -1374,7 +1433,7 @@ sub croak
1374
1433
  Log (undef, $message);
1375
1434
  freeze() if @jobstep_todo;
1376
1435
  collate_output() if @jobstep_todo;
1377
- cleanup();
1436
+ cleanup() if $Job;
1378
1437
  save_meta() if log_writer_is_active();
1379
1438
  die;
1380
1439
  }
@@ -1382,7 +1441,6 @@ sub croak
1382
1441
 
1383
1442
  sub cleanup
1384
1443
  {
1385
- return if !$job_has_uuid;
1386
1444
  if ($Job->{'state'} eq 'Cancelled') {
1387
1445
  $Job->update_attributes('finished_at' => scalar gmtime);
1388
1446
  } else {
@@ -1399,7 +1457,7 @@ sub save_meta
1399
1457
  my $loglocator = log_writer_finish();
1400
1458
  Log (undef, "log manifest is $loglocator");
1401
1459
  $Job->{'log'} = $loglocator;
1402
- $Job->update_attributes('log', $loglocator) if $job_has_uuid;
1460
+ $Job->update_attributes('log', $loglocator);
1403
1461
  }
1404
1462
 
1405
1463
 
@@ -1427,7 +1485,7 @@ sub freeze_if_want_freeze
1427
1485
  collate_output();
1428
1486
  cleanup();
1429
1487
  save_meta();
1430
- exit 0;
1488
+ exit 1;
1431
1489
  }
1432
1490
  }
1433
1491
 
@@ -1551,6 +1609,20 @@ sub put_retry_count {
1551
1609
  return ($retries > 3) ? $retries : 3;
1552
1610
  }
1553
1611
 
1612
+ sub exit_status_s {
1613
+ # Given a $?, return a human-readable exit code string like "0" or
1614
+ # "1" or "0 with signal 1" or "1 with signal 11".
1615
+ my $exitcode = shift;
1616
+ my $s = $exitcode >> 8;
1617
+ if ($exitcode & 0x7f) {
1618
+ $s .= " with signal " . ($exitcode & 0x7f);
1619
+ }
1620
+ if ($exitcode & 0x80) {
1621
+ $s .= " with core dump";
1622
+ }
1623
+ return $s;
1624
+ }
1625
+
1554
1626
  __DATA__
1555
1627
  #!/usr/bin/perl
1556
1628
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arvados-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.20141006182226
4
+ version: 0.1.20141006212502
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arvados Authors
@@ -178,7 +178,7 @@ dependencies:
178
178
  - - "<"
179
179
  - !ruby/object:Gem::Version
180
180
  version: 1.0.0
181
- description: Arvados command line tools, git commit d65963976174bd9c94fdb0b91eeb8a281f01e7b3
181
+ description: Arvados command line tools, git commit 38cc5c0a51657c6b60f3d3f32c566845988dfb6b
182
182
  email: gem-dev@curoverse.com
183
183
  executables:
184
184
  - arv