From: Brett Smith Date: Tue, 27 May 2014 14:49:13 +0000 (-0400) Subject: 2752: Avoid hiccup on arv-put with short stdin. X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/44203eefb793d8523e895d417ab4b726f63ec4c9 2752: Avoid hiccup on arv-put with short stdin. Trying to call os.stat(os.path.realpath('/dev/stdin')) usually fails in this case. Since we're never going to be able to resume from stdin anyway, don't bother with that check in this case. --- diff --git a/sdk/python/arvados/collection.py b/sdk/python/arvados/collection.py index 32c45289c2..41adc88db1 100644 --- a/sdk/python/arvados/collection.py +++ b/sdk/python/arvados/collection.py @@ -443,15 +443,22 @@ class ResumableCollectionWriter(CollectionWriter): raise errors.AssertionError("{} not a file path".format(source)) try: path_stat = os.stat(src_path) - except OSError as error: - raise errors.AssertionError( - "could not stat {}: {}".format(source, error)) + except OSError as stat_error: + path_stat = None super(ResumableCollectionWriter, self)._queue_file(source, filename) fd_stat = os.fstat(self._queued_file.fileno()) - if path_stat.st_ino != fd_stat.st_ino: + if not S_ISREG(fd_stat.st_mode): + # We won't be able to resume from this cache anyway, so don't + # worry about further checks. + self._dependencies[source] = tuple(fd_stat) + elif path_stat is None: + raise errors.AssertionError( + "could not stat {}: {}".format(source, stat_error)) + elif path_stat.st_ino != fd_stat.st_ino: raise errors.AssertionError( "{} changed between open and stat calls".format(source)) - self._dependencies[src_path] = tuple(fd_stat) + else: + self._dependencies[src_path] = tuple(fd_stat) def write(self, data): if self._queued_file is None: diff --git a/sdk/python/tests/test_arv-put.py b/sdk/python/tests/test_arv-put.py index cd0e9658eb..2e572854f5 100644 --- a/sdk/python/tests/test_arv-put.py +++ b/sdk/python/tests/test_arv-put.py @@ -4,7 +4,10 @@ import os import re import shutil +import subprocess +import sys import tempfile +import time import unittest import arvados @@ -319,6 +322,25 @@ class ArvadosPutTest(ArvadosKeepLocalStoreTestCase): '098f6bcd4621d373cade4e832627b4f6')), "did not find file stream in Keep store") + def test_short_put_from_stdin(self): + # Have to run this separately since arv-put can't read from the + # tests' stdin. + # arv-put usually can't stat(os.path.realpath('/dev/stdin')) in this + # case, because the /proc entry is already gone by the time it tries. + pipe = subprocess.Popen( + [sys.executable, arv_put.__file__, '--stream'], + stdin=subprocess.PIPE, stdout=subprocess.PIPE) + pipe.stdin.write('stdin test\n') + pipe.stdin.close() + deadline = time.time() + 5 + while (pipe.poll() is None) and (time.time() < deadline): + time.sleep(.1) + if pipe.returncode is None: + pipe.terminate() + self.fail("arv-put did not PUT from stdin within 5 seconds") + self.assertEquals(pipe.returncode, 0) + self.assertIn('4a9c8b735dce4b5fa3acf221a0b13628+11', pipe.stdout.read()) + if __name__ == '__main__': unittest.main()