[M3devel] using *context functions for user threading?
Tony Hosking
hosking at cs.purdue.edu
Sat Jan 31 05:08:49 CET 2009
It doesn't work because of security enhancements that prevent forgery
of a context as the current system does. swapcontext *is* used on
Solaris (as currently implemented) but the InitContext code needs
replacing with makecontext. longjmp is not async-signal-safe, and so
just as bad as swapcontext when called from a signal handler. Indeed,
BSD seems to imply swapcontext can be used in a signal handler.
I don't want to leap into explicit polling of a yield flag without
further thought. Better to get
Antony Hosking | Associate Professor | Computer Science | Purdue
University
305 N. University Street | West Lafayette | IN 47907 | USA
Office +1 765 494 6001 | Mobile +1 765 427 5484
On 31 Jan 2009, at 14:46, Jay wrote:
>
> I think setjmp/longjmp would continue to be ok.
> It has very little machine dependency, and I /guess/ works and is
> portable.
> I guess. We are both leary, but it's been there a while.
> It is InitContext imho that could be "better" -- more portable,
> remove all the
> mucking around with frames and stack pointers.
> I was late to see this because it is in the machine-independent
> chunk of code.
>
>
> What does swapcontext buy over setjmp/longjmp, once a thread is
> "already started"?
> I can see there is a "unifying" reason.
> If makecontext is used to InitContext, then swapcontext is needed to
> "start" a thread.
> setjmp/longjmp could be used to suspend/resume, but if you phrase
> "start" and "resume" as the same thing, then "stuck" with swapcontext.
>
>
> For some time I was under the impression that Modula-3 repeatedly
> longjmped to a buffer that only had setjmp called once, or where the
> function that setjmp was called from had returned, but I'm not sure
> of that now. It seems viable to "follow the rules" wrt setjmp/
> longjmp, other than the "escaping from a signal handler" aspect.
>
>
>> The safest solution for all of this is to have the timer signal
>> handler set a flag and for the M3 compiler to inject a test of the
>> flag at calls/backward branches, and explicitly yield if the flag is
>> set.
>
>
> Yes that makes me much more comfortable as well.
>
>
> Is it cut & dry agreed to and such?
>
>
> Someone should just do it?
>
>
> Or there are concerns that:
> - it might not be often enough?
> There are no "forward" or "backward" branches at the Modula-3
> level, are there?
> It is at the whim of the backend, right? I guess you might be
> able to
> conceptually label branches as forward or backward, even if the
> backend "rotates" things or
> adds more branches (you know, like loops often starting with a
> forward branch).
> - it might be too often?
> - it might be too code bloating? Or too slow when "checks" greatly
> outweight actual switches?
> - a call out to a function or a check of a variable?
> - only do it if a compiler command line switch is given? Or for
> platforms known to support user threads? (given the design
> though..it could be every platform)
>
>
> Though I raise the issues, it still seems the right thing, vs.
> longjmping out of a signal handler.
>
>
> The OpenBSD sigaction manpage does seem to have in mind an ability
> to "switch threads" in a signal handler:
>
>
> "When a caught
> signal is delivered, the current state of the process is saved,
> a new
> signal mask is calculated (as described below), and the signal
> handler is
> invoked. The call to the handler is arranged so that if the
> signal han-
> dling routine returns normally the process will resume execution
> in the
> context from before the signal's delivery. If the process
> wishes to re-
> sume in a different context, then it must arrange to restore the
> previous
> context itself.
> "
>
> but the idea here is not longjmp or I think exactly swapcontext, but
> manually swapping a context with the third parameter to the signal
> handler.
>
>
>> single-threaded process, but I don't know if that really prevents a
>> timer signal arriving inside the signal handler, and what impact that
>> might have.
>
>
> Right. I don't see that control-c can't come in at about the same
> time as timer.
> Though I think sigaction allows for fixing this -- block all signals
> during the signal handler.
> I'll reread some manpages.
>
>
> - Jay
>
>
>
> ----------------------------------------
>> From: hosking at cs.purdue.edu
>> To: jay.krell at cornell.edu
>> Date: Sat, 31 Jan 2009 14:09:23 +1100
>> CC: m3devel at elegosoft.com
>> Subject: Re: [M3devel] using *context functions for user threading?
>>
>> On 31 Jan 2009, at 09:49, Jay wrote:
>>
>>> Tony, can you tell me more of what you have in mind here?
>>
>> I didn't plan anything other than using swapcontext instead of
>> longjmp
>> in switch_thread, and using makecontext instead of InitContext to get
>> a forked thread's context.
>>
>>> In particular...I /think/ it goes like:
>>>
>>>
>>> use getcontext + makecontext to "create a thread"
>>> use simple struct copying/memcpy of the third parameter to the
>>> signal handler for context switching
>>
>> No, swapcontext.
>>
>>> in particular -- setcontext/makecontext never used -- except to
>>> start a thread, but not to switch to/from already started threads.
>>
>> Right.
>>
>>> ?
>>>
>>>
>>> Implication here is that even on systems without context APIs, our
>>> ucontext_t needs to match what the signal handler gets. That isn't
>>> the case for what I just got "working" (prototype, proof of concept,
>>> whatever) on OpenBSD, but easy enough.
>>
>> I don't know what you are saying here. swapcontext should be enough.
>>
>>> An alternative is to call setcontext in the signal handler, but that
>>> makes me nervous.
>>> It seems best to exit "cleanly" out of a signal handler?
>>
>> You're right, but this is probably broken for the current longjmp-
>> based implementation too.
>>
>>> And then I get to seeing very murky things, like, can a system call
>>> be interrupted by an alarm signal? If so, switching threads
>>> then...what would that do? Seems bad.
>>
>> Yes, I was never convinced that the longjmp-based implementation was
>> safe either. I figured that it probably worked only because it was a
>> single-threaded process, but I don't know if that really prevents a
>> timer signal arriving inside the signal handler, and what impact that
>> might have.
>>
>>> So then I guess I see the origin of all the original system call
>>> wrappers -- to turn of thread switching during system calls.
>>
>> No, those were only for GC.
>>
>>> ?
>>>
>>> The current code does appear to longjmp out of a system call -- or
>>> rather, to longjmp from one alarm signal to another. Again this
>>> seems confusing if alarm signals can interrupt system calls.
>>
>> Right...
>>
>>> Some abstraction that encompasses Win32 fibers might be nice, though
>>> there would remain the question of how to preempt.
>>
>> The safest solution for all of this is to have the timer signal
>> handler set a flag and for the M3 compiler to inject a test of the
>> flag at calls/backward branches, and explicitly yield if the flag is
>> set.
>>
>>>
>>>
>>> - Jay
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20090131/7cd23cfd/attachment-0002.html>
More information about the M3devel
mailing list