[Vm-dev] [OpenSmalltalk/opensmalltalk-vm] "Failed to write image file" if stdin is closed at snapshot-and-quit time on Unix (Issue #607)
Tony Garnock-Jones
notifications at github.com
Mon Nov 29 15:44:18 UTC 2021
## To reproduce
1. Open a fresh Squeak trunk image
2. doIt:
```smalltalk
FileStream stdin close.
Smalltalk snapshot: true andQuit: true.
```
## Expected
Image saves and quits.
## Actual
Image fails to save, opens an error window with message `Failed to write image file (disk full?)`.
## Analysis
- `writeImageFileIO` calls `sqImageFileOpen`.
- `sqImageFileOpen` in `platforms/unix/vm/sqImageFileAccess.h` never observably fails to its caller - it calls `exit` if `open(2)` fails
- `sqImageFileOpen` can perfectly reasonably hand back file descriptor zero for the new image file! If `FileStream stdin` has been closed, it will in fact do so.
- If it does this, `writeImageFileIO` gets confused, because if the result of `sqImageFileOpen` is equal to `null`, it considers this a failure.
This looks annoyingly Unix-specific, a result of punning raw fds as `sqImageFile` values. Other platforms use e.g. a `FILE*` instead of a raw fd, in which case even if fd 0 were to be opened under the covers, the corresponding `FILE*` would not be `null`.
## Appendix (not very useful): Full bug report from debugger
29 November 2021 4:32:57.802885 pm
VM: unix - Smalltalk
Image: Squeak6.0alpha [latest update: #20751]
SecurityManager state:
Restricted: false
FileAccess: true
SocketAccess: true
Working Dir /tmp/squeaker-run-g38g7lcb
Trusted Dir /tmp/squeaker-run-g38g7lcb/secure
Untrusted Dir /tmp/squeaker-run-g38g7lcb/My Squeak
SmalltalkImage(Object)>>error:
Receiver: Smalltalk
Arguments and temporary variables:
aString: 'Failed to write image file (disk full?)'
Receiver's instance variables:
globals: Smalltalk
SmalltalkImage>>snapshot:andQuit:withExitCode:embedded:
Receiver: Smalltalk
Arguments and temporary variables:
save: true
quit: true
exitCode: nil
embeddedFlag: false
resuming: nil
msg: '----QUIT----{29 November 2021 . 4:32:05 pm} squeak.image priorSource: 20637916...etc...
Receiver's instance variables:
globals: Smalltalk
SmalltalkImage>>snapshot:andQuit:embedded:
Receiver: Smalltalk
Arguments and temporary variables:
save: true
quit: true
embeddedFlag: false
Receiver's instance variables:
globals: Smalltalk
SmalltalkImage>>snapshot:andQuit:
Receiver: Smalltalk
Arguments and temporary variables:
save: true
quit: true
Receiver's instance variables:
globals: Smalltalk
UndefinedObject>>DoIt
Receiver: nil
Arguments and temporary variables:
Receiver's instance variables:
nil
Compiler>>evaluateCue:ifFail:
Receiver: a Compiler
Arguments and temporary variables:
aCue: a CompilationCue
failBlock: [closure] in Compiler>>evaluateCue:ifFail:logged:
methodNode: DoIt
^ Smalltalk snapshot: true andQuit: true
method: (UndefinedObject>>#DoIt "a CompiledMethod(1015626)")
value: nil
Receiver's instance variables:
parser: a Parser
cue: a CompilationCue
Compiler>>evaluateCue:ifFail:logged:
Receiver: a Compiler
Arguments and temporary variables:
aCue: a CompilationCue
failBlock: [closure] in [] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:...etc...
logFlag: true
value: nil
Receiver's instance variables:
parser: a Parser
cue: a CompilationCue
Compiler>>evaluate:in:to:environment:notifying:ifFail:logged:
Receiver: a Compiler
Arguments and temporary variables:
textOrStream: a ReadStream
aContext: nil
receiver: nil
anEnvironment: Smalltalk
aRequestor: a SmalltalkEditor
failBlock: [closure] in [] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:...etc...
logFlag: true
Receiver's instance variables:
parser: a Parser
cue: a CompilationCue
[] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:
Receiver: a SmalltalkEditor
Arguments and temporary variables:
aBlock: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelection
result: nil
rcvr: nil
ctxt: nil
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
FullBlockClosure(BlockClosure)>>on:do:
Receiver: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:
Arguments and temporary variables:
exceptionOrExceptionSet: OutOfScopeNotification
handlerAction: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:...etc...
handlerActive: true
handlerRearmed: false
Receiver's instance variables:
outerContext: SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:
startpcOrMethod: ([] in TextEditor>>#evaluateSelectionAndDo: "a CompiledBlock(1...etc...
numArgs: 0
receiver: a SmalltalkEditor
SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:
Receiver: a SmalltalkEditor
Arguments and temporary variables:
aBlock: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelection
result: nil
rcvr: nil
ctxt: nil
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
SmalltalkEditor(TextEditor)>>evaluateSelection
Receiver: a SmalltalkEditor
Arguments and temporary variables:
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
SmalltalkEditor(TextEditor)>>doIt
Receiver: a SmalltalkEditor
Arguments and temporary variables:
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
SmalltalkEditor(TextEditor)>>doIt:
Receiver: a SmalltalkEditor
Arguments and temporary variables:
aKeyboardEvent: [140 at 92 keystroke '<Opt-Cmd-d>' (100) 12807]
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
SmalltalkEditor(TextEditor)>>dispatchOnKeyboardEvent:
Receiver: a SmalltalkEditor
Arguments and temporary variables:
aKeyboardEvent: [140 at 92 keystroke '<Opt-Cmd-d>' (100) 12807]
honorCommandKeys: true
typedChar: $d
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
SmalltalkEditor(TextEditor)>>keyStroke:
Receiver: a SmalltalkEditor
Arguments and temporary variables:
anEvent: [140 at 92 keystroke '<Opt-Cmd-d>' (100) 12807]
Receiver's instance variables:
morph: a TextMorphForEditView(2236073)
model: a Workspace
paragraph: a NewParagraph
markBlock: a CharacterBlock with index 1 and character $F and rectangle 3 at 0 cor...etc...
pointBlock: a CharacterBlock with index 62 and rectangle 235 at 16 corner: 235 at 32
...etc...
beginTypeInIndex: nil
emphasisHere: #()
lastParenLocation: nil
otherInterval: (49 to: 56)
oldInterval: nil
typeAhead: a WriteStream
history: a TextEditorCommandHistory
[] in [] in TextMorphForEditView(TextMorph)>>keyStroke:
Receiver: a TextMorphForEditView(2236073)
Arguments and temporary variables:
evt: [140 at 92 keystroke '<Opt-Cmd-d>' (100) 12807]
action: nil
Receiver's instance variables:
bounds: 0 at 0 corner: 435 at 32
owner: a TransformMorph(3867971)
submorphs: #()
fullBounds: 0 at 0 corner: 435 at 32
color: Color black
extension: a MorphExtension (3908410) [other: (unfocusedSelectionColor -> (Col...etc...
borderWidth: 0
borderColor: Color black
textStyle: a TextStyle Bitmap DejaVu Sans 9
text: a Text for 'FileStream stdin close
Smalltalk snapshot: true andQuit: true...etc...
wrapFlag: true
paragraph: a NewParagraph
editor: a SmalltalkEditor
container: nil
predecessor: nil
successor: nil
backgroundColor: nil
margins: 3 at 0 corner: 0 at 0
readOnly: false
autoFit: true
editView: a PluggableTextMorphPlus(2181400)
acceptOnCR: false
TextMorphForEditView(TextMorph)>>handleInteraction:fromEvent:
Receiver: a TextMorphForEditView(2236073)
Arguments and temporary variables:
interactionBlock: [closure] in [] in TextMorphForEditView(TextMorph)>>keyStroke:...etc...
evt: [140 at 92 keystroke '<Opt-Cmd-d>' (100) 12807]
oldEditor: a SmalltalkEditor
oldParagraph: a NewParagraph
oldText: a Text for 'FileStream stdin close
Smalltalk save: true andQuit: true'...etc...
oldSelection: {205 at 16 corner: 210 at 32}
Receiver's instance variables:
bounds: 0 at 0 corner: 435 at 32
owner: a TransformMorph(3867971)
submorphs: #()
fullBounds: 0 at 0 corner: 435 at 32
color: Color black
extension: a MorphExtension (3908410) [other: (unfocusedSelectionColor -> (Col...etc...
borderWidth: 0
borderColor: Color black
textStyle: a TextStyle Bitmap DejaVu Sans 9
text: a Text for 'FileStream stdin close
Smalltalk snapshot: true andQuit: true...etc...
wrapFlag: true
paragraph: a NewParagraph
editor: a SmalltalkEditor
container: nil
predecessor: nil
successor: nil
backgroundColor: nil
margins: 3 at 0 corner: 0 at 0
readOnly: false
autoFit: true
editView: a PluggableTextMorphPlus(2181400)
acceptOnCR: false
TextMorphForEditView>>handleInteraction:fromEvent:
Receiver: a TextMorphForEditView(2236073)
Arguments and temporary variables:
interActionBlock: [closure] in [] in TextMorphForEditView(TextMorph)>>keyStroke:...etc...
evt: [140 at 92 keystroke '<Opt-Cmd-d>' (100) 12807]
Receiver's instance variables:
bounds: 0 at 0 corner: 435 at 32
owner: a TransformMorph(3867971)
submorphs: #()
fullBounds: 0 at 0 corner: 435 at 32
color: Color black
extension: a MorphExtension (3908410) [other: (unfocusedSelectionColor -> (Col...etc...
borderWidth: 0
borderColor: Color black
textStyle: a TextStyle Bitmap DejaVu Sans 9
text: a Text for 'FileStream stdin close
Smalltalk snapshot: true andQuit: true...etc...
wrapFlag: true
paragraph: a NewParagraph
editor: a SmalltalkEditor
container: nil
predecessor: nil
successor: nil
backgroundColor: nil
margins: 3 at 0 corner: 0 at 0
readOnly: false
autoFit: true
editView: a PluggableTextMorphPlus(2181400)
acceptOnCR: false
--- The full stack ---
SmalltalkImage(Object)>>error:
SmalltalkImage>>snapshot:andQuit:withExitCode:embedded:
SmalltalkImage>>snapshot:andQuit:embedded:
SmalltalkImage>>snapshot:andQuit:
UndefinedObject>>DoIt
Compiler>>evaluateCue:ifFail:
Compiler>>evaluateCue:ifFail:logged:
Compiler>>evaluate:in:to:environment:notifying:ifFail:logged:
[] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:
FullBlockClosure(BlockClosure)>>on:do:
SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:
SmalltalkEditor(TextEditor)>>evaluateSelection
SmalltalkEditor(TextEditor)>>doIt
SmalltalkEditor(TextEditor)>>doIt:
SmalltalkEditor(TextEditor)>>dispatchOnKeyboardEvent:
SmalltalkEditor(TextEditor)>>keyStroke:
[] in [] in TextMorphForEditView(TextMorph)>>keyStroke:
TextMorphForEditView(TextMorph)>>handleInteraction:fromEvent:
TextMorphForEditView>>handleInteraction:fromEvent:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[] in TextMorphForEditView(TextMorph)>>keyStroke:
StandardToolSet class>>codeCompletionAround:textMorph:keyStroke:
ToolSet class>>codeCompletionAround:textMorph:keyStroke:
TextMorphForEditView(TextMorph)>>keyStroke:
TextMorphForEditView>>keyStroke:
TextMorphForEditView(Morph)>>handleKeystroke:
TextMorphForEditView(TextMorph)>>handleKeystroke:
KeyboardEvent>>sentTo:
TextMorphForEditView(Morph)>>handleEvent:
TextMorphForEditView(Morph)>>handleFocusEvent:
MorphicEventDispatcher>>doHandlingForFocusEvent:with:
MorphicEventDispatcher>>dispatchFocusEvent:with:
TextMorphForEditView(Morph)>>processFocusEvent:using:
TextMorphForEditView(Morph)>>processFocusEvent:
[] in [] in [] in HandMorph>>sendFocusEvent:to:clear:
[] in ActiveEventVariable class(DynamicVariable class)>>value:during:
FullBlockClosure(BlockClosure)>>ensure:
ActiveEventVariable class(DynamicVariable class)>>value:during:
[] in ActiveEventVariable class>>value:during:
FullBlockClosure(BlockClosure)>>ensure:
ActiveEventVariable class>>value:during:
KeyboardEvent(MorphicEvent)>>becomeActiveDuring:
[] in [] in HandMorph>>sendFocusEvent:to:clear:
[] in ActiveHandVariable class(DynamicVariable class)>>value:during:
FullBlockClosure(BlockClosure)>>ensure:
ActiveHandVariable class(DynamicVariable class)>>value:during:
[] in ActiveHandVariable class>>value:during:
FullBlockClosure(BlockClosure)>>ensure:
ActiveHandVariable class>>value:during:
HandMorph>>becomeActiveDuring:
[] in HandMorph>>sendFocusEvent:to:clear:
[] in ActiveWorldVariable class(DynamicVariable class)>>value:during:
FullBlockClosure(BlockClosure)>>ensure:
ActiveWorldVariable class(DynamicVariable class)>>value:during:
[] in ActiveWorldVariable class>>value:during:
FullBlockClosure(BlockClosure)>>ensure:
ActiveWorldVariable class>>value:during:
PasteUpMorph>>becomeActiveDuring:
HandMorph>>sendFocusEvent:to:clear:
HandMorph>>sendEvent:focus:clear:
HandMorph>>sendKeyboardEvent:
HandMorph>>handleEvent:
-- and more not shown --
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/607
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20211129/ed0533ef/attachment-0001.html>
More information about the Vm-dev
mailing list