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
Afficher les réponses par date
Hi,
It would be nice if such a hook could be created on all Gambit platforms. In the meantime, I would simply suggest that you make your persistency code more robust (with transactions for example). Just an idea...
Francois Magnan
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 _______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
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