import apt_pkg
 import apt_inst
 import shutil
-import commands
+import subprocess
 import threading
 
 from daklib import utils
                            re_contrib, re_nonfree, re_localhost, re_newlinespace, \
                            re_package, re_doc_directory
 from daklib.dak_exceptions import ChangesUnicodeError
+import daklib.daksubprocess
 
 ################################################################################
 
     tempdir = utils.temp_dirname()
     os.rmdir(tempdir)
 
-    cmd = "dpkg-source --no-check --no-copy -x %s %s" % (dsc_filename, tempdir)
-    (result, output) = commands.getstatusoutput(cmd)
-    if (result != 0):
+    cmd = ('dpkg-source', '--no-check', '--no-copy', '-x', dsc_filename, tempdir)
+    try:
+        daklib.daksubprocess.check_output(cmd, stderr=1)
+    except subprocess.CalledProcessError as e:
         res = "How is education supposed to make me feel smarter? Besides, every time I learn something new, it pushes some\n old stuff out of my brain. Remember when I took that home winemaking course, and I forgot how to drive?\n"
         res += "Error, couldn't extract source, WTF?\n"
-        res += "'dpkg-source -x' failed. return code: %s.\n\n" % (result)
-        res += output
+        res += "'dpkg-source -x' failed. return code: %s.\n\n" % (e.returncode)
+        res += e.output
         return res
 
     path = os.path.join(tempdir, 'debian/README.source')
 
 import pwd
 import apt_pkg, apt_inst
 import examine_package
-import subprocess
+import daklib.daksubprocess
 from sqlalchemy import or_
 
 from daklib.dbconn import *
             changes=changes,
             )
 
-    subprocess.check_call(shell_command, shell=True)
+    daklib.daksubprocess.check_call(shell_command, shell=True)
 
 ################################################################################
 
 
 import daklib.utils as utils
 from daklib.fstransactions import FilesystemTransaction
 from daklib.regexes import re_changelog_versions, re_bin_only_nmu
+import daklib.daksubprocess
 
 import apt_pkg
 from datetime import datetime
 import os
 import shutil
-import subprocess
 from sqlalchemy.orm.exc import NoResultFound
 import sqlalchemy.exc
 import tempfile
         sourcedir = os.path.join(self.directory, 'source')
         if not os.path.exists(sourcedir):
             devnull = open('/dev/null', 'w')
-            subprocess.check_call(["dpkg-source", "--no-copy", "--no-check", "-x", dsc_path, sourcedir], shell=False, stdout=devnull)
+            daklib.daksubprocess.check_call(["dpkg-source", "--no-copy", "--no-check", "-x", dsc_path, sourcedir], shell=False, stdout=devnull)
         if not os.path.isdir(sourcedir):
             raise Exception("{0} is not a directory after extracting source package".format(sourcedir))
         return sourcedir
                 continue
 
             script = rule['Script']
-            retcode = subprocess.call([script, os.path.join(self.directory, f.filename), control['Version'], arch, os.path.join(self.directory, self.changes.filename)], shell=False)
+            retcode = daklib.daksubprocess.call([script, os.path.join(self.directory, f.filename), control['Version'], arch, os.path.join(self.directory, self.changes.filename)], shell=False)
             if retcode != 0:
                 print "W: error processing {0}.".format(f.filename)
                 remaining.append(f)
 
 
 from multiprocessing import Pool
 from shutil import rmtree
-from subprocess import Popen, PIPE, check_call
 from tempfile import mkdtemp
 
+import daklib.daksubprocess
 import os.path
-import signal
 
 class BinaryContentsWriter(object):
     '''
     scanner = BinaryContentsScanner(binary_id)
     scanner.scan()
 
-
-def subprocess_setup():
-    # Python installs a SIGPIPE handler by default. This is usually not what
-    # non-Python subprocesses expect.
-    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
 class UnpackedSource(object):
     '''
     UnpackedSource extracts a source package into a temporary location and
         self.root_directory = os.path.join(temp_directory, 'root')
         command = ('dpkg-source', '--no-copy', '--no-check', '-q', '-x',
             dscfilename, self.root_directory)
-        check_call(command, preexec_fn = subprocess_setup)
+        daklib.daksubprocess.check_call(command)
 
     def get_root_directory(self):
         '''
         scanner.scan()
     except Exception as e:
         print e
-
 
--- /dev/null
+"""subprocess management for dak
+
+@copyright: 2013, Ansgar Burchardt <ansgar@debian.org>
+@license: GPL-2+
+"""
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import signal
+import subprocess
+
+#
+def fix_signal_handlers():
+    """reset signal handlers to default action.
+
+    Python changes the signal handler to SIG_IGN for a few signals which
+    causes unexpected behaviour in child processes. This function resets
+    them to their default action.
+
+    Reference: http://bugs.python.org/issue1652
+    """
+    for signal_name in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'):
+        try:
+            signal_number = getattr(signal, signal_name)
+            signal.signal(signal_number, signal.SIG_DFL)
+        except AttributeError:
+            pass
+
+def _generate_preexec_fn(other_preexec_fn=None):
+    def preexec_fn():
+        fix_signal_handlers()
+        if other_preexec_fn is not None:
+            other_preexec_fn()
+    return preexec_fn
+
+def call(*args, **kwargs):
+    """wrapper around subprocess.call that fixes signal handling"""
+    preexec_fn = _generate_preexec_fn(kwargs.get('preexec_fn'))
+    kwargs['preexec_fn'] = preexec_fn
+    return subprocess.call(*args, **kwargs)
+
+def check_call(*args, **kwargs):
+    """wrapper around subprocess.check_call that fixes signal handling"""
+    preexec_fn = _generate_preexec_fn(kwargs.get('preexec_fn'))
+    kwargs['preexec_fn'] = preexec_fn
+    return subprocess.check_call(*args, **kwargs)
+
+def check_output(*args, **kwargs):
+    """wrapper around subprocess.check_output that fixes signal handling"""
+    preexec_fn = _generate_preexec_fn(kwargs.get('preexec_fn'))
+    kwargs['preexec_fn'] = preexec_fn
+    return subprocess.check_output(*args, **kwargs)
+
+def Popen(*args, **kwargs):
+    """wrapper around subprocess.Popen that fixes signal handling"""
+    preexec_fn = _generate_preexec_fn(kwargs.get('preexec_fn'))
+    kwargs['preexec_fn'] = preexec_fn
+    return subprocess.Popen(*args, **kwargs)
 
 ################################################################################
 
 import apt_pkg
+import daklib.daksubprocess
 import os
 from os.path import normpath
 import re
 import psycopg2
+import subprocess
 import traceback
-import commands
-import signal
 
 try:
     # python >= 2.6
 from datetime import datetime, timedelta
 from errno import ENOENT
 from tempfile import mkstemp, mkdtemp
-from subprocess import Popen, PIPE
 from tarfile import TarFile
 
 from inspect import getargspec
 
 ################################################################################
 
-def subprocess_setup():
-    # Python installs a SIGPIPE handler by default. This is usually not what
-    # non-Python subprocesses expect.
-    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
 class DBBinary(ORMObject):
     def __init__(self, package = None, source = None, version = None, \
         maintainer = None, architecture = None, poolfile = None, \
         package does not contain any regular file.
         '''
         fullpath = self.poolfile.fullpath
-        dpkg = Popen(['dpkg-deb', '--fsys-tarfile', fullpath], stdout = PIPE,
-            preexec_fn = subprocess_setup)
+        dpkg_cmd = ('dpkg-deb', '--fsys-tarfile', fullpath)
+        dpkg = daklib.daksubprocess.Popen(dpkg_cmd, stdout=subprocess.PIPE)
         tar = TarFile.open(fileobj = dpkg.stdout, mode = 'r|')
         for member in tar.getmembers():
             if not member.isdir():
         return session
 
 __all__.append('DBConn')
-
-
 
 
 from daklib.config import Config
 
-from subprocess import check_call
+from daklib.daksubprocess import check_call
 
 import os, os.path
 
 
 import ldap
 
 import daklib.config as config
+import daklib.daksubprocess
 from dbconn import DBConn, get_architecture, get_component, get_suite, \
                    get_override_type, Keyring, session_wrapper, \
                    get_active_keyring_paths, get_primary_keyring_path, \
 # code in lenny's Python. This also affects commands.getoutput and
 # commands.getstatus.
 def dak_getstatusoutput(cmd):
-    pipe = subprocess.Popen(cmd, shell=True, universal_newlines=True,
+    pipe = daklib.daksubprocess.Popen(cmd, shell=True, universal_newlines=True,
         stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
     output = pipe.stdout.read()
     try:
         print >>tmp, text,
         tmp.close()
-        subprocess.check_call([editor, tmp.name])
+        daklib.daksubprocess.check_call([editor, tmp.name])
         return open(tmp.name, 'r').read()
     finally:
         os.unlink(tmp.name)