Skip to content

Commit

Permalink
Merge pull request #99 from jbenden/resource-warnings
Browse files Browse the repository at this point in the history
Fix subprocess.Popen handle leakage
  • Loading branch information
Thomas Lehmann committed Aug 14, 2018
2 parents ea895a2 + ffd2a88 commit c034795
Showing 1 changed file with 29 additions and 15 deletions.
44 changes: 29 additions & 15 deletions spline/components/bash.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# pylint: disable=too-many-instance-attributes
import contextlib
import sys
import os
import shlex
Expand All @@ -28,6 +29,18 @@
from spline.tools.event import Event


@contextlib.contextmanager
def managed_process(process):
"""Wrapper for subprocess.Popen to work across various Python versions, when using the with syntax."""
try:
yield process
finally:
for stream in [process.stdout, process.stdin, process.stderr]:
if stream:
stream.close()
process.wait()


class Bash(object):
"""Wrapper for Bash execution."""

Expand Down Expand Up @@ -134,23 +147,24 @@ def render_bash_options(self):
def process_script(self, filename):
"""Running the Bash code."""
try:
process = subprocess.Popen(shlex.split("bash %s" % filename),
stdout=self.stdout, stderr=self.stderr,
shell=self.shell, env=self.env) # nosec
for line in iter(process.stdout.readline, ' '):
if not line:
break
yield line[0:-1].decode('utf-8')
process.wait()
self.exit_code = process.returncode
self.success = (process.returncode == 0)
if not self.config.internal:
if process.returncode == 0:
self.logger.info("Exit code has been %d", process.returncode)
else:
self.logger.error("Exit code has been %d", process.returncode)
with managed_process(subprocess.Popen(shlex.split("bash %s" % filename),
stdout=self.stdout, stderr=self.stderr,
shell=self.shell, env=self.env)) as process: # nosec
for line in iter(process.stdout.readline, ' '):
if not line:
break
yield line[0:-1].decode('utf-8')
process.wait()
self.exit_code = process.returncode
self.success = (process.returncode == 0)
if not self.config.internal:
if process.returncode == 0:
self.logger.info("Exit code has been %d", process.returncode)
else:
self.logger.error("Exit code has been %d", process.returncode)
except OSError as exception:
self.exit_code = 1
self.success = False
yield str(exception)

def process_file(self, filename):
Expand Down

0 comments on commit c034795

Please sign in to comment.