Opened 5 years ago
Closed 5 years ago
#1638 closed defect (fixed)
Signal handling and parameters
Reported by: | Mario Domenech Goulart | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | 5.3 |
Component: | unknown | Version: | 5.1.0 |
Keywords: | signals, parameters | Cc: | |
Estimated difficulty: |
Description
I'm facing a difference in behavior between C4 and C5 regarding signal handling, parameters and load.
The code below hopefully helps illustrate the problem.
There's a loop printing the value of a parameter, and a signal handler that catches SIGHUP and loads a file which sets the parameter.
Case 1: In C4, when the process catches SIGHUP and loads the configuration file, the value of the parameter changes. In C5, the value doesn't change.
Case 2: if we call (load conf-file)
in the toplevel, both C4 and C5 behave the same (expected behavior).
The problem seems to be related to parameters. I tried this code with a regular variable instead of a parameter (using set!
to set it), and in that scenario the program behaves as expected.
$ cat hup.scm (cond-expand (chicken-4 (use posix)) (chicken-5 (import (chicken base) (chicken process signal) (chicken process-context)))) (define param (make-parameter 42)) (define conf-file (car (command-line-arguments))) ; (load conf-file) (set-signal-handler! signal/hup (lambda (signum) (print "reloading conf file") (load conf-file))) (let loop () (print (param)) (sleep 1) (loop)) $ cat conf.scm (param 4) ;;; Case 1: `(load conf-file)` in the toplevel commented out ;;; Steps: ;;; 1. run hup.scm ;;; 2. go to another terminal and kill it with signal 1 $ ~/local/chicken-4.13.0/bin/csi -s hup.scm conf.scm 42 42 42 reloading conf file 4 4 4 $ ~/local/chicken-5.1.0/bin/csi -s hup.scm conf.scm 42 42 42 reloading conf file 42 42 42 ;;; Case 2: `(load conf-file)` in the toplevel uncommented. ;;; Notice that now the conf file is loaded in the toplevel and ;;; the configuration file contains `(param 4)'. ;;; Steps: ;;; 1. run hup.scm ;;; 2. go to another terminal change param in conf.scm (to 10) ;;; and kill csi with signal 1 $ ~/local/chicken-4.13.0/bin/csi -s hup.scm conf.scm 4 4 4 reloading conf file 10 10 10 ;;; Here the config file has the param set to 10 (previous execution) ;;; and I set it to 12 before sending signal 1 to csi. $ ~/local/chicken-5.1.0/bin/csi -s hup.scm conf.scm 10 10 10 reloading conf file 12 12 12
Attachments (1)
Change History (6)
comment:1 Changed 5 years ago by
Milestone: | someday → 5.3 |
---|
comment:2 Changed 5 years ago by
Keywords: | load removed |
---|
Changed 5 years ago by
Attachment: | scheduler.diff added |
---|
comment:3 Changed 5 years ago by
if I correctly traced the problem, it is located in scheduler.
##sys#update-thread-state-buffer
and ##sys#restore-thread-state-buffer
are used to save/restore elements, and among others ##sys#current-parameter-vector
(which keep track of parameters changes).
with the current code of the scheduler, after an interruption is proceeded, the thread-state-buffer is overrided (without saving) by previous state, resulting changes lost.
the code exposes the problem because when (param 42)
is called the vector is resized before the interruption-code. so it is the same vector which is used (even if value inside the vector changed). When (param 42)
is not called, when the interruption-code call (param 4)
it trigger a resize, and so ##sys#current-parameter-vector
points to a new vector with new values, and once the primodial thread is rescheduled, it first calls ##sys#restore-thread-state-buffer
and ##sys#current-parameter-vector
is overrided by the old vector (with old values).
With a modified scheduler.scm, I have the following trace:
switching to #<thread: primordial> ##sys#restore-thread-state-buffer: override global with thread data: global=29 thread=29 42 #<thread: primordial> blocks for timeout 4652.0 ==================== scheduling, current: #<thread: primordial>, ready: () ##sys#update-thread-state-buffer: override thread data with global: global=29 thread=29 timeout: #<thread: primordial> -> 4652.0 (now: 3652) reloading old value 42 new value 4 primordial thread forced due to interrupt unblocking: #<thread: primordial> switching to #<thread: primordial> ##sys#restore-thread-state-buffer: override global with thread data: global=31 thread=29 42 #
it shows that after the interrupt code, when the primodial thread is rescheduler, the global vector (with size 31) is overrided by the thread-state-buffer data (a vector with size 29).
the attached diff calls ##sys#update-thread-state-buffer
before primordial thread is rescheduled. but as I am unfamiliar with scheduler internal, I am unsure it is properly done.
comment:4 Changed 5 years ago by
Thanks a lot Sebastien! I don't know if this is the right fix, but it does solve the issue I reported. Tested with master as of 10180e4cf73e3ee0c894b41c91b30337f877087f.
comment:5 Changed 5 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
Fixed by 6c3a82c35350763efdb4a9bf2a49614b5d9be23a
the testcase could be simplified to not depend on (load).
when
(param 42)
is uncommented, the code works as expected, and the signal handler properly change the parameter.else the parameter continues to return
42
value even after signal hander called(param 4)