Use an alarm signal to implement a timeout when rsync is fetching the server timestam...
authorZac Medico <zmedico@gentoo.org>
Thu, 1 Mar 2007 20:42:52 +0000 (20:42 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 1 Mar 2007 20:42:52 +0000 (20:42 -0000)
svn path=/main/branches/2.1.2/; revision=6110

bin/emerge

index 3133ae29e001e65e9d7f18cdc060d45d6dd48038..95169c14bb9fab856a327a622e636697bd7662fe 100755 (executable)
@@ -3929,23 +3929,51 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                                        "/metadata/timestamp.chk")
                                mycommand.append(tmpservertimestampfile)
                                import portage_exec
+                               content = None
+                               mypids = []
                                try:
-                                       exitcode = portage_exec.spawn(
-                                               mycommand, env=settings.environ())
-                                       content = portage.grabfile(tmpservertimestampfile)
-                                       if content:
+                                       def timeout_handler(signum, frame):
+                                               raise portage_exception.PortageException("timed out")
+                                       signal.signal(signal.SIGALRM, timeout_handler)
+                                       # Timeout here in case the server is unresponsive.  The
+                                       # --timeout rsync option doesn't apply to the initial
+                                       # connection attempt.
+                                       signal.alarm(15)
+                                       try:
+                                               mypids.extend(portage_exec.spawn(
+                                                       mycommand, env=settings.environ(), returnpid=True))
+                                               exitcode = os.waitpid(mypids[0], 0)[1]
+                                               content = portage.grabfile(tmpservertimestampfile)
+                                       finally:
+                                               signal.alarm(0)
                                                try:
-                                                       servertimestamp = time.mktime(time.strptime(
-                                                               content[0], "%a, %d %b %Y %H:%M:%S +0000"))
-                                               except OverflowError, ValueError:
+                                                       os.unlink(tmpservertimestampfile)
+                                               except OSError:
                                                        pass
-                                       del content
-                               finally:
+                               except portage_exception.PortageException, e:
+                                       # timed out
+                                       print e
+                                       del e
+                                       if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
+                                               os.kill(mypids[0], signal.SIGTERM)
+                                               os.waitpid(mypids[0], 0)
+                                       # This is the same code rsync uses for timeout.
+                                       exitcode = 30
+                               else:
+                                       if mypids:
+                                               portage_exec.spawned_pids.remove(mypids[0])
+                                       if exitcode != os.EX_OK:
+                                               if exitcode & 0xff:
+                                                       exitcode = (exitcode & 0xff) << 8
+                                               else:
+                                                       exitcode >> 8
+                               if content:
                                        try:
-                                               os.unlink(tmpservertimestampfile)
-                                       except OSError:
+                                               servertimestamp = time.mktime(time.strptime(
+                                                       content[0], "%a, %d %b %Y %H:%M:%S +0000"))
+                                       except OverflowError, ValueError:
                                                pass
-                               del mycommand
+                               del mycommand, mypids, content
                        if exitcode == os.EX_OK:
                                if (servertimestamp != 0) and (servertimestamp == mytimestamp):
                                        emergelog(xterm_titles,