apache/seatunnel · warning · IOException

Interrupted while closing python source reader

Error message

Interrupted while closing python source reader

What it means

During close(), a thread that was interrupted while waiting for another close caller to finish (e.g. joining pump threads under lifecycleLock) restores its interrupt flag and throws this IOException. The library does this so the interrupt is not silently swallowed: the caller learns that close did not fully complete its waiting logic before being interrupted.

Source

Thrown at seatunnel-connectors-v2/connector-python/src/main/java/org/apache/seatunnel/connectors/seatunnel/python/source/PythonSourceReader.java:668

    }

    /** Waits without abandoning cleanup when the close thread itself is interrupted. */
    private boolean waitForLifecycleChange() {
        try {
            lifecycleLock.wait();
            return false;
        } catch (InterruptedException e) {
            return true;
        }
    }

    /** Restores an interrupt consumed while waiting for another close caller. */
    private void restoreInterrupt(boolean interrupted) throws IOException {
        if (!interrupted) {
            return;
        }
        Thread.currentThread().interrupt();
        throw new IOException("Interrupted while closing python source reader");
    }

    private IOException joinThread(Thread thread, String threadName, IOException closeException) {
        return joinThread(
                thread,
                threadName,
                closeException,
                TimeUnit.SECONDS.toMillis(PROCESS_DESTROY_TIMEOUT_SECONDS));
    }

    private IOException joinThread(
            Thread thread, String threadName, IOException closeException, long timeoutMillis) {
        return joinThread(thread, threadName, closeException, timeoutMillis, true);
    }

    private IOException joinThread(
            Thread thread,
            String threadName,

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Treat it as cancellation: re-check the interrupt status and finish cleanup, since the interrupt flag has been restored
  2. Retry close() if the underlying resources still need cleanup after handling the interrupt
  3. Avoid interrupting SeaTunnel task threads during close unless cancellation is intended
  4. Verify no watchdog/scheduler is spuriously interrupting threads during normal shutdown

Example fix

// before
sourceReader.close();
// after
try {
    sourceReader.close();
} catch (IOException e) {
    if (Thread.currentThread().isInterrupted() && e.getMessage().contains("closing python source reader")) {
        LOG.warn("close interrupted; retrying cleanup", e);
        sourceReader.close();
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    reader.close();
} catch (IOException e) {
    if (Thread.currentThread().isInterrupted()
            && e.getMessage().contains("Interrupted while closing python source reader")) {
        LOG.warn("close was interrupted; interrupt flag restored, cleanup may be incomplete");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Thread.interrupt() is delivered to a thread blocked waiting on another close caller inside close(); restoreInterrupt(boolean interrupted=true) is then called, re-interrupting the thread and throwing this IOException.

Common situations: Job cancellation or task shutdown interrupting the reader thread while it is closing; another component (e.g. engine teardown) interrupts the thread mid-close; double-close races where a second caller waits on the first.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/b0f58adb1bda24cd. Report an issue: GitHub.