{"record":{"id":"4f2cadd8b786d0e4","repo":"apache/seatunnel","slug":"python-source-stream-closer-did-not-finish-within","errorCode":null,"errorMessage":"Python source stream closer did not finish within {}ms; process stream handles may remain open until it completes or the JVM exits","messagePattern":"Python source stream closer did not finish within (.+?)ms; process stream handles may remain open until it completes or the JVM exits","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-python/src/main/java/org/apache/seatunnel/connectors/seatunnel/python/source/PythonSourceReader.java","lineNumber":791,"sourceCode":"     */\n    private static void closeProcessStreams(Process runningProcess, long timeoutMillis) {\n        Thread streamCloser =\n                new Thread(\n                        () -> {\n                            closeQuietly(runningProcess.getOutputStream());\n                            closeQuietly(runningProcess.getInputStream());\n                            closeQuietly(runningProcess.getErrorStream());\n                        },\n                        \"python-source-stream-closer\");\n        streamCloser.setDaemon(true);\n        streamCloser.start();\n        try {\n            streamCloser.join(timeoutMillis);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n        if (streamCloser.isAlive()) {\n            LOG.warn(\n                    \"Python source stream closer did not finish within {}ms; process stream\"\n                            + \" handles may remain open until it completes or the JVM exits\",\n                    timeoutMillis);\n        }\n    }\n\n    /** Stream cleanup is best effort because process termination is the authoritative boundary. */\n    private static void closeQuietly(Closeable closeable) {\n        try {\n            closeable.close();\n        } catch (IOException e) {\n            LOG.debug(\"Failed to close Python source process stream\", e);\n        }\n    }\n\n    private static boolean isAlive(Thread thread) {\n        return thread != null && thread.isAlive();\n    }","sourceCodeStart":773,"sourceCodeEnd":809,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-python/src/main/java/org/apache/seatunnel/connectors/seatunnel/python/source/PythonSourceReader.java#L773-L809","documentation":"closeProcessStreams() joins the stream-closer thread with a bounded timeout; if that thread is still alive after the join, this warning is logged. The process's stdout/stderr handles may remain open until the closer finishes or the JVM exits, risking file-descriptor leaks.","triggerScenarios":"close() -> closeProcessStreams(): streamCloser.join(timeoutMillis) returns and streamCloser.isAlive() is still true — the closer is blocked, typically on reading streams that never reach EOF because the process (or a child holding the pipe) is still running.","commonSituations":"Python process or its descendants keeping stdout/stderr pipes open after close was requested; large buffered stream output still being drained; blocked read() on a pipe nobody closes.","solutions":["Ensure the Python process and all children terminate so the pipes close and EOF is reached","Increase the close timeout to let stream draining finish","Check the script for spawned child processes inheriting stdout/stderr","If leaks accumulate, recycle the task/JVM or close handles at OS level"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { reader.close(); } catch (IOException e) { /* close failure precedence */ log.warn(\"python stream close incomplete: {}\", e.getMessage()); }","preventionTips":["Ensure script and children close stdout/stderr on exit","Avoid scripts that fork background processes inheriting pipes","Raise close timeout if scripts emit large buffered output","Watch JVM fd counts (ulimit/lsof) for leaks"],"tags":["python","fd-leak","shutdown"],"backgroundTag":"broken-pipe","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}