[Scons-users] Wacky crash in Clone()
Marc Branchaud
marcnarc at xiplink.com
Fri Jan 21 16:39:41 EST 2022
(Possibly should send this to scons-dev@?)
Hi all,
I'm updating a complex build from 2.2.0 (Python 2.7.18) to 4.2.0 (Python
3.10.1), and I've run into this crash. Unfortunately I have been unable
to craft a simple reproduction example, and the code cannot be
published. The crash happens inside an env.Clone() call in a function
being used as an Action's output, where the Action is a custom Builder.
I'm hoping someone can point out something I'm doing that became "wrong"
since SCons 2.2.0. Has there been a change in how custom Builders work?
Or, maybe someone can point me at someplace that might help me figure
out the bug.
The code is basically structured as follows. The custom builder uses
functions from a "BaseBuilder" module defined in site_scons. (I've
elided a lot of setup work in the real code, which is sprinkled among
several different files, many of which are exec()'d by the SConstruct.
I'm trying not to suspect the reliance on exec() to split up what would
otherwise be a giant SConstruct file.)
SConstruct
e1 = Environment(
tools = [ 'MyBuilder' ],
)
e2 = e1.Clone(
CCFLAGS = ['-g']
)
e2.MyBuilder(
target="out",
source="in",
)
site_scons/BaseBuilder.py
def message(target, source, env):
myenv = env.Clone() # <-- This crashes
print("MESSAGE")
def builder(target, source, env):
print("BUILDER")
site_scons/site_tools/MyBuilder.py
import BaseBuilder
def exists(env):
return True
def generate(env, **kwargs):
env['BUILDERS']['MyBuilder'] = env.Builder(
action = env.Action(
BaseBuilder.builder,
BaseBuilder.message,
)
)
Sadly the above code works just fine. But here's the crash from the
real code:
Traceback (most recent call last):
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Taskmaster.py",
line 235, in execute
self.targets[0].build()
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Node/__init__.py",
line 755, in build
self.get_executor()(self, **kw)
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Executor.py",
line 384, in __call__
return _do_execute_map[self._do_execute](self, target, kw)
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Executor.py",
line 117, in execute_action_list
status = act(*args, **kw)
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Action.py",
line 686, in __call__
cmd = self.strfunction(target, source, env)
File
"/usr/home/marcnarc/Code/Worktrees/python3-build/site_scons/BaseBuilder.py",
line 77, in message
myenv = env.Clone()
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Environment.py",
line 1450, in Clone
clone = copy.copy(self)
File "/usr/local/lib/python3.10/copy.py", line 102, in copy
return _reconstruct(x, None, *rv)
File "/usr/local/lib/python3.10/copy.py", line 272, in _reconstruct
if hasattr(y, '__setstate__'):
File
"/usr/local/lib/python3.10/site-packages/SCons-4.2.0-py3.10.egg/SCons/Environment.py",
line 2384, in __getattr__
attr = getattr(self.__dict__['__subject'], name)
KeyError: '__subject'
At the offending line, `self` is an OverrideEnvironment that somehow has
a completely empty __dict__.
One frame up, the `y` that's being checked with hasattr() was created
inside copy.copy()'s _reconstruct() via a __newobj__() call. This `y`
is an OverrideEnvironment but it's __dict__ is empty.
If I set a breakpoint at the dying getattr() line, it gets called twice
before the crash, both with proper OverrideEnvironment objects.
Any ideas? Could something in the build's code have possibly mucked
with the OverrideEnvironment created by __newobj__()? (What would such
a thing even look like?)
My next step will be to bisect this using different Python and SCons
versions. Whee!
M.
More information about the Scons-users
mailing list