On Mon, 27 Oct 2025 08:24:41 GMT, Florian Weimer <[email protected]> wrote:
>> We (you and me, @fweimer-rh) discussed this a couple of years ago: >> https://mail.openjdk.org/pipermail/hotspot-dev/2023-December/082324.html >> >> Quoting from here: >> https://mail.openjdk.org/pipermail/hotspot-dev/2023-December/083142.html >> >> " >> Empirically, a recursive initialization attempt doesn't make any attempt to >> throw. Rather, it blocks forever waiting for a futex signal from a thread >> that >> succeeds in the initialization. Which of course will never come. >> >> And that makes sense, now that I've looked at the code. >> >> In __cxa_guard_acquire, with _GLIBCXX_USE_FUTEX, if the guard indicates >> initialization hasn't yet been completed, then it goes into a while loop. >> This while loop tries to claim initialization. Failing that, it checks >> whether initialization is complete. Failing that, it does a SYS_futex >> syscall, waiting for some other thread to perform the initialization. >> There's >> nothing there to check for recursion. >> >> throw_recursive_init_exception is only called if single-threaded (either by >> configuration or at runtime). >> " >> >> It doesn't look like there have been any relevant changes in that area since >> then. So I think there is still not a problem here. > > @kimbarrett Sorry, I forgot about the old thread. You can get the exception > in a single-threaded scenario, something like this: > > > struct S { > S() { > static S s; > *this = s; > } > } global; > > > Maybe the actual rule is more like this? > >> Functions that may throw exceptions must not be used, unless individual >> calls ensure that these particular invocations cannot throw exceptions. Recursively entering a block-scoped static is undefined behavior. That some configurations of glibc might throw an exception in that situation (even despite the caller being compiled with exceptions disabled) seems like a mistake in glibc, and not really our concern. Our code should avoid such a situation because it's UB, regardless of whether the actual behavior involves exceptions or nasal demons. The exception only gets thrown when the application is single-threaded. But at least the common way to start java (via the launcher) is already multi-threaded on entry to Threads::create_vm(). So that case doesn't normally apply to us anyway. Also, I really don't think we want people trying to figure out whether a particular call might or might not throw (neither when writing nor when reading code). So no, I don't think the proposed rule should be changed. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27601#discussion_r2483178071
