[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