Using select on a unix command in lieu of signal

rh0dium sklass at pointcircle.com
Mon Aug 29 16:36:36 EDT 2005


Hi all,

Another newbie question.  So you can't use signals on threads but you
can use select.  The reason I want to do this in the first place it I
need a timeout.  Fundamentally I want to run a command on another
machine, but I need a timeout.  I have to do this to a LOT of machines
( > 3000 ) and threading becomes necessary for timeliess.  So I created
a function which works with signals ( until you throw threading at it..
) but I can't seem to modify it correctly to use select.  Can some
select ( pun intended ) experts out there point out the error of my
way..

Not working RunCmd using select

    def runCmd( self, cmd, timeout=None ):

        starttime = time.time()

        child = popen2.Popen3(cmd)
        child.tochild.write("\n")
        child.tochild.close()
        child.wait()

        results = []
        results = "".join(child.fromchild.readlines())

        endtime = starttime + timeout

        r, w, x = select.select(results, [], [], endtime - time.time())

        if len(r) == 0:
            # We timed out.
            prefix = ("TIMED OUT:" + " " * maxlen)[:maxlen]
            sys.stdout.write(prefix)
            space = ""
            os.kill(child.pid,9)
            child.fromchild.close()

        return results


Working RunCmd using signal

    def handler(self, signum, frame):
        self.logger.debug("Signal handler called with signal %s" %
signum)

    def runCmd( self, cmd, timeout=None ):
        self.logger.debug("Initializing function %s - %s" %
(sys._getframe().f_code.co_name,cmd) )

        # Set the signal handler and a 5-second alarm
        signal.signal(signal.SIGALRM, self.handler)
        signal.alarm(timeout)

        try:
            child = popen2.Popen3(cmd)
            child.tochild.write("y\n")
            child.tochild.close()
            child.wait()

            results = "".join(child.fromchild.readlines())
            out = child.fromchild.close()
            self.logger.debug("command: %s Status: %s PID: %s " % (cmd,
out, child.pid))

            if out is None:
                out = 0

        except:
            self.logger.warning( "command: %s failed!" % cmd)
            kill = os.kill(child.pid,9)
            self.logger.debug( "Killing command %s - Result: %s" %
(cmd, kill))
            out = results = None

        signal.alarm(0)          # Disable the alarm

        return out,results

Thanks much - Alternatively if anyone else has a better way to do what
I am trying to get done always looking for better ways.  I still want
this to work though..




More information about the Python-list mailing list