Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Signals and Events

9 views
Skip to first unread message

Leopold Toetsch

unread,
Jan 23, 2004, 4:37:31 AM1/23/04
to P6I
The Plan(tm) AFAIK is to convert signals to events[1]. Pressing ^C on the
console or such should be available to user defined exception or signal
handlers.

So the flow of information would be:

1) signal async per definition - in some thread
2) event-handler thread convert to event, which is broadcasted
3) interpreters task queue event-handlers pass it on
4) exception handler converts to exception
5) user action and finally PASM runs

Some experiments on Linux with SIGINT:

I have sorted out signal blocking and threads, so the signal gets
delivered to the event-handler thread. But what now:

,--[ man pthread_cond_signal ]-------------------------------------
| The condition functions are not async-signal safe, and
| should not be called from a signal handler. In particular,
| calling pthread_cond_signal or pthread_cond_broadcast from
| a signal handler may deadlock the calling thread.
`------------------------------------------------------------------

So directly signalling the event queue isn't allowed (a short test
shows: it works, but that doesn't seem to be a solution)

The docs indicate, that a timedwait would return EINTR like the
low-level read(2) or such functions:

,--[ man pthread_cond_signal ]-------------------------------------
| EINTR pthread_cond_timedwait was interrupted by a
| signal
`------------------------------------------------------------------

But:

,--[ less linuxthreads/ChangeLog ]----------------------------------------
| * condvar.c (pthread_cond_timedwait_relative): Never return with
| EINTR. Patch by Andreas Schwab.
`-------------------------------------------------------------------------

So:

,--[ less linuxthreads/FAQ ]----------------------------------------------
| The only sensible things you can do from a signal handler is set a
| global flag, or call sem_post on a semaphore, to record the delivery
| of the signal. The remainder of the program can then either poll the
| global flag, or use sem_wait() and sem_trywait() on the semaphore.
|
| Another option is to do nothing in the signal handler, and dedicate
| one thread (preferably the initial thread) to wait synchronously for
| signals, using sigwait(), and send messages to the other threads
| accordingly.
`-------------------------------------------------------------------------

The event handler thread is waiting on a condition, so the only
possibility seems to be the latter option, that is run another thread
that does nothing but sigwait(3).

[1] where applicable, e.g. no "Program Error Signals"

all citations are from a SuSE 7.3, glibc 2.2.4 system.

Comments welcome,
leo

Leopold Toetsch

unread,
Jan 23, 2004, 6:05:52 AM1/23/04
to perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> wrote:

> The event handler thread is waiting on a condition, so the only
> possibility seems to be the latter option, that is run another thread
> that does nothing but sigwait(3).

While pressing $send_button I realized, that there is another option and
- of course - we'll have to handle IO events too.

So my local src/events.c does:

1) block all signals before any thread creation
2) install an event handler for SIGINT
3) start the event handler thread
4) start an IO handler thread, which does:
- unblock SIGINT
- select in a while loop
- if select returns -1, check for EINTR and the sig_atomic_t flag
set by the signal handler

This works fine. Pressing ^C (and ^\ to quit) in sl.pasm now prints
diagnostics for testing:

started
sig_handler SIGINT in pid 2535
select EINTR
int arrived
Quit

$ cat sl.pasm
print "started\n"
sleep 1000
end

The IO thread can then generate a SIGINT_EVENT and pthread_signal the
event thread. And it could wait on various file-handles and on an
internal pipe, which can be used to communicate file-handles to be
waited on to the IO thread.

Comments welcome,

leo

Dan Sugalski

unread,
Jan 23, 2004, 9:39:27 AM1/23/04
to l...@toetsch.at, perl6-i...@perl.org
At 12:05 PM +0100 1/23/04, Leopold Toetsch wrote:
>Leopold Toetsch <l...@toetsch.at> wrote:
>
>> The event handler thread is waiting on a condition, so the only
>> possibility seems to be the latter option, that is run another thread
>> that does nothing but sigwait(3).
>
>While pressing $send_button I realized, that there is another option and
>- of course - we'll have to handle IO events too.
>
>So my local src/events.c does:
>
>1) block all signals before any thread creation
>2) install an event handler for SIGINT
>3) start the event handler thread
>4) start an IO handler thread, which does:
> - unblock SIGINT
> - select in a while loop
> - if select returns -1, check for EINTR and the sig_atomic_t flag
> set by the signal handler

All this stuff needs to get out of events.c at some point, and we
probably better do it now rather than later. Not because they're not
events, but because this behaviour is all very platform-dependent,
and so ought to go in the platform-local source instead. (It's not
even Unix-dependent, as all the different unix flavors handle signals
and threads differently)

What we need to do is get an abstraction in place for this and write
platform-specific code to get concrete implementations of that
abstraction in place. Which also means we need to have more complex
processing of the platform source files.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Leopold Toetsch

unread,
Jan 23, 2004, 9:52:06 AM1/23/04
to perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> wrote:

[ and another f'up myself ]

> The IO thread can then generate a SIGINT_EVENT and pthread_signal the
> event thread. And it could wait on various file-handles and on an
> internal pipe, which can be used to communicate file-handles to be
> waited on to the IO thread.

I have that part now running too. The IO thread listens (via select
currently) on an internal message pipe, can handle a "stop running"
message, and converts a SIGINT signal into a broadcast event
(EVENT_TYPE_SIGNAL).

Some questions:

Will we have special signal-handler functions for PASM or are the handler
functions plain exception handlers?

And: Should I check the changes in, or submit a ticket?

leo

Leopold Toetsch

unread,
Jan 23, 2004, 10:17:59 AM1/23/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:

> All this stuff needs to get out of events.c at some point, and we
> probably better do it now rather than later.

Yeah. Thought about that too. I'm a bit unhappy with the current
config/gen/platform/* files.

Me thinks that we should do:
- s/generic/posix/g
- add linux.*

All common *nix code, that conforms to POSIX (and is working) could go
into posix.[ch]. If some platform has a different behavior, it could be
overridden in a more specialized file.

> What we need to do is get an abstraction in place for this and write
> platform-specific code to get concrete implementations of that
> abstraction in place. Which also means we need to have more complex
> processing of the platform source files.

And some more config tests.

leo

Gordon Henriksen

unread,
Jan 23, 2004, 11:21:09 PM1/23/04
to Dan Sugalski, l...@toetsch.at, perl6-i...@perl.org
On Friday, January 23, 2004, at 09:39 , Dan Sugalski wrote:

> At 12:05 PM +0100 1/23/04, Leopold Toetsch wrote:
>
>> So my local src/events.c does:
>>
>> 1) block all signals before any thread creation
>> 2) install an event handler for SIGINT
>> 3) start the event handler thread
>> 4) start an IO handler thread, which does:
>> - unblock SIGINT
>> - select in a while loop
>> - if select returns -1, check for EINTR and the sig_atomic_t flag
>> set by the signal handler
>
> All this stuff needs to get out of events.c at some point, and we
> probably better do it now rather than later. Not because they're not
> events, but because this behaviour is all very platform-dependent, and
> so ought to go in the platform-local source instead. (It's not even
> Unix-dependent, as all the different unix flavors handle signals and
> threads differently)
>
> What we need to do is get an abstraction in place for this and write
> platform-specific code to get concrete implementations of that
> abstraction in place. Which also means we need to have more complex
> processing of the platform source files.

It may even be important enough to probe this stuff at runtime and
select the appropriate implementation then, so that a single parrot
binary can be compatible across different versions of the same operating
system. For instance: Linux flavors with per-thread PIDs, or different
versions of Mac OS X with evolving pthreads implementations (or with and
without poll()). Or Windows 98 vs. Server 2003. Finally, if the most
performant strategy might differ for uniprocessors and multiprocessors.

Gordon Henriksen
mali...@mac.com

0 new messages