Register for poll events before forking, in order to avoid potential race conditions
authorZac Medico <zmedico@gentoo.org>
Thu, 25 Dec 2008 01:21:17 +0000 (01:21 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 25 Dec 2008 01:21:17 +0000 (01:21 -0000)
in SpawnProcess._start() and EbuildMetadataPhase._start(). Hopefully this solves
hung poll calls with defunct ebuild.sh processes, reported on solaris systems by
Fabian Groffen <grobian@g.o>. (trunk r12285)

svn path=/main/branches/2.1.6/; revision=12316

pym/_emerge/__init__.py

index c596adc226da8bf8179290e183d09ae1c598703c..c82bd2062c868f34bc6867b9d46ef87c022373f1 100644 (file)
@@ -2156,6 +2156,10 @@ class SpawnProcess(SubProcess):
                kwargs["returnpid"] = True
                kwargs.pop("logfile", None)
 
+               self._reg_id = self.scheduler.register(files.process.fileno(),
+                       PollConstants.POLLIN, output_handler)
+               self._registered = True
+
                retval = self._spawn(self.args, **kwargs)
 
                os.close(slave_fd)
@@ -2164,8 +2168,7 @@ class SpawnProcess(SubProcess):
 
                if isinstance(retval, int):
                        # spawn failed
-                       for f in files.values():
-                               f.close()
+                       self._unregister()
                        self.returncode = retval
                        self.wait()
                        return
@@ -2173,10 +2176,6 @@ class SpawnProcess(SubProcess):
                self.pid = retval[0]
                portage.process.spawned_pids.remove(self.pid)
 
-               self._reg_id = self.scheduler.register(files.process.fileno(),
-                       PollConstants.POLLIN, output_handler)
-               self._registered = True
-
        def _pipe(self, fd_pipes):
                """
                @type fd_pipes: dict
@@ -2821,6 +2820,12 @@ class EbuildMetadataPhase(SubProcess):
 
                fd_pipes[self._metadata_fd] = slave_fd
 
+               self._raw_metadata = []
+               files.ebuild = os.fdopen(master_fd, 'r')
+               self._reg_id = self.scheduler.register(files.ebuild.fileno(),
+                       PollConstants.POLLIN, self._output_handler)
+               self._registered = True
+
                retval = portage.doebuild(ebuild_path, "depend",
                        settings["ROOT"], settings, debug,
                        mydbapi=self.portdb, tree="porttree",
@@ -2830,7 +2835,7 @@ class EbuildMetadataPhase(SubProcess):
 
                if isinstance(retval, int):
                        # doebuild failed before spawning
-                       os.close(master_fd)
+                       self._unregister()
                        self.returncode = retval
                        self.wait()
                        return
@@ -2838,12 +2843,6 @@ class EbuildMetadataPhase(SubProcess):
                self.pid = retval[0]
                portage.process.spawned_pids.remove(self.pid)
 
-               self._raw_metadata = []
-               files.ebuild = os.fdopen(master_fd, 'r')
-               self._reg_id = self.scheduler.register(files.ebuild.fileno(),
-                       PollConstants.POLLIN, self._output_handler)
-               self._registered = True
-
        def _output_handler(self, fd, event):
                files = self._files
                self._raw_metadata.append(files.ebuild.read())