Merge lp://qastaging/~smspillaz/compiz-core/compiz-core.fix_931927 into lp://qastaging/compiz-core
- compiz-core.fix_931927
- Merge into 0.9.7
Status: | Merged |
---|---|
Merged at revision: | 3010 |
Proposed branch: | lp://qastaging/~smspillaz/compiz-core/compiz-core.fix_931927 |
Merge into: | lp://qastaging/compiz-core |
Diff against target: |
420 lines (+87/-89) 9 files modified
include/core/abiversion.h (+1/-1) include/core/option.h (+3/-3) include/core/plugin.h (+2/-2) plugins/move/src/move.cpp (+7/-7) plugins/resize/src/resize.cpp (+7/-7) src/event.cpp (+1/-1) src/option.cpp (+62/-64) src/plugin.cpp (+1/-1) src/session.cpp (+3/-3) |
To merge this branch: | bzr merge lp://qastaging/~smspillaz/compiz-core/compiz-core.fix_931927 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Griffiths | Approve | ||
Daniel van Vugt | Approve | ||
Tim Penhey | Pending | ||
Review via email: mp+93779@code.qastaging.launchpad.net |
This proposal supersedes a proposal from 2012-02-16.
Commit message
Description of the change
Only call removeAction on the CompOption destructor and not the CompOption::Value
destructor, since plugins that make copies of CompOption::Value can cause actions to
be added through setOptionForPlugin and then those actions will be removed when the
value temporary goes away.
The action adding and removing only happens within the bounds of CompOption anyways, so
its its more appropriate to have it in its destructor.
Of course, this brings up another issue, which is that CompOption should be noncopyable
but this opens up a whole another can of worms.
How this even worked before is beyond me...
(See also lp:~smspillaz/compiz-expo-plugin/compiz-expo-plugin.api_change_931927)
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
And change:
extern CompOption::Vector noOptions;
to:
extern const CompOption::Vector noOptions;
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
And the same for all of:
164 -CompOption::Vector noOptions (0);
165 -CompOption:
166 -CompString emptyString;
167 -CompMatch emptyMatch;
168 -CompAction emptyAction;
169 -unsigned short emptyColor[4];
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
All the globals should remain globals instead of functions. Perhaps convert them to const for safety.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Static initialization and destruction, basically.
There's a case where the destructor would be called on the global when a plugin was loaded (compiler, linker bug?) before it was actually fully constructed.
I would have made them const, but a lot of the Option* code requires a non const reference. It worked fine even when the globals weren't const, so I don't think this is an issue.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
OK, that's not a compiler/
The real problem must be globals using other globals during their construction/
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Its not worth fixing in this branch :)
The best way to get around this fiasco, is like the article says, to use the construct-
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
> OK, that's not a compiler/
> I have seen many such static ctor/dtor DSO bugs on various Unixes before, but
> not Linux, at least not for ~10 years.
To clarify, I guess the reason why I said linker bug was because of this
#0 CompAction::active
#1 CompOption:
#2 __static_
The use of uninitialized globals within the constructors of other globals is fine, but calling the destructor to a static object before we hit main () is very strange indeed.
(And yes, I've hit compiler bugs before where destructors were incorrectly called :P)
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
OK, I agree it's a quick fix that should work, even though it impacts the public API in a less than ideal way.
Alan already started logging bugs describing the removal of globals such as screen (in the distant future)...
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
And I do believe you now :)
But you will probably find some obscure DSO-related reason for the apparently premature destruction.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
> OK, I agree it's a quick fix that should work, even though it impacts the
> public API in a less than ideal way.
>
> Alan already started logging bugs describing the removal of globals such as
> screen (in the distant future)...
The good news is that only one plugin was impacted by this.
It would be so awesome if const references could be NULL. I guess that's what exceptions are for.
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal | # |
I have to agree with Daniel on a number of points. This is kinda ick, but
better than nothing as far as I can tell.
Might as well remove the boost/noncopyable header since you are not using it.
You do hit a couple of differences here.
Static initialisation initially zeros things out. So...
unsigned short emptyColor[4];
would be zero initialised.
When you have a static variable in a function, I don't think it is zero
initialised. Worth checking with Alan about that. So, inside the emptyColor
function use:
static unsigned short v[4] = {0,0,0,0};
We need to file bugs about the catch (...) bits, that's just ick.
I can't comment on whether this fix actually works. Ideally we'd have test
coverage :-(
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal | # |
> And I do believe you now :)
>
> But you will probably find some obscure DSO-related reason for the apparently
> premature destruction.
What do you mean by DSO-related?
And I have to say that everytime I've come across a weird destruction bug, whether mis-timed or double delete, it has been a coding error, not the compiler.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
I mean that if this destruction issue /is/ a bug then it is most likely triggered by using dynamic shared objects. I've seen many such loader/
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Re: "Static initialisation initially zeros things out"
Is that in the C++ spec? As far as I know, basic types like;
unsigned short emptyColor[4];
will not be initialized at all, because they don't have a constructor.
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal | # |
> Re: "Static initialisation initially zeros things out"
>
> Is that in the C++ spec? As far as I know, basic types like;
> unsigned short emptyColor[4];
> will not be initialized at all, because they don't have a constructor.
Normally no, but for statics / globals, yes.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
If that's true I would still recommend explicit initialization for the sake of readability :)
Tim Penhey (thumper) : Posted in a previous version of this proposal | # |
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> Re: "Static initialisation initially zeros things out"
>
> Is that in the C++ spec? As far as I know, basic types like;
> unsigned short emptyColor[4];
> will not be initialized at all, because they don't have a constructor.
Local statics have a special case (don't you just love C++) - they are zero initialized (the same as namespace scope variables - which is what they are to the link loader).
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
Oh, and you don't need
"static unsigned short v[4] = {0,0,0,0};"
either:
"static unsigned short v[] = {0,0,0,0};"
or
"static unsigned short v[4] = {0};"
is fine
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
*** Found the problem ***
CompOption::Vector noOptions (0);
causes a reserve of at least one CompOption to be constructed (and then quickly destructed)
The fix is to change:
CompOption:
to:
CompOption:
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
> *** Found the problem ***
>
> CompOption::Vector noOptions (0);
> causes a reserve of at least one CompOption to be constructed (and then
> quickly destructed)
>
> The fix is to change:
> CompOption::Vector noOptions (0);
> to:
> CompOption::Vector noOptions;
It is still better to use the on-demand construction, for reasons specified above. I'll fix this though.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
This means we don't need to change the public API of "noOptions" or need to change any plugins. You're now doing it for stylistic reasons only. :)
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
There is still a risk involved. I'd much prefer to have less risky code then to be tripped up later.
This isn't "purely stylistic"
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
(Also as evidenced by the fact that PrivateAction was not even created during static initialization and destruction makes me more inclined to make it like this)
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
170 + CompString & emptyString ()
Rather invites:
emptyString () = CompString("Murphy rules!");
(The same applies to a lot of the functions, and the original [non-]constants.)
So, we should add const to the "constants" while addressing this problem.
On the comment discussion: Global data, monostate & singleton are all likely causes for issues. So this code could do with some cleanup regardless of "on demand" or "global data".
As Sam says, it is slightly safer to use "on demand" than global variables - as it ensures they have actually been initialized before use. OTOH, if we "know" there is no init-sequence issue that only makes the design marginally better.
So, I wouldn't have done the "wrapping" if the problem can be fixed more simply. But, if we had the code ready to go I'd take it, it make the codebase a safer place to live.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
I can remove all the global data, but I can tell you know that the diff is going to get a *lot* bigger (ditto for adding constness)
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal | # |
Sam, if the change to the vector constructor is enough to fix this bug, we should go with the simplest possible branch.
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal | # |
I have to admit to preferring to use the default constructor for vectors rather than trying to be clever with the size. It also means that people don't have to go and look for what the integer parameter constructor does.
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
"Don't initialize to list size zero since that creates a temporary and destroys it
(for gosh knows what reasons)"
That's because it calls a constructor with a default parameter. Vis:
CompOption:
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
I'd really like to know what all the push back on delaying initialization till use is, its a far safer way of doing things and doesn't have any obvious drawbacks.
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal | # |
Please also change the constructor in noOptions too:
static CompOption::Vector v (0);
should be:
static CompOption::Vector v;
Given that there were also issues around the ordering of the static object initialisation that Sam said he saw, I'm in favour of landing this branch. However, we should look to clean the whole mess up soonish.
I want to know though what the impact is of making these constants.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Yes indeed on demand construction is more than stylistic. I think my clumsy words missed the point there. My point should have been that on demand construction (while being good for preventative maintenance), is causing a lot more code to change just before a release. And that's a risk.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Conditionally approved, pending the 1-line fix Tim mentioned:
210 + static CompOption::Vector v (0);
becomes:
210 + static CompOption::Vector v;
I've also tested for further API breakage in libcompizconfig, compiz-plugins-main and compiz-
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Impact of removing the const is that we need to remove these
CompAction &
CompOption:
{
try
{
return boost::
}
catch (...)
{
return emptyAction ();
}
}
CompMatch &
CompOption:
{
try
{
return boost::
}
catch (...)
{
return emptyMatch ();
}
}
CompString &
CompOption:
{
try
{
return boost::get < CompString > (mValue);
}
catch (...)
{
return emptyString ();
}
}
which I am +1 for but I'm not sure how much client code uses these
Daniel van Vugt (vanvugt) wrote : | # |
Satisfies my previous comment.
Alan Griffiths (alan-griffiths) wrote : | # |
Reads OK.
Still concerned about the lack of const-safety, But willing to leave that for posterity.
The noOptions API change makes me nervous. Especially the part about returning a reference to a static local:
203 +CompOption::Vector &
204 +noOptions ()
205 +{
206 + static CompOption::Vector v (0);
207 + return v;
208 +}
Why not just change the global: :Vector noOptions (0);
CompOption:
to:
const CompOption::Vector noOptions (0);
??