[gambit-list] Graceful shutdown of running gambit process
Marc Feeley
feeley at iro.umontreal.ca
Tue Apr 22 18:22:02 EDT 2008
What are the threads blocking on? Apparently, just one thing
(receiving the next request from the student over a socket). It seems
that you want the threads to wait on the occurrence of multiple events:
1) request from the student
2) termination request
This form of waiting can be achieved in several ways (condition
variables, event queues, mailboxes, ...). I suggest you use
mailboxes. The basic idea is this: you have 1 thread waiting for
student requests and dispatching them to the appropriate thread by
adding the request to that thread's mailbox. The termination request
simply adds a "termination" message to the mailbox of all the
threads. So you end up with code like this:
(define (server)
(let ((accept-port (open-tcp-server 8000)))
(let loop ()
(let ((connection (read accept-port)))
(if (not (eof-object? connection))
(begin
(handle connection)
(loop)))))))
(define (handle connection)
(let ((request (read-line connection)))
;; just send it to a random thread
(let ((ws (map car (table->list workers))))
(thread-send
(list-ref ws (random-integer (length ws)))
(make-normal-request request connection)))))
(define (terminate-all-workers)
(let ((ws (map car (table->list workers))))
(for-each (lambda (t)
(thread-send t 'terminate))
ws)))
(define-type normal-request
request
connection)
(define (termination-request? msg)
(eq? msg 'terminate))
(define (worker id)
(pp (list 'worker id 'starting))
(let loop ()
(let ((msg (thread-receive)))
(cond ((normal-request? msg)
(pp (list 'worker id 'got 'normal-request))
(close-port (normal-request-connection msg))
(loop))
((termination-request? msg)
(pp (list 'worker id 'got 'termination-request))
(worker-termination))
(else
(pp (list 'unknown-message))
(loop))))))
(define (worker-termination)
(table-set! workers (current-thread))) ;; remove from workers
(define workers
(list->table
(map (lambda (id)
(cons (thread-start! (make-thread (lambda () (worker id))))
#f))
'(0 1 2 3))))
(thread-start! ;; terminate all workers in 10 seconds
(make-thread
(lambda ()
(thread-sleep! 10)
(terminate-all-workers))))
(server)
On 22-Apr-08, at 3:47 PM, Bradley Lucier wrote:
> Marc:
>
> My homework on the web system needs a way to shut down gracefully.
> Perhaps you can recommend how to do this.
>
> I'm using Gambit-C 4.0a8 (yes, that's right, "a8") because it
> doesn't have the GC bug that plagues long-running Gambit programs
> that use keyword/optional/whatever arguments in more recent versions
> of Gambit.
>
> The program handles up to 1000 students at a time, with > 800
> threads (one for each concurrent student) running an hour or so
> before homework is due ;-). Each Gambit process (there's one
> application running for each course) starts up 5 Maple processes as
> back-end servers. It uses a very simple method to store student
> results---when a student goes from one problem to another or from
> one problem set to another, or when a student logs out or is timed
> out for inactivity, it uses pretty-print to write the student's
> current data to a file, and then uses RCS to archive the difference
> between the current version and the previous one.
>
> Especially near the beginning of each semester, students add and
> drop the course, and move from one section to another. Currently, I
> deal with this by killing the Gambit job and restarting it with the
> new student lists, etc. (Each student's data stays with the
> student, if the student doesn't pay his/her fees and is temporarily
> dropped from the course, all the pre-existing work is still there
> when the student is re-registered for the class; if a student moves
> sections, it only affects to which instructor a student's grades are
> e-mailed.) The restarting is effective, and takes only about 1
> minute or two, but students currently working on the system have to
> log back into the system after the system comes back up.
>
> The problem is that about once a semester, the program is killed as
> a student's data is pretty-printed to the data file, so the data
> that is written is only a truncated list. The next time the program
> attempts to load the data, there is an error, mutexes are abandoned,
> etc. A day or two goes by before it's really bad enough that
> someone informs me there's a problem, and I eventually find the
> problem, restore data from the RCS file, and go on our merry way.
> (To my knowledge, no student data has ever been lost.)
>
> What I'd like is a way to send a signal to the program to shut down
> gracefully---go to each thread, one by one, save the student data,
> use RCS to back it up, and when you've done all that exit gracefully
> (or now restart by reloading the class lists, etc.). This should
> avoid the rare but somewhat catastrophic failures I see when a
> student data file is truncated.
>
> So, that's the background; any suggestions?
>
> Brad
More information about the Gambit-list
mailing list