Summary

High CPU usage when calling signal handler multiple times

Metadata

Attachments

Description

Here's an example to demonstrate the aforementioned behavior:

 ;; Press C-c multiple times in an interval < 20s
 
 (use posix)
 
 (set-signal-handler!
  signal/int
  (lambda (signal)
    (print "caught signal" signal)
    (sleep 20)))
 
 
 (let loop ()
   (sleep 1)
   (loop))

I cannot reproduce that behavior on 4.7.0. Peter mentioned on IRC that b7995839c0b481280bdeda117eb68bc0e78a40bf triggered it.

Changes and comments

[2013-02-27 22:56:55 UTC] sjamaan wrote:

Oddly enough, if I throw out the HAVE_SIGACTION from Makefile.bsd, make spotless and rebuild, it still fails the same way (on master). It seems to be related to the reworking of the signal handling itself.

gdb seems to point to an infinite loop in the GC, but that's rather difficult to understand given the setjmp/longjmp stuff. ktrace shows that it keeps setting and resetting a signal mask.

[2013-02-27 23:09:58 UTC] sjamaan wrote:

Ripping out the queueing up of pending events (so that interrupt_reason is overwritten like it used to be) doesn't help either.

[2013-02-28 21:13:48 UTC] sjamaan wrote:

[2013-03-01 11:26:22 UTC] megane attached signal-handler-hack.patch (description=a hack that makes the symptoms go away)

[2013-03-01 11:35:50 UTC] megane wrote:

Now that I try to think why that patch works, I cannot come up with an explanation.

But something seems to go wrong when multiple signal-handlers are running at the same time.

[2013-07-27 18:13:55 UTC] sjamaan wrote:

Extremely interesting: I cannot reproduce the problem when I add a single print statement after the (sleep 20) in the signal handler:

 #!scm
 ;; Press C-c multiple times in an interval < 20s
 
 (use posix)
 
 (set-signal-handler!
  signal/int
  (lambda (signal)
    (print "caught signal" signal)
    (sleep 20)
    (print "done")))
 
 (let loop ()
   (sleep 1)
   (loop))

So far, I can't explain this yet.

[2013-10-06 21:11:23 UTC] sjamaan wrote:

Still unclear, but the continuation of sleep seems to be doing something very strange. If we explicitly capture the continuation (which should be identical to the implicit continuation) and pass it to the procedure when we invoke it, it works. If we use the continuation supplied by the foreign-lambda wrapper, it breaks.

However, if sleep(x) is replaced by a constant integer, it works with either continuation.

 #!scm
 (use posix)
 
 ;; BROKEN:
 (define do-sleep
   (foreign-primitive ((scheme-object k) (int x))
                      "printf(\"%d\\n\", sleep(x)); C_values(2, C_SCHEME_UNDEFINED, C_k);"))
 
 ;; OKAY:
 (define do-sleep
   (foreign-primitive ((scheme-object k) (int x))
                      "printf(\"%d\\n\", sleep(x)); C_values(2, C_SCHEME_UNDEFINED, k);"))
 
 
 (set-signal-handler!
  signal/int
  (lambda (signal)
    (print "caught signal" signal)
    (call/cc (lambda (k) (do-sleep k 10)))))
 
 
 (let loop ()
   (sleep 1)
   (loop))

It gets weirder and weirder!

[2013-10-11 20:40:55 UTC] sjamaan wrote:

This could be related to #1058. If either is fixed, the other should be re-tested.

[2013-11-03 17:53:46 UTC] sjamaan wrote:

I think #877 is due to the same underlying problem. There seems to be something strange going on when handling interrupts. I think the reason the bug goes away when messing with the continuation is because we're now allowing interrupts to get handled via the "regular" way, through the GC rather than explicitly by C_pending_interrupt.

I still not quite grok it, but this seems to be the case. A fix is by not calling C_pending_interrupt, but this would kill the ability to save a backlog of interrupts (effectively undoing b7995839c0b481280bdeda117eb68bc0e78a40bf).

[2013-11-03 21:42:38 UTC] sjamaan wrote:

A better solution is in the works

[2013-11-04 23:09:35 UTC] mario wrote:

Fixed by 3f43b7c808269ff9eba0702800018ed327d7758e

[2013-11-05 09:40:04 UTC] sjamaan changed status from new to closed

[2013-11-05 09:40:04 UTC] sjamaan set resolution to fixed