Re: Wacky crash in Clone()
Bill Deegan <[email protected]>
| Newsgroups | gmane.comp.programming.tools.scons.user |
|---|---|
| Message-ID | <CAEyG4CFrV-PNz=8i9cM1XUTpsL=FRP8wVASFEu9LcVRUp-=LXw@mail.gmail.com> |
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 <[email protected]> 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 < > [email protected]> 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 >> [email protected] >> https://pairlist4.pair.net/mailman/listinfo/scons-users >> > _______________________________________________ Scons-users mailing list [email protected] https://pairlist4.pair.net/mailman/listinfo/scons-users