Service call to skip specific files on CLOSE#0
Rick Murray (539) 13840 posts |
On my system:
File handle 255 is the FAT partition. I’m not sure why it’s opened read/write (with outstanding data (the ‘!’ marker)) when I’ve not accessed it, but it is always this way at boot. A long-standing issue is that *CLOSE or CLOSE#0 (OS_Find close with handle of zero) will cause all file handles to be discarded as the files are closed. Would it not be logical to include a ServiceCall to allow things that don’t want their file handle discarded to object to this closure? For example, my MIDI module (a file for input data, a file for output data), and anything else that uses files in a similar manner. The problem here is that while one can sit on FindV to spot opening and closing of files, this is not the case if the file handle is zero. We could trap FindV to prevent CLOSE#0 from working at all, but currently there’s no way to object to individual file closures. The work happens in castle.Sources.FileSys.FileSwitch.s.OSFind. The This is where we should stick in the ServiceCall to allow modules to veto file closures. This is because the There should be no caveats regarding file handles lingering during shutdown because:
Thoughts? |
Martin Avison (27) 1494 posts |
Is there any justification for allowing *CLOSE or CLOSE#0 to work? |
Rick Murray (539) 13840 posts |
<shrug> I don’t think I’ve really had a legitimate use since FileStore issues on a BBC Micro (left lingering handles). Used it a few times out of laziness on old ARM but since the A5000 and big programs that crunch data (Usenet, Fidonet, etc) it’s just not been a great idea… |
Chris Mahoney (1684) 2165 posts |
CLOSE#0 is listed under “Window managed programs – Instructions to avoid” in the BASIC Reference Manual :) It’s also noted that “you should not use the CLOSE#0 form within programs”, although it goes on to say that it can be used for debugging. |
Martin Avison (27) 1494 posts |
I am currently testing a small module StopClose0 which traps *CLOSE and CLOSE#0, and asks the user to Allow or Fail it. I am just debating if it needs to disable itself when Service_Shutdown is received. Seems to work without problems so far here … anyone interested PM me. |
Colin Ferris (399) 1814 posts |
Have the feeling that this problem came up in the ‘Risc User’ Mag – and perhaps a module was produced – but can’t find it. Does your module help if a ‘C’ or ‘ARM’ program does a global CLOSE? The point here is one faulty prog can say – close a SparkFS ZIP file :-( Just one example !TaskUsage !RunImage -: Doesn’t seem to do check O% for zero – before calling CLOSE #O% Seems like several progs – that do this :-( |
Martin Avison (27) 1494 posts |
Yes.
I think you will find that it does – after the OPEN and before the BPUT & CLOSE |
Rick Murray (539) 13840 posts |
I have one on my machine, sits on FindV and just swallows attempts to CLOSE#0. I didn’t mention it before as I’m not sure which machine it is on. |
Jeffrey Lee (213) 6048 posts |
CLOSE#0 does seem to be a bit of a foolish thing for BASIC to support. I expect that the number of legitimate users is small enough that BASIC could be changed to ignore CLOSE#0 without any significant repercussions (if BASIC programs really want to close all files, they can just change to SYS “OS_Find”). Some way of protecting DeviceFS from *Close is certainly desirable, although I’m not sure what the best method would be. It may well depend on the intent behind the *Close operation (am I a portable device that’s about to run out of battery and wants to flush all pending writes to disc? Is the disc/device about to be ejected? Or has the device already been ejected and I’m having to deal with it? Is the OS shutting down? etc.) Previous thread: https://www.riscosopen.org/forum/forums/4/topics/1271 |
Dave Higton (1515) 3525 posts |
I agree. I would support such a proposal. I can’t imagine any legitimate use for CLOSE#0. Here’s an example of code that I use to avoid an accidental CLOSE#0: DEF PROCclose_file(RETURN file%) LOCAL ERROR ON ERROR LOCAL file% = 0 IF file% <> 0 THEN CLOSE#file% file% = 0 ENDIF ENDPROC which only works if a call to PROCclose_file is the only way you close a file. |
Martin Avison (27) 1494 posts |
To try and identify any cases where Close All (OS_Find,0,0) is used legitimately, and possibly some illegitimate uses, my module is now available. It prompts the user to allow the operation – if not it errors the action. I will add it to my website soon, but PM me if you would like to try it. It is in use here from boot. This should help identify if Close All can be stopped at a lower level than BASIC, which is only part of the problem. |
Rick Murray (539) 13840 posts |
Hence my service call suggestion. Things talking via DeviceFS are probably modules (or back end via modules as is the case of things like SerialUSB) so could remember file handles and veto a close. I’d agree that BASIC should be prevented from doing CLOSE#0. That, with the ServiceCall veto, ought to cover most cases without nuking the “close all files” concept completely.
You don’t need to worry about that. You should see DeviceDead long before anything bothers you about closing files. It’s worth noting that there are two very different types of file handle in question. One is a traditional “handle” that to relates to an actual file. These need to be sorted out when the machine shuts down. |
Steve Drain (222) 1620 posts |
Well … ;-) Basalt ignores
Or *Close or even *Shut.
I think if you use the SWI directly you can avoid the error:
|
Rick Murray (539) 13840 posts |
What’s the difference? Wasn’t one supposed to do it per FS and one globally… or was that Arthur/RO2? |
Andrew Conroy (370) 740 posts |
*h. close |
Timothy Baldwin (184) 242 posts |
I suggest making CLOSE#0 close all files opened with OPENIN, OPENOUT and OPENUP in the same instance of BASIC, thereby restoring the pre-RISC OS behaviour, which only effected the current program because there was only one program, which was actually useful. |
Rick Murray (539) 13840 posts |
Is this not the programmer’s responsibility? The use of CLOSE#0 was partly laziness (stuck? just close everything!) and partly because error handling in older BASIC wasn’t as advanced.
It’s not right to compare a non multitasking system with scant resources that hardly ever kept files open with a multitasking system where not only are resources frequently held open (FontManager) but devices can be associated with file handles and these held open too. If we are going to suggest restoring behaviour from the early eighties, would you agree to petition Jeffrey to modify GraphicsV to permit only MODES 0 to 7? Imagine what MODE 2 would look like on a 28" display! ;-) |
Chris Hall (132) 3554 posts |
A long-standing issue is that *CLOSE or CLOSE#0 (OS_Find close with handle of zero) will cause all file handles to be discarded as the files are closed. It is only all file handles on the current filing system. If *CLOSE is trying to close all files on all filing systems then that is a serious bug in RISC OS. It will (should) therefore discriminate (in your example) between SDFS, devices and resources. The command to close all files on all filing systems is *SHUT. I use *CLOSE during debugging if I have a multi-tasking BASIC application running that logs various things and it falls over and has to be killed. BASIC (or the Wimp) is not clever enough to close all files that an application has opened when it is killed. I avoid shut because of the side effects on streams and things, network for example. |
Steve Drain (222) 1620 posts |
That might be useful, once BASIC keeps a list of open files a la Basalt. I would look at |
Chris Hall (132) 3554 posts |
That might be useful, once BASIC keeps a list of open files a la Basalt. I would look at CLOSE LIST as a more suitable syntax. Yes. CLOSE#0 should throw an error. (If you really want to do CLOSE#0 use *CLOSE.) |
Alan Adams (2486) 1149 posts |
If CLOSE#0 does close all files on the fcurrent filing system, then would making the current filing system RAMFS solve most of the problems? |
Chris Hall (132) 3554 posts |
The most often error is the following;
so trapping the command CLOSE#variable when variable is zero would be sufficient. As the intention was to close a file on SDFS (that, in fact, had already been closed) changing filing systems won’t help. |
Alan Adams (2486) 1149 posts |
I don’t see why not. CLOSE# is using a file handle, not the name. You can close a file on SDFS while the default filesystem is set to RAMFS. It just means that if the handle happens top be 0, then the files closed are those open on RAMFS, and these are likely to be less important. (How on earth do you quote on this system? The textfile reference is useless.) |
Chris Hall (132) 3554 posts |
Yes, I see what you mean but I sometimes use RAMFS to test an application. I also rely on the CSD, especially during testing (and so does the rom compilation process). |
Matthew Phillips (473) 721 posts |
You type “bq.” and a space at the start of the paragraph. There is a hint in the formatting help just under the Reply box. If you want to quote several paragraphs you can just put the HTML blockquote tag round them. |