[Fix-18201][TaskPlugin] Fix RemoteShell task NullPointerException and…#18210
Conversation
2d7cbf9 to
b314cde
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes regressions introduced in #17800 for the RemoteShell task by avoiding ChannelExec.getInvertedOut() (which can be null before channel open completes) and by preventing MINA SSHD pipe errors when commands produce no output.
Changes:
- Rework
RemoteExecutor.runRemoteAndProcessLines()to usechannel.setOut(ByteArrayOutputStream)instead ofgetInvertedOut(). - Update
RemoteExecutorTestmocks to simulatesetOut(OutputStream)behavior and cover empty-output/non-zero-exit scenarios.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| dolphinscheduler-task-plugin/dolphinscheduler-task-remoteshell/src/main/java/org/apache/dolphinscheduler/plugin/task/remoteshell/RemoteExecutor.java | Switches RemoteShell output capture away from getInvertedOut() to avoid NPE/pipe issues; preserves line-based parsing. |
| dolphinscheduler-task-plugin/dolphinscheduler-task-remoteshell/src/test/java/org/apache/dolphinscheduler/plugin/task/remoteshell/RemoteExecutorTest.java | Adjusts unit tests to mock setOut() output delivery and updates coverage for empty output / exit status behavior. |
Comments suppressed due to low confidence (1)
dolphinscheduler-task-plugin/dolphinscheduler-task-remoteshell/src/test/java/org/apache/dolphinscheduler/plugin/task/remoteshell/RemoteExecutorTest.java:269
testTrackWithEmptyLogOutputwill spend significant time sleeping becauseRemoteExecutor.track()callsThread.sleep(TRACK_INTERVAL)when no lines are read. WithgetTaskPid()mocked to return a non-empty pid and then an empty pid, this test will hit the sleep path multiple times (making the unit test suite slow/flaky). Consider stubbingThread.sleep(e.g., via Mockito static mocking) or adjusting the test setup so the loop exits without waiting.
void testTrackWithEmptyLogOutput() throws Exception {
RemoteExecutor remoteExecutor = spy(new RemoteExecutor(sshConnectionParam));
String taskId = "1234";
ChannelExec channel = Mockito.mock(ChannelExec.class, RETURNS_DEEP_STUBS);
doReturn("9527").doReturn("").when(remoteExecutor).getTaskPid(taskId);
when(clientSession.auth().verify().isSuccess()).thenReturn(true);
when(clientSession.createExecChannel(anyString())).thenReturn(channel);
// no output → readLines=0 → sleep once, then getTaskPid returns "" → exit
when(channel.getExitStatus()).thenReturn(0);
when(channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0))
.thenReturn(EnumSet.of(ClientChannelEvent.CLOSED));
Assertions.assertDoesNotThrow(() -> remoteExecutor.track(taskId));
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… Pipe closed error Revert the channel output reading approach introduced in apache#17800 from getInvertedOut() back to setOut(ByteArrayOutputStream), which fixes two regression bugs: 1. NPE: getInvertedOut() returns null before channel.open() completes 2. Pipe closed after 0 cycles: ChannelPipedInputStream throws IOException when command produces no output
…n failure - Fix err.toString() using platform default charset, now uses UTF-8 explicitly - Reorder logic to consume stdout before checking exitStatus, so lineConsumer receives output even when command exits non-zero (improves diagnostics in UI)
28a7e1a to
63de8a1
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|


Was this PR generated or assisted by AI?
YES, assisted by Claude Sonnet 4.6 for root cause analysis and code fix.
Purpose of the pull request
close #18201
Brief change log
PR #17800 changed
runRemoteAndProcessLines()to usechannel.getInvertedOut()instead ofchannel.setOut(ByteArrayOutputStream), which introduced two regression bugs:getInvertedOut()is called beforechannel.open()completes, returns nullChannelPipedInputStreamthrows IOException when command produces no outputThis PR reverts to the
setOut(ByteArrayOutputStream)approach while keeping the line-by-line processing improvement from #17800.Verify this pull request
This pull request is already covered by existing tests, such as
RemoteExecutorTest(12 tests, all passed).Manually verified the change by testing RemoteShell task against a remote SSH server on local standalone deployment.
Pull Request Notice
Pull Request Notice
If your pull request contains incompatible change, you should also add it to
docs/docs/en/guide/upgrade/incompatible.mdVerify this pull request
This pull request is already covered by existing tests, such as
RemoteExecutorTest(12 tests, all passed).Manually verified on local standalone deployment with RemoteShell task against a remote SSH server:
Before fix:

After fix:
