Skip to content

Commit 3c07d3f

Browse files
committed
fix: agent hook sometimes not written due to race condition
1 parent f788472 commit 3c07d3f

1 file changed

Lines changed: 22 additions & 16 deletions

File tree

src/main/groovy/bpipe/agent/JMSAgent.groovy

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)