# # # patch "monotone.py" # from [594168ca14bad533817afbd34f41f73e78e6b289] # to [37a91b8934405b0a9f4776472710379b4992e892] # ============================================================ --- monotone.py 594168ca14bad533817afbd34f41f73e78e6b289 +++ monotone.py 37a91b8934405b0a9f4776472710379b4992e892 @@ -1,8 +1,9 @@ import utility import urllib import signal import string +import syslog import pipes import sets import sha @@ -44,8 +45,10 @@ def start(self): self.process = popen2.Popen3(self.command) set_nonblocking(self.process.fromchild) + syslog.syslog("AUTOMATE; %s starting %s" % (os.getpid(), self.process.pid)) def stop(self): if not self.process: return + syslog.syslog("AUTOMATE: %s stopping %s" % (os.getpid(), self.process.pid)) try: self.process.tochild.close() self.process.fromchild.close() @@ -54,38 +57,49 @@ os.kill(self.process.pid, signal.SIGKILL) self.process.wait() except: + syslog.syslog("AUTOMATE: %s failed_to_stop %s" % (os.getpid(), self.process.pid)) pass def run(self, command, args): if self.process == None: self.start() + syslog.syslog("AUTOMATE: %s run_via %s %s %s" % (os.getpid(), self.process.pid, str(command), str(args))) enc = "l%d:%s" % (len(command), command) enc += ''.join(map(lambda x: "%d:%s" % (len(x), x), args)) + 'e' - self.process.tochild.write(enc) + syslog.syslog("AUTOMATE: %s run_via_send %s %s %s" % (os.getpid(), self.process.pid, str(command), enc)) + # note that fromchild is nonblocking, but tochild is blocking + self.process.tochild.write(enc) self.process.tochild.flush() r = RecvPacket() complete = False result_string = "" result_code = None while not complete: + syslog.syslog("AUTOMATE: %s run_via_select %s" % (os.getpid(), self.process.pid)) ro, rw, re = select.select([self.process.fromchild], [], [], None) if not ro and not rw and not re: break if self.process.fromchild in ro: recv = self.process.fromchild.read() if recv == "": break - tv = r.process_data(recv) - if tv != None: - cmdnum, error, length, is_last, result = tv - if result_code == None: result_code = int(error) - result_string += result - if is_last: - complete = True - else: - # in case there is anything left over we - # didn't parse - r = RecvPacket(r.buffer) + syslog.syslog("AUTOMATE: %s run_via_recv %s %s %s" % (os.getpid(), self.process.pid, str(command), recv)) + + data_to_parse = recv + while not complete: + tv = r.process_data(data_to_parse) + if tv == None: + # this data did not result in a complete packet; we need more data from the client + break + else: + cmdnum, error, length, is_last, result = tv + if result_code == None: result_code = int(error) + result_string += result + if is_last: + complete = True + else: + # any left-over bytes must be parsed in case we have another complete packet + data_to_parse = r.buffer + r = RecvPacket() return result_code, result_string - class Monotone: def __init__(self, mt, dbfile): self.mt = mt @@ -225,7 +239,6 @@ def diff(self, rev_from, rev_to, files=None): command = self.base_command + " diff -r %s -r %s" % (pipes.quote(rev_from), pipes.quote(rev_to)) if files != None: command += ' ' + ' '.join(map(pipes.quote, files)) - import syslog syslog.syslog(command) result = utility.run_command(command) if result['exitcode'] != 0: @@ -343,6 +356,7 @@ def process_data(self, data): self.buffer += data if self.length == None: + # we have not yet read a complete header line for this packet m = packet_header_re.match(data) if m: self.cmdnum, self.error, pstate, self.length = m.groups()