• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: EVFILT_SIGNAL - observe "standard" signals before they are delivered?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: EVFILT_SIGNAL - observe "standard" signals before they are delivered?


  • Subject: Re: EVFILT_SIGNAL - observe "standard" signals before they are delivered?
  • From: Terry Lambert <email@hidden>
  • Date: Thu, 6 Sep 2007 16:19:36 -0700

On Sep 5, 2007, at 12:00 PM, Jim Correia wrote:
The man page says:

EVFILT_SIGNAL Takes the signal number to monitor as the identifier and
returns when the given signal is delivered to the process.
This coexists with the signal() and sigaction() facili-
ties, and has a lower precedence. The filter will record
all attempts to deliver a signal to a process, even if the
signal has been marked as SIG_IGN. Event notification
happens after normal signal delivery processing. data
returns the number of times the signal has occurred since
the last call to kevent(). This filter automatically sets
the EV_CLEAR flag internally.


Am I interpreting that correctly to mean that a signal whose default behavior is process termination (SIGSEGV, for example) will not be observable by the kevent mechanism?

Short answer:

No, it just means that you don't get to see the signal before the process does and prevent its delivery; you are only an observer. It also means that there is no guarantee of ordering, so you're not allowed to make any assumptions about it.

-

Long answer:

Signals are very complicated on MacOS X due to interaction with the Mach AST model (True64 UNIX has the same issues, as it is also Mach- based, and uses the AST mechanism to deliver signals).

A signal starts as a Mach exception, which can be intercepted and averted, if you hold the exception port for the process and know what you are doing. For example, gdb only partially knows what it's doing; if you don't turn off "start-with-subshell", which is on by default, for example, gdb wil hold the exception port on the subshell rather than the process being debugged, and you will not be able to override signals, since you will only see them in gdb via ptrace, rather than as a Mach exception.

After it goes to the task exception port because it hasn't been intercepted at the Mach exception level, it becomes an AST_BSD, and then is only handled when a thread stops being uninterruptible. It becomes interruptible in Mach, which throws the AST at that point.

This means there can be considerable latency, if an operation is uninterruptible, and it can also mean that the operation that was in progress at the time of the exception being thrown may in fact have completed successfully, rather than being interrupted (so, for example, you seldom see a disk read getting interrupted by a signal and returning EINTR).

After this, if the operation was interruptible (e.g. a tsleep/msleep operation on a tty wait queue or whatever), the operation is interrupted, and goes to return an EINTR up to the user/kernel boundary (an error on the BSD system call).

When we run up to the user/kernel boundary, we return to an address other than the address requested, with a bunch of state on the stack (this boils down to a "siginfo" structure with potentially multiple ucontext, mcontext, and other state structures dealing with process state prior to the running of a signal handler). The address we return to is several bytes off the actual system call stub return address, and it jumps to the signal handler for the signal in question (based, in part, on some contents of the siginfo structure which must be treated as opaque by user space application).

The handler runs in user space, then calls a system call that says "put my state back to what it was before the handler fired", and is passed the context information we passed to user space in the first place ("sigreturn").

At this point, the thread state is restored, and we return the EINTR to the system call caller.

-

The thrown AST is caught in kern_sig.c, which is what throws the KNOTE that causes the kevent to get delivered to you. Unless it gets here, you don't get the event.

-

So you won't see the signal if you intentionally intercept it (mostly by Mach means) prior to the thrown AST being turned into a "real" signal, which in turn will get delivered when it's delivered, which can be before or after your event gets delivered, depending on the code path on which the exception happened.

You can ALSO not see a signal if the signal would have been EINTR, and the operation was not an explicit signal send, AND the underlying operation completed successfully because all the work it had to do happened before the process (Mach task, actually) became interruptible. Our UNIX certification has the same permanent interpretation on this that True64 UNIX has, and that a couple of vendors have had on their signal implementations in the past.


-- Terry _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Follow-Ups:
    • Re: EVFILT_SIGNAL - observe "standard" signals before they are delivered?
      • From: Jonas Maebe <email@hidden>
References: 
 >EVFILT_SIGNAL - observe "standard" signals before they are delivered? (From: Jim Correia <email@hidden>)

  • Prev by Date: Re: Poor performance of pthreads across cpu dies.
  • Next by Date: Re: EVFILT_SIGNAL - observe "standard" signals before they are delivered?
  • Previous by thread: EVFILT_SIGNAL - observe "standard" signals before they are delivered?
  • Next by thread: Re: EVFILT_SIGNAL - observe "standard" signals before they are delivered?
  • Index(es):
    • Date
    • Thread