Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 916106 - sys-apps/portage: QueryCommand._db is missing when MergeProcess uses the multiprocessing spawn start method
Summary: sys-apps/portage: QueryCommand._db is missing when MergeProcess uses the mult...
Status: RESOLVED FIXED
Alias: None
Product: Portage Development
Classification: Unclassified
Component: Core (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Portage team
URL:
Whiteboard:
Keywords: InVCS
Depends on: 916031
Blocks: 914876
  Show dependency tree
 
Reported: 2023-10-22 06:49 UTC by Zac Medico
Modified: 2023-10-25 05:49 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Zac Medico gentoo-dev 2023-10-22 06:49:05 UTC
I ran lib/portage/tests/emerge/test_simple.py with this patch applied to make it use the multiprocessing spawn start method. The self._scheduler.is_closed() thing is a workaround for a strange issue with the asyncio loop getting closed for an unknown reason:

> diff --git a/bin/emerge b/bin/emerge
> index f5dbc3106..b2afe74b2 100755
> --- a/bin/emerge
> +++ b/bin/emerge
> @@ -4,2 +4,5 @@
>  
> +import multiprocessing
> +multiprocessing.set_start_method("spawn", force=True)
> +
>  import os
> diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py
> index 88fc52577..203eaa3bb 100644
> --- a/lib/portage/dbapi/vartree.py
> +++ b/lib/portage/dbapi/vartree.py
> @@ -4282,2 +4282,7 @@ class dblink:
>  
> +        if self._scheduler.is_closed():
> +            asyncio._thread_weakrefs.mainloop = None
> +            asyncio._thread_weakrefs.loops.clear()
> +            self._scheduler = SchedulerInterface(asyncio._safe_loop())
> +
>          # run instprep internal phase
> diff --git a/lib/portage/tests/emerge/test_simple.py b/lib/portage/tests/emerge/test_simple.py
> index 1cc6457ef..32fe3e501 100644
> --- a/lib/portage/tests/emerge/test_simple.py
> +++ b/lib/portage/tests/emerge/test_simple.py
> @@ -55,3 +55,3 @@ class SimpleEmergeTestCase(TestCase):
>      def testSimple(self):
> -        debug = False
> +        debug = True

With the above patch, I can see that QueryCommand._db is missing when MergeProcess uses the multiprocessing spawn start method, as shown by this AttributeError that happens because QueryCommand._db is missing:

> Traceback (most recent call last):
>   File "/usr/lib/python3.10/asyncio/events.py", line 80, in _run
>     self._context.run(self._callback, *self._args)
>   File "portage/lib/_emerge/EbuildIpcDaemon.py", line 55, in _input_handler
>     reply = cmd_handler(obj)
>   File "portage/lib/portage/package/ebuild/_ipc/QueryCommand.py", line 50, in __call__
>     db = self.get_db()
>   File "portage/lib/portage/package/ebuild/_ipc/QueryCommand.py", line 29, in get_db
>     return portage.db
> AttributeError: module 'portage' has no attribute 'db'
Comment 1 Zac Medico gentoo-dev 2023-10-22 06:59:31 UTC
A possible solution is to have EbuildIpcDaemon proxy the requests through to the parent process via a duplex multiprocessing.Pipe.
Comment 2 Larry the Git Cow gentoo-dev 2023-10-22 21:30:51 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/proj/portage.git/commit/?id=b9a85ff987ea677e350fb70e2c3355197ee6c39b

commit b9a85ff987ea677e350fb70e2c3355197ee6c39b
Author:     Zac Medico <zmedico@gentoo.org>
AuthorDate: 2023-10-22 08:08:02 +0000
Commit:     Zac Medico <zmedico@gentoo.org>
CommitDate: 2023-10-22 21:29:49 +0000

    MergeProcess: Support QueryCommand with spawn start method
    
    Since QueryCommand._db does not propagate to the child process
    in MergeProcess with the multiprocessing spawn start method,
    handle it by passing QueryCommand._db as an explicit parameter.
    
    Since self.mydbapi can be a bindbapi instance, override the
    bindbapi __getstate__ method so that it is picklable (omit
    the unpicklable _aux_cache_slot_dict attribute and regenerate
    it after unpickling).
    
    Bug: https://bugs.gentoo.org/916106
    Signed-off-by: Zac Medico <zmedico@gentoo.org>

 lib/portage/dbapi/_MergeProcess.py | 19 ++++++++++++++++---
 lib/portage/dbapi/bintree.py       | 20 ++++++++++++++++++--
 2 files changed, 34 insertions(+), 5 deletions(-)
Comment 3 Zac Medico gentoo-dev 2023-10-22 22:37:51 UTC
(In reply to Zac Medico from comment #0)
> The self._scheduler.is_closed() thing is a workaround for a strange issue
> with the asyncio loop getting closed for an unknown reason:
> 
> > diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py
> > index 88fc52577..203eaa3bb 100644
> > --- a/lib/portage/dbapi/vartree.py
> > +++ b/lib/portage/dbapi/vartree.py
> > @@ -4282,2 +4282,7 @@ class dblink:
> >  
> > +        if self._scheduler.is_closed():
> > +            asyncio._thread_weakrefs.mainloop = None
> > +            asyncio._thread_weakrefs.loops.clear()
> > +            self._scheduler = SchedulerInterface(asyncio._safe_loop())
> > +
> >          # run instprep internal phase

It's actually this code in bin/emerge that triggered the issue:

> finally:
>     global_event_loop().close()

For the multiprocessing spawn start method, the event loop close needs to be protected inside a __name__ == "__main__" conditional. There's a similar issue in bin/ebuild.
Comment 4 Zac Medico gentoo-dev 2023-10-23 03:40:16 UTC
Something is still not quite right about bindbapi pickling, because now it fails to pickle _aux_cache_slot_dict_cache in some cases. It may be that __gatestate__ is raising some kind of exception and preventing it from working. Also, the _instance_key attribute needs to be excluded from pickling since it refers to an instance method. The __setstate__ method can use the _multi_instance attribute to set the _instance_key attribute appropriately for the new instance.
Comment 5 Larry the Git Cow gentoo-dev 2023-10-23 14:28:50 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/proj/portage.git/commit/?id=c7768ae4820201913ba28d5fad441c1acc4659c0

commit c7768ae4820201913ba28d5fad441c1acc4659c0
Author:     Zac Medico <zmedico@gentoo.org>
AuthorDate: 2023-10-23 04:14:05 +0000
Commit:     Zac Medico <zmedico@gentoo.org>
CommitDate: 2023-10-23 04:41:10 +0000

    bindbapi: Fix pickling for MergeProcess
    
    Both the _aux_cache_slot_dict_cache and _instance_key attributes are
    unpicklable, so fix __getstate__ to exclude them both from the state.
    Override __setstate__ to initialize _instance_key appropriately.
    These changes prevent the following error:
    
    AttributeError: Can't pickle local object 'slot_dict_class.<locals>.LocalSlotDict'
    
    Fixes: b9a85ff987ea ("MergeProcess: Support QueryCommand with spawn start method")
    Bug: https://bugs.gentoo.org/916106
    Signed-off-by: Zac Medico <zmedico@gentoo.org>

 lib/portage/dbapi/bintree.py | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)
Comment 6 Larry the Git Cow gentoo-dev 2023-10-25 05:49:16 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2b9128b401def05cac46f9e6d66048e5a0d888b8

commit 2b9128b401def05cac46f9e6d66048e5a0d888b8
Author:     Sam James <sam@gentoo.org>
AuthorDate: 2023-10-25 05:48:31 +0000
Commit:     Sam James <sam@gentoo.org>
CommitDate: 2023-10-25 05:48:40 +0000

    sys-apps/portage: add 3.0.54
    
    Closes: https://bugs.gentoo.org/905869
    Closes: https://bugs.gentoo.org/915551
    Closes: https://bugs.gentoo.org/915896
    Closes: https://bugs.gentoo.org/916106
    Closes: https://bugs.gentoo.org/916108
    Closes: https://bugs.gentoo.org/916112
    Closes: https://bugs.gentoo.org/916116
    Closes: https://bugs.gentoo.org/916139
    Closes: https://bugs.gentoo.org/916141
    Closes: https://bugs.gentoo.org/916142
    Closes: https://bugs.gentoo.org/916149
    Closes: https://bugs.gentoo.org/916182
    Closes: https://bugs.gentoo.org/916231
    Closes: https://bugs.gentoo.org/916235
    Closes: https://bugs.gentoo.org/916240
    Closes: https://bugs.gentoo.org/916242
    Closes: https://bugs.gentoo.org/916245
    Closes: https://bugs.gentoo.org/916248
    Closes: https://bugs.gentoo.org/899898
    Closes: https://bugs.gentoo.org/906129
    Closes: https://bugs.gentoo.org/906156
    Closes: https://bugs.gentoo.org/916031
    Signed-off-by: Sam James <sam@gentoo.org>

 sys-apps/portage/Manifest              |   1 +
 sys-apps/portage/portage-3.0.54.ebuild | 238 +++++++++++++++++++++++++++++++++
 2 files changed, 239 insertions(+)