Can access closed memory segment
Jorn Vernee
jorn.vernee at oracle.com
Tue Jun 18 11:18:58 UTC 2024
> when closing the scope the VM only checks if the arena is on stack
but the memory segment can be stored in a static final.
I think you're talking about the handshake that we run when closing a
shared arena? Note that in that code we only care about a thread that is
currently in the process of accessing a memory segment, in which case
the arena /has/ the be on the stack (or rather, it's a local variable).
The way shared closure works is: 1. set the arena's liveness state to
closed. 2. submit a thread-local handshake to all threads. 2a. walk each
thread stack a maximum of 10 frames, or until we find a method marked
with @Scoped 2b. for methods marked @Scoped only, look inside the local
variables of those frames to see if we find the arena we're closing. 2c.
if we find it, install an async exception on that thread, which gets
thrown as soon as the target thread continues running. 3. free memory.
As a result: - because of the handshake, all threads will see the
updated liveness state of the shared arena that we set in (1) above. -
threads that were not accessing the arena, but try to in the future,
will see the up-to-date closed state and throw. - threads that were
accessing the arena (i.e. when they were stopped by the handshake, they
were somewhere//in the code /after/ checking the liveness state, but
/before/ doing the actual access), will throw the async exception,
preventing them from ever doing the actual access.
We have a stress test in test/jdk/java/foreign/TestHandshake.java which
has helped to catch quite a few obscure issues. If you think there's
still an issue, I suggest trying to modify that test to try to reproduce it.
Jorn
On 18-6-2024 09:54, Remi Forax wrote:
> Hello,
> I think i've found an issue in the current implementation of shared arena close(),
> when closing the scope the VM only checks if the arena is on stack but the memory segment can be stored in a static final.
>
> In the following code, i'm able to read the segment after the shared arena is closed.
>
> public class SharedArenaCloseBug {
> static final Arena SHARED = Arena.ofShared();
> static final MemorySegment SEGMENT = SHARED.allocate(16);
> static int STATE;
>
> void run() {
> for(;;) {
> if (STATE == 0) {
> var value = SEGMENT.get(ValueLayout.JAVA_BYTE, 0L);
> if (value == 42) {
> return;
> }
> }
> }
> }
>
> public static void main(String[] args) throws InterruptedException {
> var bug = new SharedArenaCloseBug();
> var thread = new Thread(bug::run);
> thread.start();
> Thread.sleep(100);
> STATE = 1;
> System.out.println("state 1");
> Thread.sleep(100);
> System.out.println("close");
> SEGMENT.set(ValueLayout.JAVA_BYTE, 0L, (byte) 42);
> SHARED.close();
> Thread.sleep(100);
> System.out.println("state 0");
> STATE = 0;
> Thread.sleep(100);
> System.out.println("join");
> thread.join();
> }
> }
>
> regards,
> Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20240618/0b28e7ad/attachment.htm>
More information about the panama-dev
mailing list