Skip to content

Better typing for trapped exits and monitor messages #20

@CrowdHailer

Description

@CrowdHailer

See this Elixir forum post for my explination of typed processes up to this point.

Background

  1. An important difference between links and monitor is that an exit message can come from a Pid that it didn't know about, for example the parent process that used start_link. A monitor message will always come from a monitor the process it's self instantiated.
  2. Processes define their own mailbox message type, this means that process's sending to a mailbox must know the type. In the case of pub sub when the pubsub broker might have may types of clients connected the client should subscribe with a translate function that is used to cast the published update to an acceptable message type. I think the same principle can be applied to trapping exits and handling monitors. To set up either monitor/link the process must indicate how it will handle those messages.

Exits.

A process traps exits by providing the function that will handle the message.
Start with a process with the following message type

pub type Message {
  Foo
  Bar
  OhDear(BarePid, Dynamic)
}

The Exit type is OhDear to make clear its a type defined by the client, it would I expect normally be called exit in practice.

Option 1
process.spawn_link(fn(receive) {
  process.trap_exit(receive, fn(pid, reason) { OhDear(pid, reason) })

  // continue ...
})

Signature of trap_exit function.

fn trap_exit(fn(Wait) -> m, fn(BarePid, Reason) -> m)
  • Calling this function sets the flag in the process.
  • receive is only passed in to get the message type correct.
  • the mapping function can be stored in the process dictionary
  • this API should only be called once, which cannot be enforced except by a runtime check.
Option 2
process.spawn_link(fn(receive, trap_exit) {
  trap_exit(fn(pid, reason) { OhDear(pid, reason) })

  // continue ...
})
  • does not need receive to be passed to the trap_exit function.
  • Still needs to be called only once, cannot be enforced.
Option 3
process.spawn_link(fn(receive) {
  // continue ...
    
}, Ok(fn(pid, reason) { Exit(pid, reason) }))
  • No possibility of setting trap exit twice.
  • Increased Noise to start a process without trapping exits, need to pass an Error as configuration argument. see below
process.spawn_link(fn(receive) {
  // continue ...
    
}, Error(Nil))

Monitors

Very similar except the mapping function is passed when the monitor is created.

process.monitor(pid, fn(pid, reason) { MyDown(pid) })

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