<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>> <span style="white-space: pre-wrap">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.</span></p>
    <p><span style="white-space: pre-wrap">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 <i>has</i> the be on the stack (or rather, it's a local variable).</span></p>
    <p><span style="white-space: pre-wrap">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.</span></p>
    <p><span style="white-space: pre-wrap">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<i> </i>in the code <i>after</i> checking the liveness state, but <i>before</i> doing the actual access), will throw the async exception, preventing them from ever doing the actual access.</span></p>
    <p><span style="white-space: pre-wrap">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.</span></p>
    <p><span style="white-space: pre-wrap">Jorn
</span></p>
    <div class="moz-cite-prefix">On 18-6-2024 09:54, Remi Forax wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:1635633843.52889282.1718697275443.JavaMail.zimbra@univ-eiffel.fr">
      <pre class="moz-quote-pre" wrap="">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
</pre>
    </blockquote>
  </body>
</html>