This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] tst-setcontext2: avoid bug from compiler optimization


On Wed, 2017-01-25 at 12:23 -0500, Chris Metcalf wrote:
> On 1/25/2017 6:23 AM, Torvald Riegel wrote:
> > On Tue, 2017-01-24 at 19:35 -0500, Chris Metcalf wrote:
> >> Ping!  I will plan to commit this later this week if no one objects; it seems
> >> like a straightforward bug avoidance.
> >>
> >> On 1/13/2017 1:01 PM, Chris Metcalf wrote:
> >>> With an uninitialized oldctx, the compiler is free to observe that
> >>> the only path that sets up a value in oldctx is through the
> >>> "if (global == 2)" arm, in which arm we apparently return 0 without
> >>> referencing oldctx again.
> >>>
> >>> Then, after the "if" cascade, the compiler can inline the "check"
> >>> function and then observe that the sigset_t "set" variable there
> >>> is only used locally, before any apparent uses of oldctx, and as a
> >>> result it can decide to use the same stack region for both variables.
> >>> Unfortunately this has the effect of clobbering oldctx when we call
> >>> sigprocmask, and results in the test failing.
> >>>
> >>> By initializing oldctx at the top, we let the compiler know that it
> >>> has a value that has to be preserved down to the part of the code
> >>> after the "if" cascade, and it won't try to place another variable
> >>> in that same part of the stack.
> > The compiler would also know what the initial value is, which it could
> > store somewhere else, which then would still allow for reuse of a stack
> > slot.
> 
> Good point.
> 
> > I agree with Florian that the compiler needs to be made aware that
> > getcontext can return twice, or something to that effect.  This would
> > tell it that it has to reason about the lifetimes of variables
> > differently.
> 
> The problem is that "returns_twice" doesn't offer the semantics we want.

There are similarities to setjmp/longjmp, I think.

>From C11 7.13.2.1:
All accessible objects have values, and all other components of the
abstract machine have state, as of the time the longjmp function was
called, except that the values of objects of automatic storage duration
that are local to the function containing the invocation of the
corresponding setjmp macro that do not have volatile-qualified type
and have been changed between the setjmp invocation and longjmp call are
indeterminate.

oldctx is modified between the getcontext (like setjmp) and effective
longjmp part of swapcontext.

> It ensures that register-allocated variables are handled properly, i.e.
> everything is saved to the stack frame prior to calling the function.  But
> here the issue is that the stack frame itself isn't being set up in a way that
> actually works.  And in practice, tagging getcontext and swapcontext with
> attribute((returns_twice)) does not fix the bug.  (It does seem like doing so
> isn't a bad idea, but it is beyond the scope of fixing this one test bug.)
> 
> Another way to fix the problem is to make the context variables function static,
> which should forbid the compiler from doing anything funky with them.
> (Although do_test itself is static, it is called from main, and the compiler
> has to assume main could get called again and expect to find the updated
> context variables still updated, so it can't trickily ignore the static modifier
> or anything like that, I think.)

I think that we need the returns_twice attribute, but we also shouldn't
put oldctx on the stack (unless it's marked volatile).


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]