Skip to content

Commit bb83358

Browse files
authored
Fix some race conditions when running very fast tasks (#108)
1 parent 522de5e commit bb83358

6 files changed

Lines changed: 29 additions & 20 deletions

File tree

pkg/agent/report_status_plugin.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// you may not use this file except in compliance with the License.
55
// You may obtain a copy of the License at
66
//
7-
// http://www.apache.org/licenses/LICENSE-2.0
7+
// http://www.apache.org/licenses/LICENSE-2.0
88
//
99
// Unless required by applicable law or agreed to in writing, software
1010
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -39,22 +39,28 @@ func NewReportStatusPlugin(sshdPlugin any) *ReportStatusPlugin {
3939

4040
func (p *ReportStatusPlugin) Run(ctx context.Context) error {
4141
sshd := ctx.Value(p.sshdPlugin).(*SSHD)
42+
send := func() {
43+
addr := sshd.listener.Addr()
44+
port := addr.(*net.TCPAddr).Port
45+
sandboxConnection := agentd.SandboxConnection{
46+
Port: port,
47+
HostKey: sshd.HostPublicKey.Marshal(),
48+
}
49+
err := gob.NewEncoder(os.Stdout).Encode(sandboxConnection)
50+
log.Printf("Sent sandbox connection info")
51+
if err != nil {
52+
log.Fatal("Failed to encode sandbox connection:", err)
53+
}
54+
}
55+
// Handle future CHECK_POINT recovers.
4256
go func() {
4357
for {
44-
addr := sshd.listener.Addr()
45-
port := addr.(*net.TCPAddr).Port
46-
sandboxConnection := agentd.SandboxConnection{
47-
Port: port,
48-
HostKey: sshd.HostPublicKey.Marshal(),
49-
}
50-
err := gob.NewEncoder(os.Stdout).Encode(sandboxConnection)
51-
if err != nil {
52-
log.Fatal("Failed to encode sandbox connection:", err)
53-
}
5458
sig := make(chan os.Signal, 1)
5559
signal.Notify(sig, syscall.SIGCONT)
5660
<-sig
61+
send()
5762
}
5863
}()
64+
send()
5965
return p.RunNext(ctx)
6066
}

pkg/agent/sshd.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ func (s *SSHD) Start() (net.Addr, error) {
144144
}
145145

146146
s.listener = listener
147-
go s.waiter.Run()
148147
go func() {
149148
for {
150149
conn, err := listener.Accept()

pkg/agent/wait.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// you may not use this file except in compliance with the License.
55
// You may obtain a copy of the License at
66
//
7-
// http://www.apache.org/licenses/LICENSE-2.0
7+
// http://www.apache.org/licenses/LICENSE-2.0
88
//
99
// Unless required by applicable law or agreed to in writing, software
1010
// distributed under the License is distributed on an "AS IS" BASIS,

pkg/broker/agent.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ func (a *Agent) Run(
283283
response.SessionRequest = req.Request
284284
if err := stream.Send(response); err != nil {
285285
log.Printf("Failed to send session request %s to agent %s", req.Request.SessionId, a.id)
286+
a.delegate.RevokeAccessToAgent(stream.Context(), a, req)
287+
delete(a.mySessions, req.Key())
288+
// If this error happens, the stream will likely be broken. Not registering back.
286289
req.agentResponse <- AgentSessionResponse{
287290
Error: err,
288291
}
@@ -314,7 +317,7 @@ func (a *Agent) RequestKill(ctx context.Context, instanceId int64, sessionId str
314317
func (a *Agent) handleSessionUpdate(ctx context.Context, resp *proto.AgentUpdateRequest) error {
315318
// TODO: Handle multi-error.
316319
if resp.SessionInitResponse != nil {
317-
if err := a.handleSessionInitResponse(resp.SessionInitResponse); err != nil {
320+
if err := a.handleSessionInitResponse(ctx, resp.SessionInitResponse); err != nil {
318321
return err
319322
}
320323
}
@@ -326,7 +329,7 @@ func (a *Agent) handleSessionUpdate(ctx context.Context, resp *proto.AgentUpdate
326329
return nil
327330
}
328331

329-
func (a *Agent) handleSessionInitResponse(resp *proto.SessionInitResponse) error {
332+
func (a *Agent) handleSessionInitResponse(ctx context.Context, resp *proto.SessionInitResponse) error {
330333
sessionKey := SessionKey{
331334
InstanceId: resp.InstanceId,
332335
SessionId: resp.SessionId,
@@ -342,6 +345,7 @@ func (a *Agent) handleSessionInitResponse(resp *proto.SessionInitResponse) error
342345
Error: fmt.Errorf("%w: %s", ErrorFailedToStartSession, a.id),
343346
}
344347
session.Complete(proto.SessionExecutionFinalState_SESSION_EXECUTION_FINAL_STATE_STARTUP_FAILURE)
348+
a.delegate.RevokeAccessToAgent(ctx, a, session)
345349
a.scheduler.AddAgent(a)
346350
a.scheduler.PoolManager.MarkIdle(a.id, a.slots-len(a.mySessions))
347351
a.receiving = true

pkg/broker/broker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (s *server) AgentUpdate(stream proto.BrokerService_AgentUpdateServer) error
9393
}
9494
update := func(sess *Session) error {
9595
agent.mySessions[key] = sess
96-
agent.handleSessionInitResponse(session.Response)
96+
agent.handleSessionInitResponse(stream.Context(), session.Response)
9797
sess.Reconnect()
9898
return nil
9999
}

pkg/tasks/task_service.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ func (s *TaskServiceServer) WatchTask(in *proto.GetTaskRequest, stream proto.Tas
205205
if err != nil {
206206
return err
207207
}
208-
if isTaskStatusFinal(task.Status) {
208+
if IsTaskStatusFinal(task.Status) {
209209
return nil
210210
}
211211

@@ -224,15 +224,15 @@ func (s *TaskServiceServer) WatchTask(in *proto.GetTaskRequest, stream proto.Tas
224224
// Client cancel
225225
return ctx.Err()
226226
case status := <-statusChan:
227-
if (isTaskStatusFinal(status) || status == proto.TaskStatus_TASK_STATUS_RUNNING_SUBTASKS) && sendErr != nil && leased {
227+
if (IsTaskStatusFinal(status) || status == proto.TaskStatus_TASK_STATUS_RUNNING_SUBTASKS) && sendErr != nil && leased {
228228
// Task execution finished, stop watching live status, ensure updates are processed.
229229
err := <-sendErr
230230
if err != nil && !errors.Is(err, io.EOF) {
231231
return err
232232
}
233233
sendErr = nil
234234
}
235-
if isTaskStatusFinal(status) {
235+
if IsTaskStatusFinal(status) {
236236
// Get full task from db
237237
task, err := s.db.GetTask(ctx, in.TaskId)
238238
if err != nil {
@@ -348,6 +348,6 @@ func (s *TaskServiceServer) patchTaskStatus(ctx context.Context, tasks ...*proto
348348
return nil
349349
}
350350

351-
func isTaskStatusFinal(status proto.TaskStatus) bool {
351+
func IsTaskStatusFinal(status proto.TaskStatus) bool {
352352
return status == proto.TaskStatus_TASK_STATUS_SUCCESS || status == proto.TaskStatus_TASK_STATUS_FAILURE || status == proto.TaskStatus_TASK_STATUS_CANCELLED || status == proto.TaskStatus_TASK_STATUS_FAILED_UPSTREAM
353353
}

0 commit comments

Comments
 (0)