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

Source Code for Module ClusterShell.Worker.Popen

  1  # 
  2  # Copyright CEA/DAM/DIF (2008, 2009, 2010) 
  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: Popen.py 242 2010-03-05 13:18:28Z st-cea $ 
 34   
 35  """ 
 36  WorkerPopen 
 37   
 38  ClusterShell worker for executing local commands. 
 39  """ 
 40   
 41  import os 
 42  import signal 
 43   
 44  from ClusterShell.Worker.Worker import WorkerSimple, WorkerBadArgumentError 
 45   
 46   
47 -class WorkerPopen(WorkerSimple):
48 """ 49 Implements the Popen Worker. 50 """ 51
52 - def __init__(self, command, key=None, handler=None, 53 stderr=False, timeout=-1, autoclose=False):
54 """ 55 Initialize Popen worker. 56 """ 57 WorkerSimple.__init__(self, None, None, None, key, handler, 58 stderr, timeout, autoclose) 59 60 self.command = command 61 if not self.command: 62 raise WorkerBadArgumentError() 63 64 self.popen = None 65 self.rc = None
66
67 - def _start(self):
68 """ 69 Start worker. 70 """ 71 assert self.popen is None 72 73 self.popen = self._exec_nonblock(self.command, shell=True) 74 self.file_reader = self.popen.stdout 75 self.file_error = self.popen.stderr 76 self.file_writer = self.popen.stdin 77 78 if self.task.info("debug", False): 79 self.task.info("print_debug")(self.task, "POPEN: %s" % self.command) 80 81 self._invoke("ev_start") 82 83 return 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 if not force and self._rbuf: 92 # We still have some read data available in buffer, but no 93 # EOL. Generate a final message before closing. 94 self.worker._on_msgline(self._rbuf) 95 96 rc = -1 97 if force or timeout: 98 # check if process has terminated 99 prc = self.popen.poll() 100 if prc is None: 101 # process is still running, kill it 102 os.kill(self.popen.pid, signal.SIGKILL) 103 else: 104 # close process / check if it has terminated 105 prc = self.popen.wait() 106 # get exit status 107 if prc >= 0: 108 # process exited normally 109 rc = prc 110 else: 111 # if process was signaled, return 128 + signum (bash-like) 112 rc = 128 + -prc 113 114 self.popen.stdin.close() 115 self.popen.stdout.close() 116 117 if rc >= 0: 118 self._on_rc(rc) 119 elif timeout: 120 self._on_timeout() 121 122 self._invoke("ev_close")
123
124 - def _on_rc(self, rc):
125 """ 126 Set return code. 127 """ 128 self.rc = rc 129 self.task._rc_set((self, self.key), rc) 130 131 self._invoke("ev_hup")
132
133 - def retcode(self):
134 """ 135 Return return code or None if command is still in progress. 136 """ 137 return self.rc
138