Opened 8 months ago

Closed 4 weeks 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)

scheduler.diff (632 bytes) - added by Sebastien Marie 4 weeks ago.

Download all attachments as: .zip

Change History (6)

comment:1 Changed 7 months ago by Mario Domenech Goulart

Milestone: someday5.3

comment:2 Changed 5 weeks ago by Sebastien Marie

Keywords: load removed

the testcase could be simplified to not depend on (load).

$ 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))
;(param 42)

(set-signal-handler!
 signal/hup
 (lambda (signum)
   (print "reloading")
   (param 4)
   ))

(let loop ()
  (print (param))
  (sleep 1)
  (loop))

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)

Changed 4 weeks ago by Sebastien Marie

Attachment: scheduler.diff added

comment:3 Changed 4 weeks ago by Sebastien Marie

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.

Last edited 4 weeks ago by Sebastien Marie (previous) (diff)

comment:4 Changed 4 weeks ago by Mario Domenech Goulart

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 4 weeks ago by megane

Resolution: fixed
Status: newclosed

Fixed by 6c3a82c35350763efdb4a9bf2a49614b5d9be23a

Note: See TracTickets for help on using tickets.