Package ClusterShell :: Package Worker :: Module Popen2
[hide private]
[frames] | no frames]

Source Code for Module ClusterShell.Worker.Popen2

  1  # 
  2  # Copyright CEA/DAM/DIF (2008, 2009) 
  3  #  Contributor: Stephane THIELL <stephane.thiell@cea.fr> 
  4  # 
  5  # This file is part of the ClusterShell library. 
  6  # 
  7  # This software is governed by the CeCILL-C license under French law and 
  8  # abiding by the rules of distribution of free software.  You can  use, 
  9  # modify and/ or redistribute the software under the terms of the CeCILL-C 
 10  # license as circulated by CEA, CNRS and INRIA at the following URL 
 11  # "http://www.cecill.info". 
 12  # 
 13  # As a counterpart to the access to the source code and  rights to copy, 
 14  # modify and redistribute granted by the license, users are provided only 
 15  # with a limited warranty  and the software's author,  the holder of the 
 16  # economic rights,  and the successive licensors  have only  limited 
 17  # liability. 
 18  # 
 19  # In this respect, the user's attention is drawn to the risks associated 
 20  # with loading,  using,  modifying and/or developing or reproducing the 
 21  # software by the user in light of its specific status of free software, 
 22  # that may mean  that it is complicated to manipulate,  and  that  also 
 23  # therefore means  that it is reserved for developers  and  experienced 
 24  # professionals having in-depth computer knowledge. Users are therefore 
 25  # encouraged to load and test the software's suitability as regards their 
 26  # requirements in conditions enabling the security of their systems and/or 
 27  # data to be ensured and,  more generally, to use and operate it in the 
 28  # same conditions as regards security. 
 29  # 
 30  # The fact that you are presently reading this means that you have had 
 31  # knowledge of the CeCILL-C license and that you accept its terms. 
 32  # 
 33  # $Id: Popen2.py 161 2009-10-28 12:36:00Z st-cea $ 
 34   
 35  """ 
 36  WorkerPopen2 
 37   
 38  ClusterShell worker for executing local commands with popen2. 
 39  """ 
 40   
 41  from ClusterShell.NodeSet import NodeSet 
 42   
 43  from Worker import WorkerSimple 
 44   
 45  import fcntl 
 46  import os 
 47  import popen2 
 48  import signal 
 49   
 50   
51 -class WorkerPopen2(WorkerSimple):
52 """ 53 Implements the Popen2 Worker. 54 """ 55
56 - def __init__(self, command, key, handler, timeout, autoclose=False):
57 """ 58 Initialize Popen2 worker. 59 """ 60 WorkerSimple.__init__(self, None, None, None, key, handler, timeout, autoclose) 61 62 self.command = command 63 if not self.command: 64 raise WorkerBadArgumentException() 65 66 self.fid = None 67 self.rc = None
68
69 - def _start(self):
70 """ 71 Start worker. 72 """ 73 assert self.fid is None 74 75 cmdlist = ['/bin/sh', '-c', self.command] 76 self.fid = self._exec_nonblock(cmdlist) 77 self.file_reader = self.fid.fromchild 78 self.file_writer = self.fid.tochild 79 80 if self.task.info("debug", False): 81 self.task.info("print_debug")(self.task, "POPEN2: [%s]" % ','.join(cmdlist)) 82 83 return WorkerSimple._start(self)
84
85 - def _close(self, force, timeout):
86 """ 87 Close worker. Called by engine after worker has been 88 unregistered. This method should handle all termination types 89 (normal, forced or on timeout). 90 """ 91 rc = -1 92 if force or timeout: 93 # check if process has terminated 94 status = self.fid.poll() 95 if status == -1: 96 # process is still running, kill it 97 os.kill(self.fid.pid, signal.SIGKILL) 98 else: 99 # close process / check if it has terminated 100 status = self.fid.wait() 101 # get exit status 102 if os.WIFEXITED(status): 103 # process exited normally 104 rc = os.WEXITSTATUS(status) 105 elif os.WIFSIGNALED(status): 106 # if process was signaled, return 128 + signum (bash-like) 107 rc = 128 + os.WSTOPSIG(status) 108 else: 109 # unknown condition 110 rc = 255 111 112 self.fid.tochild.close() 113 self.fid.fromchild.close() 114 115 if rc >= 0: 116 self._on_rc(rc) 117 elif timeout: 118 self._on_timeout() 119 120 self._invoke("ev_close")
121
122 - def _on_rc(self, rc):
123 """ 124 Set return code. 125 """ 126 self.rc = rc 127 self.task._rc_set((self, self.key), rc) 128 129 self._invoke("ev_hup")
130
131 - def retcode(self):
132 """ 133 Return return code or None if command is still in progress. 134 """ 135 return self.rc
136