Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyError: '__builtins__' #385

Closed
jordanbriere opened this issue Feb 4, 2021 · 2 comments · Fixed by #386
Closed

KeyError: '__builtins__' #385

jordanbriere opened this issue Feb 4, 2021 · 2 comments · Fixed by #386
Labels

Comments

@jordanbriere
Copy link
Contributor

While playing around #384, I ran across an issue that I was able to reproduce randomly with the following steps:

  • Launch CS:S/Windows server.
  • Connect to the server but do not join a team.
  • Load the following code:
from players.entity import Player

Player(1).give_named_item('weapon_awp')

Randomly results into:

[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\plugins\command.py", line 164, in load_plugin
    plugin = self.manager.load(plugin_name)
  File "..\addons\source-python\packages\source-python\plugins\manager.py", line 207, in load
    plugin._load()
  File "..\addons\source-python\packages\source-python\plugins\instance.py", line 74, in _load
    self.module = import_module(self.import_name)
  File "..\addons\source-python\plugins\testing\testing.py", line 3, in <module>
    Player(1).give_named_item('weapon_awp')
  File "..\addons\source-python\packages\source-python\entities\helpers.py", line 108, in __call__
    *self.wrapper(self.wrapped_self, *args, **kwargs))
  File "..\addons\source-python\packages\source-python\memory\helpers.py", line 334, in __call__
    return super().__call__(self._this, *args)
  File "<string>", line 1, in <lambda>

KeyError: '__builtins__'

Not sure yet why exactly this happens, but it is also reproducible on master.

@jordanbriere
Copy link
Contributor Author

Okay, after a quick investigation, it appears to be caused by a thread/frame issue related to hibernation combined with the compiled expression bound to CFunction::__call__ through raw_method.

Basically, when that expression is compiled by the interpreter at that time, PyEval_GetGlobals returns NULL resulting into the globals/locals being empty dictionaries. Normally, this is not really an issue, but since the compiled expression returns a nested lambda, and that globals == locals, it tries to resolve its namespace from the original scope instead of the calling frame.

jordanbriere added a commit that referenced this issue Feb 4, 2021
@Ayuto Ayuto added the bug label Feb 6, 2021
@jordanbriere
Copy link
Contributor Author

Weirdly enough, it is reproducible 100% of the times by adding the following import:

import entities.hooks
from players.entity import Player

Player(1).give_named_item('weapon_awp')

Not really sure why that is at this point, but raw_method fixes it while also being slightly faster. Tested the following:

"""
struct Foo { object dummy(boost::python::tuple args, dict kwargs) { return object(); } };
class_<Foo>("Foo")
	.def("bar", raw_method(&Foo::dummy))
	.def("baz", eval("lambda method: lambda *args, **kw: method(args[0], args[1:], kw)")(
		make_function(&Foo::dummy))
	)
;
"""

from time import *

foo = Foo()

t = time()
for i in range(10000000):
    foo.bar()
print('Without eval:', time() - t)

t = time()
for i in range(10000000):
    foo.baz()
print('With eval:', time() - t)

Results:

Without eval: 4.681713581085205
With eval: 5.766758680343628

@jordanbriere jordanbriere linked a pull request Feb 6, 2021 that will close this issue
jordanbriere added a commit that referenced this issue Feb 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants