[Scons-users] Wacky crash in Clone()

Bill Deegan bill at baddogconsulting.com
Fri Jan 21 17:46:47 EST 2022


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/86b5cdd8/attachment-0001.htm>


More information about the Scons-users mailing list