Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH 1/3 v2] Add cached portage.getpid() function
Date: Sat, 08 Aug 2020 06:09:54
Message-Id: 20200808060727.80682-1-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 1/3] Add cached portage.getpid() function by Zac Medico
1 Since getpid is a syscall, cache results, and update them
2 via an after fork hook.
3
4 Signed-off-by: Zac Medico <zmedico@g.o>
5 ---
6 lib/portage/__init__.py | 16 +++++++++++++
7 .../tests/process/test_AsyncFunction.py | 24 +++++++++++++++++++
8 2 files changed, 40 insertions(+)
9
10 diff --git a/lib/portage/__init__.py b/lib/portage/__init__.py
11 index 916c93510..4d4b590a8 100644
12 --- a/lib/portage/__init__.py
13 +++ b/lib/portage/__init__.py
14 @@ -14,6 +14,7 @@ try:
15 if not hasattr(errno, 'ESTALE'):
16 # ESTALE may not be defined on some systems, such as interix.
17 errno.ESTALE = -1
18 + import multiprocessing.util
19 import re
20 import types
21 import platform
22 @@ -368,6 +369,21 @@ _internal_caller = False
23
24 _sync_mode = False
25
26 +class _ForkWatcher:
27 + @staticmethod
28 + def hook(_ForkWatcher):
29 + _ForkWatcher.current_pid = _os.getpid()
30 +
31 +_ForkWatcher.hook(_ForkWatcher)
32 +
33 +multiprocessing.util.register_after_fork(_ForkWatcher, _ForkWatcher.hook)
34 +
35 +def getpid():
36 + """
37 + Cached version of os.getpid(). ForkProcess updates the cache.
38 + """
39 + return _ForkWatcher.current_pid
40 +
41 def _get_stdin():
42 """
43 Buggy code in python's multiprocessing/process.py closes sys.stdin
44 diff --git a/lib/portage/tests/process/test_AsyncFunction.py b/lib/portage/tests/process/test_AsyncFunction.py
45 index 55857026d..3b360e02f 100644
46 --- a/lib/portage/tests/process/test_AsyncFunction.py
47 +++ b/lib/portage/tests/process/test_AsyncFunction.py
48 @@ -3,6 +3,7 @@
49
50 import sys
51
52 +import portage
53 from portage import os
54 from portage.tests import TestCase
55 from portage.util._async.AsyncFunction import AsyncFunction
56 @@ -36,3 +37,26 @@ class AsyncFunctionTestCase(TestCase):
57 def testAsyncFunctionStdin(self):
58 loop = asyncio._wrap_loop()
59 loop.run_until_complete(self._testAsyncFunctionStdin(loop))
60 +
61 + def _test_getpid_fork(self):
62 + """
63 + Verify that portage.getpid() cache is updated in a forked child process.
64 + """
65 + loop = asyncio._wrap_loop()
66 + proc = AsyncFunction(scheduler=loop, target=portage.getpid)
67 + proc.start()
68 + proc.wait()
69 + self.assertEqual(proc.pid, proc.result)
70 +
71 + def test_getpid_fork(self):
72 + self._test_getpid_fork()
73 +
74 + def test_getpid_double_fork(self):
75 + """
76 + Verify that portage.getpid() cache is updated correctly after
77 + two forks.
78 + """
79 + loop = asyncio._wrap_loop()
80 + proc = AsyncFunction(scheduler=loop, target=self._test_getpid_fork)
81 + proc.start()
82 + self.assertEqual(proc.wait(), 0)
83 --
84 2.25.3