Skip to content

Commit be4441a

Browse files
committed
Set stdout and stderr to blocking after running an external command
Some nodejs executables set stdout and/or stderr to non-blocking, which can trigger an IOError when the collectstatic command prints more than 1024 bytes at a time to stdout or stderr
1 parent 9d7c6c0 commit be4441a

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

pipeline/compilers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from pipeline.conf import settings
1414
from pipeline.exceptions import CompilerError
15-
from pipeline.utils import to_class
15+
from pipeline.utils import to_class, set_std_streams_blocking
1616

1717

1818
class Compiler(object):
@@ -120,6 +120,7 @@ def execute_command(self, command, cwd=None, stdout_captured=None):
120120
stdout=stdout,
121121
stderr=subprocess.PIPE)
122122
_, stderr = compiling.communicate()
123+
set_std_streams_blocking()
123124

124125
if compiling.returncode != 0:
125126
stdout_captured = None # Don't save erroneous result.

pipeline/compressors/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from pipeline.conf import settings
1616
from pipeline.exceptions import CompressorError
17-
from pipeline.utils import to_class, relpath
17+
from pipeline.utils import to_class, relpath, set_std_streams_blocking
1818

1919
URL_DETECTOR = r"""url\((['"]){0,1}\s*(.*?)["']{0,1}\)"""
2020
URL_REPLACER = r"""url\(__EMBED__(.+?)(\?\d+)?\)"""
@@ -248,6 +248,7 @@ def execute_command(self, command, content):
248248
if content:
249249
content = smart_bytes(content)
250250
stdout, stderr = pipe.communicate(content)
251+
set_std_streams_blocking()
251252
if stderr.strip() and pipe.returncode != 0:
252253
raise CompressorError(stderr)
253254
elif self.verbose:

pipeline/utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
from __future__ import unicode_literals
22

3+
try:
4+
import fcntl
5+
except ImportError:
6+
# windows
7+
fcntl = None
8+
39
import importlib
410
import mimetypes
511
import posixpath
12+
import os
13+
import sys
614

715
try:
816
from urllib.parse import quote
@@ -54,3 +62,12 @@ def relpath(path, start=posixpath.curdir):
5462
if not rel_list:
5563
return posixpath.curdir
5664
return posixpath.join(*rel_list)
65+
66+
67+
def set_std_streams_blocking():
68+
if not fcntl:
69+
return
70+
for f in (sys.__stdout__, sys.__stderr__):
71+
fileno = f.fileno()
72+
flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
73+
fcntl.fcntl(fileno, fcntl.F_SETFL, flags & ~os.O_NONBLOCK)

0 commit comments

Comments
 (0)