diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h b/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h
index 6cfbe41592b..e5985af5eee 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h
@@ -58,7 +58,7 @@ void (*fp_pw_stream_destroy)(struct pw_stream *stream);
 
 
 void (*fp_pw_init)(int *argc, char **argv[]);
-
+void (*fp_pw_deinit)(void);
 
 struct pw_core *
 (*fp_pw_context_connect_fd)(struct pw_context *context,
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
index bb6c3b445fb..e2f4ea31d2e 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
@@ -89,12 +89,17 @@ static gboolean initScreenSpace() {
 }
 
 static void doCleanup() {
+    if (pw.loop) {
+        DEBUG_SCREENCAST("STOPPING loop\n", NULL);
+        fp_pw_thread_loop_stop(pw.loop);
+    }
+
     for (int i = 0; i < screenSpace.screenCount; ++i) {
         struct ScreenProps *screenProps = &screenSpace.screens[i];
         if (screenProps->data) {
             if (screenProps->data->stream) {
-                fp_pw_stream_disconnect(screenProps->data->stream);
                 fp_pw_thread_loop_lock(pw.loop);
+                fp_pw_stream_disconnect(screenProps->data->stream);
                 fp_pw_stream_destroy(screenProps->data->stream);
                 fp_pw_thread_loop_unlock(pw.loop);
                 screenProps->data->stream = NULL;
@@ -116,10 +121,7 @@ static void doCleanup() {
         pw.core = NULL;
     }
 
-    DEBUG_SCREENCAST("STOPPING loop\n", NULL)
-
     if (pw.loop) {
-        fp_pw_thread_loop_stop(pw.loop);
         fp_pw_thread_loop_destroy(pw.loop);
         pw.loop = NULL;
     }
@@ -130,6 +132,10 @@ static void doCleanup() {
         screenSpace.screenCount = 0;
     }
 
+    if (!sessionClosed) {
+        fp_pw_deinit();
+    }
+
     gtk->g_string_set_size(activeSessionToken, 0);
     sessionClosed = TRUE;
 }
@@ -571,6 +577,7 @@ static const struct pw_core_events coreEvents = {
  * @return TRUE on success
  */
 static gboolean doLoop(GdkRectangle requestedArea) {
+    gboolean isLoopLockTaken = FALSE;
     if (!pw.loop && !sessionClosed) {
         pw.loop = fp_pw_thread_loop_new("AWT Pipewire Thread", NULL);
 
@@ -599,6 +606,7 @@ static gboolean doLoop(GdkRectangle requestedArea) {
         }
 
         fp_pw_thread_loop_lock(pw.loop);
+        isLoopLockTaken = TRUE;
 
         pw.core = fp_pw_context_connect_fd(
                 pw.context,
@@ -639,12 +647,16 @@ static gboolean doLoop(GdkRectangle requestedArea) {
         DEBUG_SCREEN_PREFIX(screen, "@@@ screen processed %i\n", i);
     }
 
-    fp_pw_thread_loop_unlock(pw.loop);
+    if (isLoopLockTaken) {
+        fp_pw_thread_loop_unlock(pw.loop);
+    }
 
     return TRUE;
 
     fail:
-        fp_pw_thread_loop_unlock(pw.loop);
+        if (isLoopLockTaken) {
+            fp_pw_thread_loop_unlock(pw.loop);
+        }
         doCleanup();
         return FALSE;
 }
@@ -700,6 +712,7 @@ static gboolean loadSymbols() {
     LOAD_SYMBOL(fp_pw_stream_disconnect, "pw_stream_disconnect");
     LOAD_SYMBOL(fp_pw_stream_destroy, "pw_stream_destroy");
     LOAD_SYMBOL(fp_pw_init, "pw_init");
+    LOAD_SYMBOL(fp_pw_deinit, "pw_deinit");
     LOAD_SYMBOL(fp_pw_context_connect_fd, "pw_context_connect_fd");
     LOAD_SYMBOL(fp_pw_core_disconnect, "pw_core_disconnect");
     LOAD_SYMBOL(fp_pw_context_new, "pw_context_new");
@@ -855,6 +868,33 @@ static void arrayToRectangles(JNIEnv *env,
     (*env)->ReleaseIntArrayElements(env, boundsArray, body, 0);
 }
 
+static int makeScreencast(
+        const gchar *token,
+        GdkRectangle *requestedArea,
+        GdkRectangle *affectedScreenBounds,
+        gint affectedBoundsLength
+) {
+    if (!initScreencast(token, affectedScreenBounds, affectedBoundsLength)) {
+        return pw.pwFd;
+    }
+
+    if (!doLoop(*requestedArea)) {
+        return RESULT_ERROR;
+    }
+
+    while (!isAllDataReady()) {
+        fp_pw_thread_loop_lock(pw.loop);
+        fp_pw_thread_loop_wait(pw.loop);
+        fp_pw_thread_loop_unlock(pw.loop);
+        if (hasPipewireFailed) {
+            doCleanup();
+            return RESULT_ERROR;
+        }
+    }
+
+    return RESULT_OK;
+}
+
 /*
  * Class:     sun_awt_screencast_ScreencastHelper
  * Method:    closeSession
@@ -911,26 +951,22 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
             jx, jy, jwidth, jheight, token
     );
 
-    if (!initScreencast(token, affectedScreenBounds, affectedBoundsLength)) {
-        releaseToken(env, jtoken, token);
-        return pw.pwFd;
-    }
-
-    if (!doLoop(requestedArea)) {
-        releaseToken(env, jtoken, token);
-        return RESULT_ERROR;
-    }
+    int attemptResult = makeScreencast(
+        token, &requestedArea, affectedScreenBounds, affectedBoundsLength);
 
-    while (!isAllDataReady()) {
-        fp_pw_thread_loop_lock(pw.loop);
-        fp_pw_thread_loop_wait(pw.loop);
-        if (hasPipewireFailed) {
-            fp_pw_thread_loop_unlock(pw.loop);
-            doCleanup();
+    if (attemptResult) {
+        if (attemptResult == RESULT_DENIED) {
             releaseToken(env, jtoken, token);
-            return RESULT_ERROR;
+            return attemptResult;
+        }
+        DEBUG_SCREENCAST("Screencast attempt failed with %i, re-trying...\n",
+                         attemptResult);
+        attemptResult = makeScreencast(
+            token, &requestedArea, affectedScreenBounds, affectedBoundsLength);
+        if (attemptResult) {
+            releaseToken(env, jtoken, token);
+            return attemptResult;
         }
-        fp_pw_thread_loop_unlock(pw.loop);
     }
 
     DEBUG_SCREENCAST("\nall data ready\n", NULL);