Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!elroy.jpl.nasa.gov!decwrl!pa.dec.com!src.dec.com!Peter.Robinson@computer-lab.cambridge.ac.uk From: Peter.Robinson@computer-lab.cambridge.ac.uk Newsgroups: comp.lang.modula3 Subject: Re: 1.6 bugs Message-ID: Date: 8 Apr 91 11:50:15 GMT Lines: 117 To: kalsow Cc: Peter.Robinson@computer-lab.cambridge.ac.uk, m3 Inreplyto: kalsow's message of 6 Apr 91 06:49:27 +0100 (Saturday) Original-Sender: Peter.Robinson@computer-lab.cambridge.ac.uk | 4. In spite of their signatures, some routines in Rd don't raise | Thread.Alerted. | | Fix: in system/corelib/filerw/UFileRdWr.m3, | in TerminalReaderSeek link 262, | change RTScheduler.IOSelect | to RTScheduler.IOAlertSelect | | Thanks to Norman Ramsey and David Nichols for reporting these bugs. This fixes Norman Ramsey's problem, but a similar program that I have been struggling with still doesn't seem to work. The idea is to read a line of input from stdin with a 10 second timeout if nothing is read: MODULE Alerts EXPORTS Main; IMPORT Rd, Stdio, Thread, Time, Wr; TYPE Getter = Thread.Closure OBJECT text: TEXT; status := "latent"; METHODS apply := DoGet; END; Timer = Thread.Closure OBJECT interval: CARDINAL; victim: Thread.T; METHODS apply := DoTime; END; PROCEDURE DoGet (self: Getter): REFANY RAISES {} = BEGIN TRY self.status := "reading"; self.text := Rd.GetLine (Stdio.stdin); self.status := "finished"; EXCEPT Thread.Alerted => self.text := ""; self.status := "interrupted"; END; RETURN self; END DoGet; PROCEDURE DoTime (self: Timer): REFANY RAISES {} = BEGIN Time.LongPause (self.interval); Thread.Alert (self.victim); RETURN self; END DoTime; VAR getter := NEW (Getter); thread := Thread.Fork (getter); BEGIN EVAL Thread.Fork (NEW (Timer, interval := 10, victim := thread)); TRY EVAL Thread.AlertJoin (thread); Wr.PutText (Stdio.stdout, "normal join\n"); EXCEPT Thread.Alerted => Wr.PutText (Stdio.stdout, "alerted join\n"); END; Wr.PutText (Stdio.stdout, getter.status & "\n"); Wr.Close (Stdio.stdout); END Alerts. If I have understood it correctly, there should be three possible outcomes: 1. You type quickly and get a normal join with a status of finished. 2. You press return momentarily before the timer goes off and get an alerted join with a status of either reading or finished. 3. You type too slowly and get a normal join with a status of interrupted. The first works just fine. The second occurs with probability approximately zero and has not been tested experimentally. The third is giving problems. Until the latest release, it simply did not work; Rd.GetLine never raised Alerted. With the fix to UFileRdWr.m3, the thread executing getter still seems to be waiting on a select for terminal, even after being marked as alerted. The transcript goes as follows: $ Alerts test normal join interrupted $ test: Command not found. $ The line "test" is typed taking more than 10 seconds, but the alert is only raised when the line is completed. However, the input is then ignored and so is picked up by the shell as the next command. My guess is that the scheduler is proceeding as follows: 1. getter is forked and the thread descheduled pending a select for the read. 2. timer is forked and the thread descheduled pending a select for the timeout. 3. The scheduler blocks on a select for the read or the timeout. 4. The timeout occurs and its thread is rescheduled; it marks getter as alerted and exits. 5. The scheduler ignores the fact that getter is marked as alerted and blocks on another select for the read. 6. When the line of typing is completed, the select returns, the scheduler notices the alert and duly raises Alerted, without the line being read. Of course, I may have got hold of the wrong end of the stick. Advice welcomed. - Peter Robinson.