Please review. :-)<br>
<br>
Best,<br>
Christoph<b><br>
<br>
=============== Summary ===============</b><br>
<br>
Change Set:        robust-forceChangesToDisk<br>
Date:            25 March 2022<br>
Author:            Christoph Thiede<br>
<br>
Increases the robustness of Smalltalk forceChangesToDisk. When this method is interrupted, make sure to maintain the invariant that the source file is always opened and set to the right position. In the course of this, also makes StandardFileStream>>#open:forWrite: more robust. Adds a smoke/regression test.<br>
<br>
For context: Interrupting Smalltalk forceChangesToDisk is not a fictional scenario. In combination with a slow file system access, I could reproduce this many times when running StringTest>>#testPercentEncodingJa with a too small timeout.<br>
<br>
<b>=============== Diff ===============</b><br>
<br>
<b>SmalltalkImage>>forceChangesToDisk {sources, changes log} · ct 3/25/2022 14:17 (changed)</b><br>
forceChangesToDisk<br>
    "Ensure that the changes file has been fully written to disk by closing and re-opening it. This makes the system more robust in the face of a power failure or hard-reboot."<br>
<br>
    | changesFile |<br>
    changesFile := SourceFiles at: 2.<br>
    (changesFile isKindOf: FileStream) ifTrue: [<br>
        changesFile flush.<br>
<s><font color="#0000FF">-         SecurityManager default hasFileAccess ifTrue:[<br>
-             changesFile close.<br>
-             changesFile open: changesFile name forWrite: true].<br>
-         changesFile setToEnd.<br>
-     ].<br>
</font></s><font color="#FF0000">+         SecurityManager default hasFileAccess<br>
+             ifTrue: [<br>
+                 [changesFile close.<br>
+                 changesFile open: changesFile name forWrite: true.<br>
+                 changesFile setToEnd]<br>
+                     ifCurtailed: [<br>
+                         changesFile closed ifFalse: [changesFile close].<br>
+                         changesFile open: changesFile name forWrite: true.<br>
+                         changesFile setToEnd]]<br>
+             ifFalse: [changesFile setToEnd]].<br>
</font><br>
<br>
<b>SmalltalkImageTest>>testForceChangesToDiskRobustness {tests} · ct 3/25/2022 14:23</b><br>
<font color="#FF0000">+ testForceChangesToDiskRobustness<br>
+     <timeout: 11 "seconds"><br>
+     <fatal "regression test! Unless this bug is fixed, this may damage your image."><br>
+ <br>
+     50 timesRepeat:<br>
+         [[[Smalltalk forceChangesToDisk] repeat] valueWithin: 0.1 seconds onTimeout: []].<br>
+     <br>
+     self shouldnt: [Smalltalk logChange: ('Test from {1}' format: {self})] raise: Error.</font><br>
<br>
<b>StandardFileStream>>open:forWrite: {open/close} · ct 3/25/2022 14:42 (changed)</b><br>
open: fileName forWrite: writeMode <br>
    "Open the file with the given name. If writeMode is true, allow writing, otherwise open the file in read-only mode."<br>
    "Changed to do a GC and retry before failing ar 3/21/98 17:25"<br>
<s><font color="#0000FF">-     | f |<br>
</font></s><font color="#FF0000">+     | f newFileID |<br>
</font>    f := fileName asVmPathName.<br>
<s><font color="#0000FF">- <br>
-     fileID := StandardFileStream retryWithGC:[self primOpen: f writable: writeMode] <br>
-                     until:[:id| id notNil] <br>
-                     forFileNamed: fileName.<br>
</font></s><font color="#FF0000">+     <br>
+     fileID := nil.<br>
+     fileID := [StandardFileStream<br>
+         retryWithGC:<br>
+             [newFileID := nil.<br>
+             newFileID := self primOpen: f writable: writeMode] <br>
+         until: [:id | id notNil] <br>
+         forFileNamed: fileName]<br>
+             ifCurtailed:<br>
+                 [newFileID ifNotNil: [self primClose: newFileID]].<br>
</font>    fileID ifNil: [^ nil].  "allows sender to detect failure"<br>
    name := fileName.<br>
    self register.<br>
    rwmode := writeMode.<br>
    buffer1 := String new: 1.<br>
<s><font color="#0000FF">-     self enableReadBuffering<br>
-     <br>
</font></s><font color="#FF0000">+     self enableReadBuffering.</font><br>
<br>
["robust-forceChangesToDisk.1.cs"]<br>
<br>
<font color="#808080">---<br>
</font><font color="#808080"><i>Sent from </i></font><font color="#808080"><i><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><u><font color="#808080">Squeak Inbox Talk</font></u></a></i></font><br>
["robust-forceChangesToDisk.1.cs"]