Skip to content

Data Race on actor.Future #1145

@GetSource1234

Description

@GetSource1234

A data race has been detected by the Go race detector involving the actor.Future object. The race occurs when one goroutine blocks on future.Result() while another goroutine writes to the same Future by calling ctx.Respond().

To Reproduce

  • create two actors A and B
  • actor A send request future : ctx.RequestFuture(actorBPID, ProtoMsg, 4*time.Second).Result()
  • actor B respond to actor A future message : ctx.Respond(ptotoMsg)

Expected behavior
The data race is caused by an unsafe concurrent memory access pattern. The actor blocks on future.Result(), waiting for a value, while the another actor writes to that same Future to fulfill it. This direct read/write access to the shared Future object is not synchronized, violating the core message-passing principles of the actor model.

Environment
Mac Pro M3, go 1.24, one node with Consul as provider

Additional context

==================
WARNING: DATA RACE
Write at 0x00c000f9a4a0 by goroutine 20745:
  github.com/asynkron/protoactor-go/actor.(*futureProcess).SendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/future.go:161 +0x18c
  github.com/asynkron/protoactor-go/actor.(*PID).sendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/pid.go:49 +0x54
  github.com/asynkron/protoactor-go/actor.(*actorContext).sendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:304 +0x1a0
  github.com/asynkron/protoactor-go/actor.(*actorContext).Send()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:297 +0xe8
  github.com/asynkron/protoactor-go/actor.(*actorContext).Respond()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:193 +0xdc
  game/actor.(*ActorA).Receive()
      /default/game/actor/ActorA.go:626 +0x3198
  github.com/asynkron/protoactor-go/actor.(*actorContext).defaultReceive()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:372 +0x118
  github.com/asynkron/protoactor-go/actor.(*actorContext).Receive()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:345 +0x78
  github.com/asynkron/protoactor-go/actor.(*Props).Clone.WithReceiverMiddleware.func6.1()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/props_opts.go:57 +0x40
  github.com/asynkron/protoactor-go/cluster.NewKind.withClusterReceiveMiddleware.func1.1()
      /go/pkg/mod/github.com/asynkron/[email protected]/cluster/config.go:99 +0xd4
  github.com/asynkron/protoactor-go/actor.(*actorContext).processMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:515 +0x388
  github.com/asynkron/protoactor-go/actor.(*actorContext).InvokeUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:505 +0x404
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).run()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:169 +0x278
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).processMessages()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:105 +0x28
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).processMessages-fm()
      <autogenerated>:1 +0x34

Previous read at 0x00c000f9a4a0 by goroutine 20728:
  github.com/asynkron/protoactor-go/actor.(*Future).Result()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/future.go:125 +0x1064
  game/actor.(*ActorB).Receive()
      /default/game/actor/actorB.go:159 +0x1050
  github.com/asynkron/protoactor-go/actor.(*actorContext).defaultReceive()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:372 +0x118
  github.com/asynkron/protoactor-go/actor.(*actorContext).Receive()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:345 +0x78
  github.com/asynkron/protoactor-go/actor.(*Props).Clone.WithReceiverMiddleware.func6.1()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/props_opts.go:57 +0x40
  github.com/asynkron/protoactor-go/cluster.NewKind.withClusterReceiveMiddleware.func1.1()
      /go/pkg/mod/github.com/asynkron/[email protected]/cluster/config.go:99 +0xd4
  github.com/asynkron/protoactor-go/actor.(*actorContext).processMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:515 +0x388
  github.com/asynkron/protoactor-go/actor.(*actorContext).InvokeUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:505 +0x404
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).run()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:169 +0x278
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).processMessages()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:105 +0x28
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).processMessages-fm()
      <autogenerated>:1 +0x34

Goroutine 20745 (running) created at:
  github.com/asynkron/protoactor-go/actor.goroutineDispatcher.Schedule()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/dispatcher.go:13 +0x28
  github.com/asynkron/protoactor-go/actor.(*goroutineDispatcher).Schedule()
      <autogenerated>:1 +0x48
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).schedule()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:99 +0xc0
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).PostUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:80 +0x21c
  github.com/asynkron/protoactor-go/actor.(*ActorProcess).SendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_process.go:21 +0x54
  github.com/asynkron/protoactor-go/actor.(*PID).sendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/pid.go:49 +0x54
  github.com/asynkron/protoactor-go/actor.(*actorContext).sendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:304 +0x1a0
  github.com/asynkron/protoactor-go/actor.(*actorContext).RequestFuture()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:334 +0x138
  game/actor.(*ActorB).Receive()
      /default/game/actor/actorB.go:155 +0x1048
  github.com/asynkron/protoactor-go/actor.(*actorContext).defaultReceive()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:372 +0x118
  github.com/asynkron/protoactor-go/actor.(*actorContext).Receive()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:345 +0x78
  github.com/asynkron/protoactor-go/actor.(*Props).Clone.WithReceiverMiddleware.func6.1()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/props_opts.go:57 +0x40
  github.com/asynkron/protoactor-go/cluster.NewKind.withClusterReceiveMiddleware.func1.1()
      /go/pkg/mod/github.com/asynkron/[email protected]/cluster/config.go:99 +0xd4
  github.com/asynkron/protoactor-go/actor.(*actorContext).processMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:515 +0x388
  github.com/asynkron/protoactor-go/actor.(*actorContext).InvokeUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_context.go:505 +0x404
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).run()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:169 +0x278
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).processMessages()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:105 +0x28
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).processMessages-fm()
      <autogenerated>:1 +0x34

Goroutine 20728 (finished) created at:
  github.com/asynkron/protoactor-go/actor.goroutineDispatcher.Schedule()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/dispatcher.go:13 +0x28
  github.com/asynkron/protoactor-go/actor.(*goroutineDispatcher).Schedule()
      <autogenerated>:1 +0x48
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).schedule()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:99 +0xc0
  github.com/asynkron/protoactor-go/actor.(*defaultMailbox).PostUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/mailbox.go:80 +0x21c
  github.com/asynkron/protoactor-go/actor.(*ActorProcess).SendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/actor_process.go:21 +0x54
  github.com/asynkron/protoactor-go/actor.(*PID).sendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/pid.go:49 +0x54
  github.com/asynkron/protoactor-go/actor.(*RootContext).sendUserMessage()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/root_context.go:148 +0x164
  github.com/asynkron/protoactor-go/actor.(*RootContext).RequestFuture()
      /go/pkg/mod/github.com/asynkron/[email protected]/actor/root_context.go:137 +0x134 
==================

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions