<p></p>
<br>
<br>
> On Nov 29, 2021, at 7:44 AM, Tony Garnock-Jones ***@***.***> wrote:<br>
> <br>
> <br>
> To reproduce<br>
> <br>
> Open a fresh Squeak trunk image<br>
> doIt:<br>
> FileStream stdin close.<br>
> Smalltalk snapshot: true andQuit: true.<br>
> Expected<br>
> <br>
> Image saves and quits.<br>
> <br>
> Actual<br>
> <br>
> Image fails to save, opens an error window with message Failed to write image file (disk full?).<br>
> <br>
> Analysis<br>
> <br>
> writeImageFileIO calls sqImageFileOpen.<br>
> sqImageFileOpen in platforms/unix/vm/sqImageFileAccess.h never observably fails to its caller - it calls exit if open(2) fails<br>
> 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.<br>
> If it does this, writeImageFileIO gets confused, because if the result of sqImageFileOpen is equal to null, it considers this a failure.<br>
> 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.<br>
> <br>
<br>
Well sqImageFile can be what ever the implementor deems best for a particular platform.  Using FILE * is a convenient but slow default.  What’s missing in the abstraction is an operator that determines what an invalid sqImageFile is.  Assuming NULL is always invalid is the bug.  We need an sqImageFileIsInvalid(sif) operator that is defined as sif < 0 when using unix file descriptors.  This should be an easy fix.<br>
> <br>
> Appendix (not very useful): Full bug report from debugger<br>
> <br>
> 29 November 2021 4:32:57.802885 pm<br>
> <br>
> VM: unix - Smalltalk<br>
> Image: Squeak6.0alpha [latest update: #20751]<br>
> <br>
> SecurityManager state:<br>
> Restricted: false<br>
> FileAccess: true<br>
> SocketAccess: true<br>
> Working Dir /tmp/squeaker-run-g38g7lcb<br>
> Trusted Dir /tmp/squeaker-run-g38g7lcb/secure<br>
> Untrusted Dir /tmp/squeaker-run-g38g7lcb/My Squeak<br>
> <br>
> SmalltalkImage(Object)>>error:<br>
> Receiver: Smalltalk<br>
> Arguments and temporary variables:<br>
> aString: 'Failed to write image file (disk full?)'<br>
> Receiver's instance variables:<br>
> globals: Smalltalk<br>
> <br>
> SmalltalkImage>>snapshot:andQuit:withExitCode:embedded:<br>
> Receiver: Smalltalk<br>
> Arguments and temporary variables:<br>
> save: true<br>
> quit: true<br>
> exitCode: nil<br>
> embeddedFlag: false<br>
> resuming: nil<br>
> msg: '----QUIT----{29 November 2021 . 4:32:05 pm} squeak.image priorSource: 20637916...etc...<br>
> Receiver's instance variables:<br>
> globals: Smalltalk<br>
> <br>
> SmalltalkImage>>snapshot:andQuit:embedded:<br>
> Receiver: Smalltalk<br>
> Arguments and temporary variables:<br>
> save: true<br>
> quit: true<br>
> embeddedFlag: false<br>
> Receiver's instance variables:<br>
> globals: Smalltalk<br>
> <br>
> SmalltalkImage>>snapshot:andQuit:<br>
> Receiver: Smalltalk<br>
> Arguments and temporary variables:<br>
> save: true<br>
> quit: true<br>
> Receiver's instance variables:<br>
> globals: Smalltalk<br>
> <br>
> UndefinedObject>>DoIt<br>
> Receiver: nil<br>
> Arguments and temporary variables:<br>
> <br>
> Receiver's instance variables: <br>
> nil<br>
> <br>
> Compiler>>evaluateCue:ifFail:<br>
> Receiver: a Compiler<br>
> Arguments and temporary variables:<br>
> aCue: a CompilationCue<br>
> failBlock: [closure] in Compiler>>evaluateCue:ifFail:logged:<br>
> methodNode: DoIt<br>
> ^ Smalltalk snapshot: true andQuit: true<br>
> method: (UndefinedObject>>#DoIt "a CompiledMethod(1015626)")<br>
> value: nil<br>
> Receiver's instance variables:<br>
> parser: a Parser<br>
> cue: a CompilationCue<br>
> <br>
> Compiler>>evaluateCue:ifFail:logged:<br>
> Receiver: a Compiler<br>
> Arguments and temporary variables:<br>
> aCue: a CompilationCue<br>
> failBlock: [closure] in [] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:...etc...<br>
> logFlag: true<br>
> value: nil<br>
> Receiver's instance variables:<br>
> parser: a Parser<br>
> cue: a CompilationCue<br>
> <br>
> Compiler>>evaluate:in:to:environment:notifying:ifFail:logged:<br>
> Receiver: a Compiler<br>
> Arguments and temporary variables:<br>
> textOrStream: a ReadStream<br>
> aContext: nil<br>
> receiver: nil<br>
> anEnvironment: Smalltalk<br>
> aRequestor: a SmalltalkEditor<br>
> failBlock: [closure] in [] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:...etc...<br>
> logFlag: true<br>
> Receiver's instance variables:<br>
> parser: a Parser<br>
> cue: a CompilationCue<br>
> <br>
> [] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> aBlock: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelection<br>
> result: nil<br>
> rcvr: nil<br>
> ctxt: nil<br>
> Receiver's instance variables:<br>
> morph: a TextMorphForEditView(2236073)<br>
> model: a Workspace<br>
> paragraph: a NewParagraph<br>
> markBlock: a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
> pointBlock: a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> FullBlockClosure(BlockClosure)>>on:do:<br>
> Receiver: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:<br>
> Arguments and temporary variables:<br>
> exceptionOrExceptionSet: OutOfScopeNotification<br>
> handlerAction: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:...etc...<br>
> handlerActive: true<br>
> handlerRearmed: false<br>
> Receiver's instance variables:<br>
> outerContext: SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:<br>
> startpcOrMethod: ([] in TextEditor>>#evaluateSelectionAndDo: "a CompiledBlock(1...etc...<br>
> numArgs: 0<br>
> receiver: a SmalltalkEditor<br>
> <br>
> SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> aBlock: [closure] in SmalltalkEditor(TextEditor)>>evaluateSelection<br>
> result: nil<br>
> rcvr: nil<br>
> ctxt: nil<br>
> Receiver's instance variables:<br>
> morph: a TextMorphForEditView(2236073)<br>
> model: a Workspace<br>
> paragraph: a NewParagraph<br>
> markBlock: a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
> pointBlock: a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> SmalltalkEditor(TextEditor)>>evaluateSelection<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> <br>
> Receiver's instance variables: <br>
>    morph:  a TextMorphForEditView(2236073)<br>
>    model:  a Workspace<br>
>    paragraph:      a NewParagraph<br>
>    markBlock:      a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
>    pointBlock:     a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> SmalltalkEditor(TextEditor)>>doIt<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> <br>
> Receiver's instance variables: <br>
>    morph:  a TextMorphForEditView(2236073)<br>
>    model:  a Workspace<br>
>    paragraph:      a NewParagraph<br>
>    markBlock:      a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
>    pointBlock:     a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> SmalltalkEditor(TextEditor)>>doIt:<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> aKeyboardEvent: ***@***.*** keystroke '' (100) 12807]<br>
> Receiver's instance variables:<br>
> morph: a TextMorphForEditView(2236073)<br>
> model: a Workspace<br>
> paragraph: a NewParagraph<br>
> markBlock: a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
> pointBlock: a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> SmalltalkEditor(TextEditor)>>dispatchOnKeyboardEvent:<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> aKeyboardEvent: ***@***.*** keystroke '' (100) 12807]<br>
> honorCommandKeys: true<br>
> typedChar: $d<br>
> Receiver's instance variables:<br>
> morph: a TextMorphForEditView(2236073)<br>
> model: a Workspace<br>
> paragraph: a NewParagraph<br>
> markBlock: a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
> pointBlock: a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> SmalltalkEditor(TextEditor)>>keyStroke:<br>
> Receiver: a SmalltalkEditor<br>
> Arguments and temporary variables:<br>
> anEvent: ***@***.*** keystroke '' (100) 12807]<br>
> Receiver's instance variables:<br>
> morph: a TextMorphForEditView(2236073)<br>
> model: a Workspace<br>
> paragraph: a NewParagraph<br>
> markBlock: a CharacterBlock with index 1 and character $F and rectangle ***@***.*** cor...etc...<br>
> pointBlock: a CharacterBlock with index 62 and rectangle ***@***.*** corner: ***@***.***<br>
> ...etc...<br>
> beginTypeInIndex: nil<br>
> emphasisHere: #()<br>
> lastParenLocation: nil<br>
> otherInterval: (49 to: 56)<br>
> oldInterval: nil<br>
> typeAhead: a WriteStream<br>
> history: a TextEditorCommandHistory<br>
> <br>
> [] in [] in TextMorphForEditView(TextMorph)>>keyStroke:<br>
> Receiver: a TextMorphForEditView(2236073)<br>
> Arguments and temporary variables:<br>
> evt: ***@***.*** keystroke '' (100) 12807]<br>
> action: nil<br>
> Receiver's instance variables:<br>
> bounds: ***@***.*** corner: ***@***.***<br>
> owner: a TransformMorph(3867971)<br>
> submorphs: #()<br>
> fullBounds: ***@***.*** corner: ***@***.***<br>
> color: Color black<br>
> extension: a MorphExtension (3908410) [other: (unfocusedSelectionColor -> (Col...etc...<br>
> borderWidth: 0<br>
> borderColor: Color black<br>
> textStyle: a TextStyle Bitmap DejaVu Sans 9<br>
> text: a Text for 'FileStream stdin close<br>
> Smalltalk snapshot: true andQuit: true...etc...<br>
> wrapFlag: true<br>
> paragraph: a NewParagraph<br>
> editor: a SmalltalkEditor<br>
> container: nil<br>
> predecessor: nil<br>
> successor: nil<br>
> backgroundColor: nil<br>
> margins: ***@***.*** corner: ***@***.***<br>
> readOnly: false<br>
> autoFit: true<br>
> editView: a PluggableTextMorphPlus(2181400)<br>
> acceptOnCR: false<br>
> <br>
> TextMorphForEditView(TextMorph)>>handleInteraction:fromEvent:<br>
> Receiver: a TextMorphForEditView(2236073)<br>
> Arguments and temporary variables:<br>
> interactionBlock: [closure] in [] in TextMorphForEditView(TextMorph)>>keyStroke:...etc...<br>
> evt: ***@***.*** keystroke '' (100) 12807]<br>
> oldEditor: a SmalltalkEditor<br>
> oldParagraph: a NewParagraph<br>
> oldText: a Text for 'FileStream stdin close<br>
> Smalltalk save: true andQuit: true'...etc...<br>
> oldSelection: ***@***.*** corner: ***@***.***}<br>
> Receiver's instance variables:<br>
> bounds: ***@***.*** corner: ***@***.***<br>
> owner: a TransformMorph(3867971)<br>
> submorphs: #()<br>
> fullBounds: ***@***.*** corner: ***@***.***<br>
> color: Color black<br>
> extension: a MorphExtension (3908410) [other: (unfocusedSelectionColor -> (Col...etc...<br>
> borderWidth: 0<br>
> borderColor: Color black<br>
> textStyle: a TextStyle Bitmap DejaVu Sans 9<br>
> text: a Text for 'FileStream stdin close<br>
> Smalltalk snapshot: true andQuit: true...etc...<br>
> wrapFlag: true<br>
> paragraph: a NewParagraph<br>
> editor: a SmalltalkEditor<br>
> container: nil<br>
> predecessor: nil<br>
> successor: nil<br>
> backgroundColor: nil<br>
> margins: ***@***.*** corner: ***@***.***<br>
> readOnly: false<br>
> autoFit: true<br>
> editView: a PluggableTextMorphPlus(2181400)<br>
> acceptOnCR: false<br>
> <br>
> TextMorphForEditView>>handleInteraction:fromEvent:<br>
> Receiver: a TextMorphForEditView(2236073)<br>
> Arguments and temporary variables:<br>
> interActionBlock: [closure] in [] in TextMorphForEditView(TextMorph)>>keyStroke:...etc...<br>
> evt: ***@***.*** keystroke '' (100) 12807]<br>
> Receiver's instance variables:<br>
> bounds: ***@***.*** corner: ***@***.***<br>
> owner: a TransformMorph(3867971)<br>
> submorphs: #()<br>
> fullBounds: ***@***.*** corner: ***@***.***<br>
> color: Color black<br>
> extension: a MorphExtension (3908410) [other: (unfocusedSelectionColor -> (Col...etc...<br>
> borderWidth: 0<br>
> borderColor: Color black<br>
> textStyle: a TextStyle Bitmap DejaVu Sans 9<br>
> text: a Text for 'FileStream stdin close<br>
> Smalltalk snapshot: true andQuit: true...etc...<br>
> wrapFlag: true<br>
> paragraph: a NewParagraph<br>
> editor: a SmalltalkEditor<br>
> container: nil<br>
> predecessor: nil<br>
> successor: nil<br>
> backgroundColor: nil<br>
> margins: ***@***.*** corner: ***@***.***<br>
> readOnly: false<br>
> autoFit: true<br>
> editView: a PluggableTextMorphPlus(2181400)<br>
> acceptOnCR: false<br>
> <br>
> --- The full stack ---<br>
> SmalltalkImage(Object)>>error:<br>
> SmalltalkImage>>snapshot:andQuit:withExitCode:embedded:<br>
> SmalltalkImage>>snapshot:andQuit:embedded:<br>
> SmalltalkImage>>snapshot:andQuit:<br>
> UndefinedObject>>DoIt<br>
> Compiler>>evaluateCue:ifFail:<br>
> Compiler>>evaluateCue:ifFail:logged:<br>
> Compiler>>evaluate:in:to:environment:notifying:ifFail:logged:<br>
> [] in SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:<br>
> FullBlockClosure(BlockClosure)>>on:do:<br>
> SmalltalkEditor(TextEditor)>>evaluateSelectionAndDo:<br>
> SmalltalkEditor(TextEditor)>>evaluateSelection<br>
> SmalltalkEditor(TextEditor)>>doIt<br>
> SmalltalkEditor(TextEditor)>>doIt:<br>
> SmalltalkEditor(TextEditor)>>dispatchOnKeyboardEvent:<br>
> SmalltalkEditor(TextEditor)>>keyStroke:<br>
> [] in [] in TextMorphForEditView(TextMorph)>>keyStroke:<br>
> TextMorphForEditView(TextMorph)>>handleInteraction:fromEvent:<br>
> TextMorphForEditView>>handleInteraction:fromEvent:<br>
> <br>
> [] in TextMorphForEditView(TextMorph)>>keyStroke:<br>
> StandardToolSet class>>codeCompletionAround:textMorph:keyStroke:<br>
> ToolSet class>>codeCompletionAround:textMorph:keyStroke:<br>
> TextMorphForEditView(TextMorph)>>keyStroke:<br>
> TextMorphForEditView>>keyStroke:<br>
> TextMorphForEditView(Morph)>>handleKeystroke:<br>
> TextMorphForEditView(TextMorph)>>handleKeystroke:<br>
> KeyboardEvent>>sentTo:<br>
> TextMorphForEditView(Morph)>>handleEvent:<br>
> TextMorphForEditView(Morph)>>handleFocusEvent:<br>
> MorphicEventDispatcher>>doHandlingForFocusEvent:with:<br>
> MorphicEventDispatcher>>dispatchFocusEvent:with:<br>
> TextMorphForEditView(Morph)>>processFocusEvent:using:<br>
> TextMorphForEditView(Morph)>>processFocusEvent:<br>
> [] in [] in [] in HandMorph>>sendFocusEvent:to:clear:<br>
> [] in ActiveEventVariable class(DynamicVariable class)>>value:during:<br>
> FullBlockClosure(BlockClosure)>>ensure:<br>
> ActiveEventVariable class(DynamicVariable class)>>value:during:<br>
> [] in ActiveEventVariable class>>value:during:<br>
> FullBlockClosure(BlockClosure)>>ensure:<br>
> ActiveEventVariable class>>value:during:<br>
> KeyboardEvent(MorphicEvent)>>becomeActiveDuring:<br>
> [] in [] in HandMorph>>sendFocusEvent:to:clear:<br>
> [] in ActiveHandVariable class(DynamicVariable class)>>value:during:<br>
> FullBlockClosure(BlockClosure)>>ensure:<br>
> ActiveHandVariable class(DynamicVariable class)>>value:during:<br>
> [] in ActiveHandVariable class>>value:during:<br>
> FullBlockClosure(BlockClosure)>>ensure:<br>
> ActiveHandVariable class>>value:during:<br>
> HandMorph>>becomeActiveDuring:<br>
> [] in HandMorph>>sendFocusEvent:to:clear:<br>
> [] in ActiveWorldVariable class(DynamicVariable class)>>value:during:<br>
> FullBlockClosure(BlockClosure)>>ensure:<br>
> ActiveWorldVariable class(DynamicVariable class)>>value:during:<br>
> [] in ActiveWorldVariable class>>value:during:<br>
> FullBlockClosure(BlockClosure)>>ensure:<br>
> ActiveWorldVariable class>>value:during:<br>
> PasteUpMorph>>becomeActiveDuring:<br>
> HandMorph>>sendFocusEvent:to:clear:<br>
> HandMorph>>sendEvent:focus:clear:<br>
> HandMorph>>sendKeyboardEvent:<br>
> HandMorph>>handleEvent:<br>
> -- and more not shown --<br>
> <br>
> —<br>
> You are receiving this because you are subscribed to this thread.<br>
> Reply to this email directly, view it on GitHub, or unsubscribe.<br>
> Triage notifications on the go with GitHub Mobile for iOS or Android. <br>


<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br />You are receiving this because you are subscribed to this thread.<br />Reply to this email directly, <a href="https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/607#issuecomment-982785604">view it on GitHub</a>, or <a href="https://github.com/notifications/unsubscribe-auth/AIJPEW4TBAF5HYXABXJ6BTDUOTZS7ANCNFSM5I7OLL3Q">unsubscribe</a>.<br />Triage notifications on the go with GitHub Mobile for <a href="https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675">iOS</a> or <a href="https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub">Android</a>.
<img src="https://github.com/notifications/beacon/AIJPEWY2BMFQS6YBPHO2DFLUOTZS7A5CNFSM5I7OLL32YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOHKKB4RA.gif" height="1" width="1" alt="" /></p>
<script type="application/ld+json">[
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ViewAction",
"target": "https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/607#issuecomment-982785604",
"url": "https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/607#issuecomment-982785604",
"name": "View Issue"
},
"description": "View this Issue on GitHub",
"publisher": {
"@type": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]</script>