Disable global spawned_pids (avoid memory leak)
authorZac Medico <zmedico@gentoo.org>
Sat, 6 Jul 2013 00:09:30 +0000 (17:09 -0700)
committerZac Medico <zmedico@gentoo.org>
Sat, 6 Jul 2013 00:09:30 +0000 (17:09 -0700)
It used to be necessary for API consumers to remove pids from the
global spawned_pids, since otherwise it would accumulate a pids
endlessly. Now, spawned_pids is just an empty dummy list, so for
backward compatibility, ignore ValueError for removal on non-existent
items.

pym/_emerge/EbuildMetadataPhase.py
pym/_emerge/SpawnProcess.py
pym/_emerge/actions.py
pym/portage/dbapi/_MergeProcess.py
pym/portage/process.py
pym/portage/util/_async/ForkProcess.py

index 4c7d772d4fa9e3e5748db8a2a31495a1e2a24fe6..7418aba9f7a2a870c6186b84ba6ce281259f81fe 100644 (file)
@@ -128,7 +128,6 @@ class EbuildMetadataPhase(SubProcess):
                        return
 
                self.pid = retval[0]
-               portage.process.spawned_pids.remove(self.pid)
 
        def _output_handler(self, fd, event):
 
index 25859a9cd4449f6e0dab81732dcd5ffb92d64bfe..c57bd2e47df699eff12cb8f15dd81d2e9e820622 100644 (file)
@@ -114,7 +114,6 @@ class SpawnProcess(SubProcess):
                        return
 
                self.pid = retval[0]
-               portage.process.spawned_pids.remove(self.pid)
 
                stdout_fd = None
                if can_log and not self.background:
index 9463be8b90846591ca48d60e6b9d7e67a2320aa7..034613e9f0f3741307d22bb3b20654cd6ecc6a62 100644 (file)
@@ -2423,8 +2423,7 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                                                        exitcode = (exitcode & 0xff) << 8
                                                else:
                                                        exitcode = exitcode >> 8
-                               if mypids:
-                                       portage.process.spawned_pids.remove(mypids[0])
+
                                if content:
                                        try:
                                                servertimestamp = time.mktime(time.strptime(
index 1442d56ac3cf7cb6e7d26ca99e4591b3bfcead98..76108c882b6005e2bbc82e3b38594fcfdb8f9462 100644 (file)
@@ -174,7 +174,6 @@ class MergeProcess(ForkProcess):
                                self.vartree.dbapi._pkgs_changed = True
                                self.vartree.dbapi._clear_pkg_cache(mylink)
 
-                               portage.process.spawned_pids.append(pid)
                                return [pid]
 
                        os.close(elog_reader_fd)
index 7fdc1333a99bee5c78b3cc29c4a3c55fce87ea70..728a01daf162126bab716e79019f19eec434099a 100644 (file)
@@ -156,26 +156,23 @@ def run_exitfuncs():
 
 atexit.register(run_exitfuncs)
 
-# We need to make sure that any processes spawned are killed off when
-# we exit. spawn() takes care of adding and removing pids to this list
-# as it creates and cleans up processes.
-spawned_pids = []
-def cleanup():
-       while spawned_pids:
-               pid = spawned_pids.pop()
+# It used to be necessary for API consumers to remove pids from spawned_pids,
+# since otherwise it would accumulate a pids endlessly. Now, spawned_pids is
+# just an empty dummy list, so for backward compatibility, ignore ValueError
+# for removal on non-existent items.
+class _dummy_list(list):
+       def remove(self, item):
+               # TODO: Trigger a DeprecationWarning here, after stable portage
+               # has dummy spawned_pids.
                try:
-                       # With waitpid and WNOHANG, only check the
-                       # first element of the tuple since the second
-                       # element may vary (bug #337465).
-                       if os.waitpid(pid, os.WNOHANG)[0] == 0:
-                               os.kill(pid, signal.SIGTERM)
-                               os.waitpid(pid, 0)
-               except OSError:
-                       # This pid has been cleaned up outside
-                       # of spawn().
+                       list.remove(self, item)
+               except ValueError:
                        pass
 
-atexit_register(cleanup)
+spawned_pids = _dummy_list()
+
+def cleanup():
+       pass
 
 def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
           uid=None, gid=None, groups=None, umask=None, logfile=None,
@@ -309,7 +306,6 @@ def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
 
        # Add the pid to our local and the global pid lists.
        mypids.append(pid)
-       spawned_pids.append(pid)
 
        # If we started a tee process the write side of the pipe is no
        # longer needed, so close it.
@@ -332,10 +328,6 @@ def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
                # and wait for it.
                retval = os.waitpid(pid, 0)[1]
 
-               # When it's done, we can remove it from the
-               # global pid list as well.
-               spawned_pids.remove(pid)
-
                if retval:
                        # If it failed, kill off anything else that
                        # isn't dead yet.
@@ -346,7 +338,6 @@ def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
                                if os.waitpid(pid, os.WNOHANG)[0] == 0:
                                        os.kill(pid, signal.SIGTERM)
                                        os.waitpid(pid, 0)
-                               spawned_pids.remove(pid)
 
                        # If it got a signal, return the signal that was sent.
                        if (retval & 0xff):
index 17be02a6eee7a5e9604eb3f9392f210d43263f55..be856d039f719d642758f17d94adc999e4bd9f24 100644 (file)
@@ -26,7 +26,6 @@ class ForkProcess(SpawnProcess):
                                if not isinstance(pid, int):
                                        raise AssertionError(
                                                "fork returned non-integer: %s" % (repr(pid),))
-                               portage.process.spawned_pids.append(pid)
                                return [pid]
 
                        rval = 1