Potential bug relating to something calling PDriver?
Rick Murray (539) 13750 posts |
For the little test program that I wrote to see what flags OS_File 255 returned for a non-existant file (see other thread), running it in a TaskWindow gave a massively wide memory dump – not so good for a forum post. So I went to the command line and tried to *Spool it to a file. Instead of the expected error, I got this:
It works fine when printing to screen. It fails when spooling. From the command line, no less, so it’s nothing to do with TaskWindow. I’m just wondering if anybody else is seeing something like this? |
Jeffrey Lee (213) 6048 posts |
It’s not a bug, it’s a “feature”. The error will almost certainly be stored in one of the shared error blocks that MessageTrans uses when it translates errors. Those error blocks can get overwritten pretty quickly if you continue to call SWIs after receiving the error. Solution: make your own copy of the error block (on the stack, or into a pre-allocated buffer) before calling any other SWIs. |
Rick Murray (539) 13750 posts |
Hmm… I’ve tracked it down to some code that runs as a callback. It checks to see if there’s a current printer job, to not do what it does if there’s an active job. Side effect, SWI not known messes up the error block. I wonder if I could pick up the user mode CPSR to see if V is set? (and check SPSR for the same reason?) |
Jeffrey Lee (213) 6048 posts |
That’s not really possible (the values will be buried in different places in the stack, depending on OS version). Also, it shouldn’t be necessary. When a SWI returns an error to user mode with IRQs enabled, and the error block looks like it’s in writable memory (i.e. it’s located below ROM), the kernel will temporarily block callbacks from being triggered in order to avoid callback-based code overwriting the error blocks (CBack_Postpone flag). That callback block will be removed on the next SWI that returns to user mode with IRQs enabled – which should be enough time for any code which cares about the error to have interrogated the error block. Flaw: Because the second SWI will clear the flag, if that second SWI is also returning an error then that block won’t be protected. I guess a workaround would be to call a dummy SWI like OS_IntOn to force the flag to be cleared before you call the second SWI. |
Rick Murray (539) 13750 posts |
Yup, one of the “features” of RISC OS. ;-)
Clever. Revised program:
Does this:
So there’s the answer. ;-) The problem here is probably the OSCLI command, which will call XOS_CLI to do its bidding. I wonder if there might be some value in – if the SWI returns with V set – having BASIC immediately copy the error block into its own workspace and fiddle R0 to point to that instead? Then whatever else goes on in the system won’t mess up the error message that the user can retrieve from their own code. |
Rick Murray (539) 13750 posts |
No, it looks like most of the SWI calls in BASIC are non-X form, and ChangeEnvironment sets up a centralised error handler to deal with them. |
Jeffrey Lee (213) 6048 posts |
Maybe, yeah. That’s essentially what C does if you use |