Register for poll events before forking, in order to avoid potential race conditions
authorZac Medico <zmedico@gentoo.org>
Tue, 23 Dec 2008 18:53:13 +0000 (18:53 -0000)
committerZac Medico <zmedico@gentoo.org>
Tue, 23 Dec 2008 18:53:13 +0000 (18:53 -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>.

svn path=/main/trunk/; revision=12285

pym/_emerge/__init__.py

index a22440c93e962c627aa00e079732e3bf5a7b2ab4..78715bad5a03041b5a6ffa7de11e3dbb695653a0 100644 (file)
@@ -2175,6 +2175,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)
@@ -2183,8 +2187,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
@@ -2192,10 +2195,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
@@ -2840,6 +2839,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",
@@ -2849,7 +2854,7 @@ class EbuildMetadataPhase(SubProcess):
 
                if isinstance(retval, int):
                        # doebuild failed before spawning
-                       os.close(master_fd)
+                       self._unregister()
                        self.returncode = retval
                        self.wait()
                        return
@@ -2857,12 +2862,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())