@@ -182,24 +182,30 @@ class JMSAgent extends Agent {
182182 }
183183
184184 log. info " Processing command: " + commandAttributes
185- AgentCommandRunner runner = this . processCommand(commandAttributes) {
186- // Callback invoked when command actually gets to execute
187- acknowledgeRun(message)
188- }
189-
190185
191- if (replyToValue) {
186+ // Declare runner before the closure so the closure can capture it by reference.
187+ // The closure runs on the runner thread, which is only scheduled after processCommand
188+ // returns and runner is assigned, so runner is guaranteed to be non-null when the
189+ // closure executes.
190+ AgentCommandRunner runner
191+ runner = this . processCommand(commandAttributes) {
192+ // This onRun callback executes on the runner thread, before command.run() is called.
193+ // Reply setup (setupHookReply / setupDirectReply) MUST happen here rather than after
194+ // processCommand returns, because setupHookReply sets command.onDirectoryConfigured,
195+ // which is invoked from inside command.run(). Doing it after processCommand returns
196+ // races with the runner thread reaching that callback point.
197+ acknowledgeRun(message)
192198
193- log . info " ReplyTo set on message: will send message when complete "
194-
195- // Write out the completion listener
196- BpipeCommand command = runner . command
197- if (command instanceof RunPipelineCommand ) {
198- if (config . getOrDefault( ' replyMode ' , ' hook ' ) == ' hook ' ) {
199- setupHookReply(commandAttributes, replyToValue, command, message)
200- }
201- else {
202- setupDirectReply(commandAttributes, ( RunPipelineCommand )command, message, runner)
199+ if (replyToValue) {
200+ log . info " ReplyTo set on message: will send message when complete mode = hook "
201+ BpipeCommand cmd = runner . command
202+ if (cmd instanceof RunPipelineCommand ) {
203+ if (config . getOrDefault( ' replyMode ' , ' hook ' ) == ' hook ' ) {
204+ setupHookReply(commandAttributes, replyToValue, ( RunPipelineCommand )cmd, message)
205+ }
206+ else {
207+ setupDirectReply(commandAttributes, ( RunPipelineCommand )cmd, message, runner)
208+ }
203209 }
204210 }
205211 }
0 commit comments