Hi all,
looking for a new way to crash the image? :-) Here is one:
gen := Generator on: [:gen | self assert: gen next isNil. self error]. gen yield: 1.
This is a less idiomatic but more comprehensible version:
[c := thisContext. [h := thisContext. [h swapSender: thisContext sender. c := thisContext swapSender: c] value. thisContext swapSender: c] value] value. [c := thisContext swapSender: c. self error] value.
In a nutshell, the Generator temporarily creates a loop on the stack while switching coroutines. I didn't fully get behind its implementation at the moment, and I acknowledge that I am using the generator in the "wrong" way - usually the #on: block is the producer not the consumer. However, and especially with the recent debate on safe languages in mind, I wonder whether we would be able and willing to make Squeak safe against this phenomen (loops on the stack).
The actual crash (or better: hang) comes from primitiveFindHandlerContext, but I assume primitiveFindNextUnwindContext and primitiveTerminateTo would cause a similar effect. A simple fix would be to disable these optional primitives and use the image fallback instead. This makes the method interruptable similar to a convenient infinite loop. However, this is obviously much slower. I wonder whether these primitives could be made aware of possible context stack loops and fail when a loop is detected. When the primitive fails, the fallback code would run so the image would be interruptable again, or even better, we could also detect particular stack loops then:
Context>>findNextHandlerContextStarting "Return the next handler marked context, returning nil if there is none. Search starts with self and proceeds up to nil."
- | ctx | - <primitive: 197> + | ctx known | ctx := self. + known := IdentitySet new. [ctx isHandlerContext ifTrue:[^ctx]. + (known ifAbsentAdd: ctx) ifFalse: [Processor debugWithTitle: 'Loop on stack detected!' translated full: false]. (ctx := ctx sender) == nil ] whileFalse. ^nil
So my questions to you are: Do we want to support this kind of safety (I would like it!)? Is this possible to implement in the VM without a concerning performance impact?
Best, Christoph
--- Sent from Squeak Inbox Talk
Hi Christoph,
looking for a new way to crash the image? :-) Here is one:
Highlighted on my todo list :)
In the meantime here's a VM crasher I came across while studying a bug in #return:from:
Process new return: nil value: nil.
It generates an infinite stream of debuggers. I can't figure out what is going on but it has something to do with the recursion in #effectiveProcess (when I removed the recursion the infinite debuggers stream and VM crash was gone).
The crash is irrecoverable and I'm only able to capture the notifier window before killing the process. The system seems so confused it managed to send a non-integer to #priority :) (And that points to #effectiveProcess)
I'm just curious... I remember you worked on infinite debugger chains. Any explanation very welcome. Best, Jaromir
On 28-Nov-23 7:58:38 PM, christoph.thiede@student.hpi.uni-potsdam.de wrote:
Hi all,
looking for a new way to crash the image? :-) Here is one:
gen:=Generatoron:[:gen| selfassert:gennextisNil. selferror]. genyield:1.
This is a less idiomatic but more comprehensible version:
[c:=thisContext. [h:=thisContext. [hswapSender:thisContextsender. c:=thisContextswapSender:c]value. thisContextswapSender:c]value]value. [c:=thisContextswapSender:c. selferror]value.
In a nutshell, the Generator temporarily creates a loop on the stack while switching coroutines. I didn't fully get behind its implementation at the moment, and I acknowledge that I am using the generator in the "wrong" way - usually the #on: block is the producer not the consumer. However, and especially with the recent debate on safe languages in mind, I wonder whether we would be able and willing to make Squeak safe against this phenomen (loops on the stack).
The actual crash (or better: hang) comes from primitiveFindHandlerContext, but I assume primitiveFindNextUnwindContext and primitiveTerminateTo would cause a similar effect. A simple fix would be to disable these optional primitives and use the image fallback instead. This makes the method interruptable similar to a convenient infinite loop. However, this is obviously much slower. I wonder whether these primitives could be made aware of possible context stack loops and fail when a loop is detected. When the primitive fails, the fallback code would run so the image would be interruptable again, or even better, we could also detect particular stack loops then:
Context>>findNextHandlerContextStarting "Return the next handler marked context, returning nil if there is none. Search starts with self and proceeds up to nil."
- | ctx |
- <primitive: 197>
- | ctx known | ctx := self.
- known := IdentitySet new. [ctx isHandlerContext ifTrue:[^ctx].
(known ifAbsentAdd: ctx) ifFalse: [Processor debugWithTitle:
'Loop on stack detected!' translated full: false]. (ctx := ctx sender) == nil ] whileFalse. ^nil
So my questions to you are: Do we want to support this kind of safety (I would like it!)? Is this possible to implement in the VM without a concerning performance impact?
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
Hi Jaromir,
ad loops on the context stack: Marcel convinced me that the VM would rather not be responsible of working with a corrupted stack but the image (i.e., privSender:/generators/...) should take care of not invalidating the stack. So, if you feel like working on this, great, but this would most likely just mean to add some checks to Generator and/or write an InverseGenerator/Consumer ... :)
Will try to answer on your other question in the other thread soon: https://lists.squeakfoundation.org/archives/list/squeak-dev@lists.squeakfoun...
Best, Christoph
--- Sent from Squeak Inbox Talk
On 2023-12-06T22:49:14+00:00, mail@jaromir.net wrote:
Hi Christoph,
looking for a new way to crash the image? :-) Here is one:
Highlighted on my todo list :)
In the meantime here's a VM crasher I came across while studying a bug in #return:from:
Process new return: nil value: nil.
It generates an infinite stream of debuggers. I can't figure out what is going on but it has something to do with the recursion in #effectiveProcess (when I removed the recursion the infinite debuggers stream and VM crash was gone).
The crash is irrecoverable and I'm only able to capture the notifier window before killing the process. The system seems so confused it managed to send a non-integer to #priority :) (And that points to #effectiveProcess)
I'm just curious... I remember you worked on infinite debugger chains. Any explanation very welcome. Best, Jaromir
On 28-Nov-23 7:58:38 PM, christoph.thiede(a)student.hpi.uni-potsdam.de wrote:
Hi all,
looking for a new way to crash the image? :-) Here is one:
gen:=Generatoron:[:gen| selfassert:gennextisNil. selferror]. genyield:1.
This is a less idiomatic but more comprehensible version:
[c:=thisContext. [h:=thisContext. [hswapSender:thisContextsender. c:=thisContextswapSender:c]value. thisContextswapSender:c]value]value. [c:=thisContextswapSender:c. selferror]value.
In a nutshell, the Generator temporarily creates a loop on the stack while switching coroutines. I didn't fully get behind its implementation at the moment, and I acknowledge that I am using the generator in the "wrong" way - usually the #on: block is the producer not the consumer. However, and especially with the recent debate on safe languages in mind, I wonder whether we would be able and willing to make Squeak safe against this phenomen (loops on the stack).
The actual crash (or better: hang) comes from primitiveFindHandlerContext, but I assume primitiveFindNextUnwindContext and primitiveTerminateTo would cause a similar effect. A simple fix would be to disable these optional primitives and use the image fallback instead. This makes the method interruptable similar to a convenient infinite loop. However, this is obviously much slower. I wonder whether these primitives could be made aware of possible context stack loops and fail when a loop is detected. When the primitive fails, the fallback code would run so the image would be interruptable again, or even better, we could also detect particular stack loops then:
Context>>findNextHandlerContextStarting "Return the next handler marked context, returning nil if there is none. Search starts with self and proceeds up to nil."
- | ctx |
- <primitive: 197>
- | ctx known | ctx := self.
- known := IdentitySet new. [ctx isHandlerContext ifTrue:[^ctx].
(known ifAbsentAdd: ctx) ifFalse: [Processor debugWithTitle:
'Loop on stack detected!' translated full: false]. (ctx := ctx sender) == nil ] whileFalse. ^nil
So my questions to you are: Do we want to support this kind of safety (I would like it!)? Is this possible to implement in the VM without a concerning performance impact?
Best, Christoph
Sent from Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk
squeak-dev@lists.squeakfoundation.org