[Scons-users] Wacky crash in Clone()
Bill Deegan
bill at baddogconsulting.com
Fri Jan 21 17:47:41 EST 2022
Clone() in an Action would happen on a thread.
Environment's shouldn't be modified in a thread...
Why do that?
On Fri, Jan 21, 2022 at 2:46 PM Bill Deegan <bill at baddogconsulting.com>
wrote:
> scons-users is the right place.
>
> So you're Clone()'ing inside an Action()?
> Yeah..that's a BAD idea...
>
> On Fri, Jan 21, 2022 at 1:39 PM Marc Branchaud via Scons-users <
> scons-users at scons.org> wrote:
>
>> (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.
>> _______________________________________________
>> Scons-users mailing list
>> Scons-users at scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist4.pair.net/pipermail/scons-users/attachments/20220121/0daeca81/attachment.htm>
More information about the Scons-users
mailing list