Here's a tasty little bug. If you schedule a Delay with a duration long enough to be a LargeInteger, it will sit happily in the SuspendedDelays queue until such time as it becomes the next Delay to be activated. At that time, #primitiveSignalAtMilliseconds is called. The primitive is only able to handle SmallIntegers, so it fails, whereupon #primSignal:atMilliseconds: attempts to throw 'a primitive has failed', which bolluxes up the works in the process scheduler. As far as I can tell, this is an unrecoverable error condition.
The following illustrates the problem and will usually crash your image:
| bigDelay | bigDelay := Delay forSeconds: SmallInteger maxVal + 1. [bigDelay wait. Transcript show: 'I have been waiting a long time for this'; cr] fork. (Delay forSeconds: 1) wait. Smalltalk garbageCollect "=> image will hang after failed primitive"
Two things need to be addressed:
1) The primitive should accept large integer arguments. Note that the longest possible delay with a small integer is only about 12 days: Duration seconds: (SmallInteger maxVal / 1000) asInteger => 12:10:15:41
2) Delay class>>primSignal:atMilliseconds: should do something other than #primitiveFailed when the primitive fails. Perhaps writing something to the Transcript would make sense, or just ignore the failure entirely?
This is #854 on Mantis.
Dave
(also on Mantis; CC-ed here because a patch is included)
Asking the primitive to support long integers seems like a bit much to me. The better solution is make a LongDelay class which can handle huge delays. There would have to be a background process periodically checking for LongDelay's that are close to coming into effect, and schedule a regular Delay if so.
That's a lot of work. How about, for now, we have class Delay simply refuse to create long-waiting instances? It's a shame not to support long-running delays, but this would seem much better than the current situation.
Patch attached.
squeak-dev@lists.squeakfoundation.org