@@ -76,7 +76,8 @@ def augmentEnv():
7676
7777
7878def startProgram (argv , root = '/' , stdin = None , stdout = subprocess .PIPE , stderr = subprocess .STDOUT ,
79- env_prune = None , env_add = None , reset_handlers = True , reset_lang = True , ** kwargs ):
79+ env_prune = None , env_add = None , reset_handlers = True , reset_lang = True ,
80+ do_preexec = False , ** kwargs ):
8081 """ Start an external program and return the Popen object.
8182
8283 The root and reset_handlers arguments are handled by passing a
@@ -93,6 +94,7 @@ def startProgram(argv, root='/', stdin=None, stdout=subprocess.PIPE, stderr=subp
9394 :param env_add: environment variables to add before execution
9495 :param reset_handlers: whether to reset to SIG_DFL any signal handlers set to SIG_IGN
9596 :param reset_lang: whether to set the locale of the child process to C
97+ :param do_preexec: whether to use the preexec function
9698 :param kwargs: Additional parameters to pass to subprocess.Popen
9799 :return: A Popen object for the running command.
98100 """
@@ -105,32 +107,11 @@ def startProgram(argv, root='/', stdin=None, stdout=subprocess.PIPE, stderr=subp
105107 if target_root == conf .target .physical_root :
106108 target_root = conf .target .system_root
107109
108- # Check for and save a preexec_fn argument
109- preexec_fn = kwargs .pop ("preexec_fn" , None )
110-
111110 # Map reset_handlers to the restore_signals Popen argument.
112111 # restore_signals handles SIGPIPE, and preexec below handles any additional
113112 # signals ignored by anaconda.
114113 restore_signals = reset_handlers
115114
116- def preexec ():
117- # If a target root was specificed, chroot into it
118- if target_root and target_root != '/' :
119- os .chroot (target_root )
120- os .chdir ("/" )
121-
122- # Signal handlers set to SIG_IGN persist across exec. Reset
123- # these to SIG_DFL if requested. In particular this will include the
124- # SIGPIPE handler set by python.
125- if reset_handlers :
126- for signum in range (1 , signal .NSIG ):
127- if signal .getsignal (signum ) == signal .SIG_IGN :
128- signal .signal (signum , signal .SIG_DFL )
129-
130- # If the user specified an additional preexec_fn argument, run it
131- if preexec_fn is not None :
132- preexec_fn ()
133-
134115 with program_log_lock :
135116 if target_root != '/' :
136117 program_log .info ("Running in chroot '%s'... %s" , target_root , " " .join (argv ))
@@ -148,13 +129,38 @@ def preexec():
148129 env .update (env_add )
149130
150131 # pylint: disable=subprocess-popen-preexec-fn
151- return subprocess .Popen (argv ,
152- stdin = stdin ,
153- stdout = stdout ,
154- stderr = stderr ,
155- close_fds = True ,
156- restore_signals = restore_signals ,
157- preexec_fn = preexec , cwd = root , env = env , ** kwargs )
132+ partsubp = functools .partial (subprocess .Popen ,
133+ argv ,
134+ stdin = stdin ,
135+ stdout = stdout ,
136+ stderr = stderr ,
137+ close_fds = True ,
138+ restore_signals = restore_signals ,
139+ cwd = root , env = env , ** kwargs )
140+ if do_preexec :
141+ # Check for and save a preexec_fn argument
142+ preexec_fn = kwargs .pop ("preexec_fn" , None )
143+
144+ def preexec ():
145+ # If a target root was specificed, chroot into it
146+ if target_root and target_root != '/' :
147+ os .chroot (target_root )
148+ os .chdir ("/" )
149+
150+ # Signal handlers set to SIG_IGN persist across exec. Reset
151+ # these to SIG_DFL if requested. In particular this will include the
152+ # SIGPIPE handler set by python.
153+ if reset_handlers :
154+ for signum in range (1 , signal .NSIG ):
155+ if signal .getsignal (signum ) == signal .SIG_IGN :
156+ signal .signal (signum , signal .SIG_DFL )
157+
158+ # If the user specified an additional preexec_fn argument, run it
159+ if preexec_fn is not None :
160+ preexec_fn ()
161+
162+ return partsubp (preexec_fn = preexec )
163+ return partsubp ()
158164
159165
160166class X11Status :
@@ -253,7 +259,7 @@ def sigusr1_preexec():
253259
254260
255261def _run_program (argv , root = '/' , stdin = None , stdout = None , env_prune = None , log_output = True ,
256- binary_output = False , filter_stderr = False ):
262+ binary_output = False , filter_stderr = False , do_preexec = False ):
257263 """ Run an external program, log the output and return it to the caller
258264
259265 NOTE/WARNING: UnicodeDecodeError will be raised if the output of the of the
@@ -267,6 +273,7 @@ def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_ou
267273 :param log_output: whether to log the output of command
268274 :param binary_output: whether to treat the output of command as binary data
269275 :param filter_stderr: whether to exclude the contents of stderr from the returned output
276+ :param do_preexec: whether to use a preexec_fn for subprocess.Popen
270277 :return: The return code of the command and the output
271278 """
272279 try :
@@ -276,7 +283,7 @@ def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_ou
276283 stderr = subprocess .STDOUT
277284
278285 proc = startProgram (argv , root = root , stdin = stdin , stdout = subprocess .PIPE , stderr = stderr ,
279- env_prune = env_prune )
286+ env_prune = env_prune , do_preexec = do_preexec )
280287
281288 (output_string , err_string ) = proc .communicate ()
282289 if not binary_output :
@@ -322,8 +329,8 @@ def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_ou
322329 return (proc .returncode , output_string )
323330
324331
325- def execWithRedirect (command , argv , stdin = None , stdout = None ,
326- root = '/' , env_prune = None , log_output = True , binary_output = False ):
332+ def execWithRedirect (command , argv , stdin = None , stdout = None , root = '/' , env_prune = None ,
333+ log_output = True , binary_output = False , do_preexec = False ):
327334 """ Run an external program and redirect the output to a file.
328335
329336 :param command: The command to run
@@ -334,11 +341,12 @@ def execWithRedirect(command, argv, stdin=None, stdout=None,
334341 :param env_prune: environment variable to remove before execution
335342 :param log_output: whether to log the output of command
336343 :param binary_output: whether to treat the output of command as binary data
344+ :param do_preexec: whether to use a preexec_fn for subprocess.Popen
337345 :return: The return code of the command
338346 """
339347 argv = [command ] + argv
340348 return _run_program (argv , stdin = stdin , stdout = stdout , root = root , env_prune = env_prune ,
341- log_output = log_output , binary_output = binary_output )[0 ]
349+ log_output = log_output , binary_output = binary_output , do_preexec = do_preexec )[0 ]
342350
343351
344352def execWithCapture (command , argv , stdin = None , root = '/' , log_output = True , filter_stderr = False ):
0 commit comments