From 73fd8884e4e2d7e66911f13767d7b7bb184d0081 Mon Sep 17 00:00:00 2001 From: Jeffrey Lee <jlee@gitlab.riscosopen.org> Date: Sun, 10 Jun 2018 22:59:58 +0000 Subject: [PATCH] Try and avoid blocking callbacks Detail: The kernel has a 'callback postponement flag' which will be set whenever an X SWI, called from user mode, returns a pointer to an error (and the error block looks like it's in RAM). Although this flag will help prevent the error buffer from being overwritten by any errors generated by callbacks, it will also have the effect of blocking Alt-Break and CLib's Escape handler, due to them both being reliant on callbacks. Since the flag may persist for a long time, it can be dangerous to leave the OS in this state (the flag can only be cleared by a SWI call from user mode - which may never happen if the program is stuck in a bad state). So to combat this, CLib will now make some effort to try and avoid leaving the postponement flag in situations where it shouldn't be needed. File changes: - c/armsys: - Change _sys_flen to return 0 for TTY streams, since calling OS_Args for them isn't going to generate any useful result (previously it was generating an error, causing the postponement flag to be left set on entry to main()) - Be extra vigilant when entering main() to make sure the callback postponement flag isn't set, just in case other checks don't resolve it - kernel/s/k_body: - Change CopyError to attempt to clear the callback postponement flag if we suspect it's set. We've just copied the error to our own buffer, so it should be our job to worry about preventing that buffer being prematurely overwritten, not the kernel's. Admin: Tested on BB-xM 'while (1) {}' (and similar variants) now multitasks in task windows and is no longer unkillable Fixes issue reported on forums: https://www.riscosopen.org/forum/forums/4/topics/11542#posts-79767 Version 5.96. Tagged as 'RISC_OSLib-5_96' --- VersionASM | 12 ++++++------ VersionNum | 20 ++++++++++---------- c/armsys | 4 ++++ kernel/s/k_body | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/VersionASM b/VersionASM index 84b80dc..068e314 100644 --- a/VersionASM +++ b/VersionASM @@ -11,13 +11,13 @@ GBLS Module_HelpVersion GBLS Module_ComponentName GBLS Module_ComponentPath -Module_MajorVersion SETS "5.95" -Module_Version SETA 595 +Module_MajorVersion SETS "5.96" +Module_Version SETA 596 Module_MinorVersion SETS "" -Module_Date SETS "14 Apr 2018" -Module_ApplicationDate SETS "14-Apr-18" +Module_Date SETS "10 Jun 2018" +Module_ApplicationDate SETS "10-Jun-18" Module_ComponentName SETS "RISC_OSLib" Module_ComponentPath SETS "castle/RiscOS/Sources/Lib/RISC_OSLib" -Module_FullVersion SETS "5.95" -Module_HelpVersion SETS "5.95 (14 Apr 2018)" +Module_FullVersion SETS "5.96" +Module_HelpVersion SETS "5.96 (10 Jun 2018)" END diff --git a/VersionNum b/VersionNum index 73aa5b2..fa3214d 100644 --- a/VersionNum +++ b/VersionNum @@ -1,23 +1,23 @@ -/* (5.95) +/* (5.96) * * This file is automatically maintained by srccommit, do not edit manually. * Last processed by srccommit version: 1.1. * */ -#define Module_MajorVersion_CMHG 5.95 +#define Module_MajorVersion_CMHG 5.96 #define Module_MinorVersion_CMHG -#define Module_Date_CMHG 14 Apr 2018 +#define Module_Date_CMHG 10 Jun 2018 -#define Module_MajorVersion "5.95" -#define Module_Version 595 +#define Module_MajorVersion "5.96" +#define Module_Version 596 #define Module_MinorVersion "" -#define Module_Date "14 Apr 2018" +#define Module_Date "10 Jun 2018" -#define Module_ApplicationDate "14-Apr-18" +#define Module_ApplicationDate "10-Jun-18" #define Module_ComponentName "RISC_OSLib" #define Module_ComponentPath "castle/RiscOS/Sources/Lib/RISC_OSLib" -#define Module_FullVersion "5.95" -#define Module_HelpVersion "5.95 (14 Apr 2018)" -#define Module_LibraryVersionInfo "5:95" +#define Module_FullVersion "5.96" +#define Module_HelpVersion "5.96 (10 Jun 2018)" +#define Module_LibraryVersionInfo "5:96" diff --git a/c/armsys b/c/armsys index 776c0f5..4f3c6a7 100644 --- a/c/armsys +++ b/c/armsys @@ -395,6 +395,7 @@ int _sys_seek(FILEHANDLE fh, off64_t pos) off64_t _sys_flen(FILEHANDLE fh) { + if istty(fh) return 0; #if 1 /* Can't use _kernel_osargs, even for 32-bit file pointers, because it can't handle files of size 4G-2 .*/ /* Use _kernel_swi instead so that _kernel_last_oserror is set up on failure like it always was. */ @@ -866,6 +867,9 @@ no_redirection: exit(EXIT_FAILURE); } + /* Clear any callback postponement flag in the kernel - otherwise programs which execute no SWIs may be completely uninterruptible */ + _swix(OS_IntOn,0); + argv[argc] = 0; /* for ANSI spec */ exit(/* hmm, relies on lots of things, but fast! */ (argc > 0 && (*(int *)argv[0] & ~0x20202020) == *(int *)"RUN") ? diff --git a/kernel/s/k_body b/kernel/s/k_body index b56cac3..b3f0c34 100644 --- a/kernel/s/k_body +++ b/kernel/s/k_body @@ -2512,7 +2512,26 @@ CopyErrorString STRB a3, [a2], #+1 BICS a3, a3, #&1F ; replaces CMP a3, #' ' BNE %B01 ; replaces BCS %B01 + ; We're probably here because a SWI returned an error. This probably + ; also means that the kernel has set the callback postponement flag - + ; a flag designed to prevent global error buffers being clobbered by + ; callbacks. However we've just copied the error into our own private + ; buffer, so there's no need for the kernel to postpone callbacks. In + ; fact, postponing callbacks can be harmful, potentially preventing the + ; user from quitting a malfunctioning app, due to both CLib's Escape + ; handler and Alt-Break being reliant on callbacks. So if we're in user + ; mode, do a dummy SWI to clear the postponement flag. + [ {CONFIG} = 26 + TST lr, #PSRIBit+PSRPrivileged + SWIEQ XOS_IntOn + MOVS pc, lr + | + MRS a3, CPSR + TST a3, #PSR32IBit+PSR32Privileged + SWIEQ XOS_IntOn + MSR CPSR_c, a3 MOV pc, lr + ] |_kernel_getenv| ; _kernel_oserror *_kernel_getenv(const char *name, char *buffer, unsigned size); -- GitLab