Previous: Message Receive, Up: Messaging Interface
The mach_msg
call handles port rights in a message header
atomically. Port rights and out-of-line memory in a message body do not
enjoy this atomicity guarantee. The message body may be processed
front-to-back, back-to-front, first out-of-line memory then port rights,
in some random order, or even atomically.
For example, consider sending a message with the destination port
specified as MACH_MSG_TYPE_MOVE_SEND
and the reply port specified
as MACH_MSG_TYPE_COPY_SEND
. The same send right, with one
user-reference, is supplied for both the msgh_remote_port
and
msgh_local_port
fields. Because mach_msg
processes the
message header atomically, this succeeds. If msgh_remote_port
were processed before msgh_local_port
, then mach_msg
would
return MACH_SEND_INVALID_REPLY
in this situation.
On the other hand, suppose the destination and reply port are both
specified as MACH_MSG_TYPE_MOVE_SEND
, and again the same send
right with one user-reference is supplied for both. Now the send
operation fails, but because it processes the header atomically,
mach_msg can return either MACH_SEND_INVALID_DEST
or
MACH_SEND_INVALID_REPLY
.
For example, consider receiving a message at the same time another
thread is deallocating the destination receive right. Suppose the reply
port field carries a send right for the destination port. If the
deallocation happens before the dequeuing, then the receiver gets
MACH_RCV_PORT_DIED
. If the deallocation happens after the
receive, then the msgh_local_port
and the msgh_remote_port
fields both specify the same right, which becomes a dead name when the
receive right is deallocated. If the deallocation happens between the
dequeue and the receive, then the msgh_local_port
and
msgh_remote_port
fields both specify MACH_PORT_DEAD
.
Because the header is processed atomically, it is not possible for just
one of the two fields to hold MACH_PORT_DEAD
.
The MACH_RCV_NOTIFY
option provides a more likely example.
Suppose a message carrying a send-once right reply port is received with
MACH_RCV_NOTIFY
at the same time the reply port is destroyed. If
the reply port is destroyed first, then msgh_remote_port
specifies MACH_PORT_DEAD
and the kernel does not generate a
dead-name notification. If the reply port is destroyed after it is
received, then msgh_remote_port
specifies a dead name for which
the kernel generates a dead-name notification. It is not possible to
receive the reply port right and have it turn into a dead name before
the dead-name notification is requested; as part of the message header
the reply port is received atomically.