3 ms·
In this specific type of Win32 API case, I can think of a way to make this safe. It would involve looking at the function pointer in QueueUserAPC and making su
by muststopmyths 2y ago
In this specific type of Win32 API case, I can think of a way to make this safe.
It would involve looking at the function pointer in QueueUserAPC and making sure the function being called doesn't mess with the stack frame being executed on.
This function will run in the context of the called thread, in that thread's stack. NOT in the calling thread.
It's a weird execution mode where you're allowed to hijack a blocked thread and run some code in its context.
Don't know enough about Rust or the like to say if that's something that could be done in the language with attributes/annotations for a function, but it seems plausible.
- LegionMammal978 2y agoNothing in C can prevent your function from being abnormally unwound through (whether it's via C++ exceptions or via C longjmp()). The only real fix is "don't use C++ exceptions unless you're 100% sure that the code in between is exception-safe (and don't use C longjmp() at all outside of controlled scenarios)".
- ryao 2y agoA better fix is to avoid passing pointers to C++ functions that can throw exceptions to C functions. This theoretically can be enforced by the compiler by requiring the C++ function pointers be marked noexcept. I filed bugs against both GCC and LLVM requesting warnings: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118263 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118263 https://github.com/llvm/llvm-project/issues/121427 https://github.com/llvm/llvm-project/issues/121427
- loeg 2y agoPerhaps simpler would be to just not unwind C++ exceptions through non-C++ stack frames and abort instead. (You'd run into these crashes at development time, debugging them would be pretty obvious, and it'd never release like this.) This might not be viable on Windows, though, where there is a lot of both C++ and legacy C code.
- charrondev 2y agoAs I understand this was recent stabilized in rust and is now the default behaviour. https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#abort-on-uncaught-panics-in-extern-c-functions https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#abort... You have to explicitly opt into unwinding like this now otherwise the program will abort.
- ryao 2y agoAnother possibility is to avoid it in the first place by not allowing C++ function pointers that are not marked noexcept to be passed to C functions. I filed bugs against both GCC and LLVM requesting warnings: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118263 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118263 https://github.com/llvm/llvm-project/issues/121427 https://github.com/llvm/llvm-project/issues/121427 If/when they are implemented, they will become errors with -Werror.
- loeg 2y agoDoesn't seem all that useful unless C++ compilers will start warning about noexcept functions calling exception-throwing functions -- they don't today: https://godbolt.org/z/4qbcbxaET https://godbolt.org/z/4qbcbxaET .
- deleted 2y ago[deleted]
- ryao 2y agoThat is supposed to be handled at runtime: > Whenever an exception is thrown and the search for a handler ([except.handle]) encounters the outermost block of a function with a non-throwing exception specification, the function std :: terminate is invoked ([except.terminate]) https://timsong-cpp.github.io/cppwp/n4950/except.spec#5 https://timsong-cpp.github.io/cppwp/n4950/except.spec#5 If it is not, then there is a bug in the C++ implementation.
- loeg 2y ago