[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