mach port notifications
-
Hi,
I'm trying to use mach ports on OSX as a signaling mechanism between
unrelated tasks. In particular, I'm using the mach ports to detect when
a task terminates. I've been able to do this successfully on OS X
Server 1.2 as follows. I have two tasks, A and B, where A is to monitor
task B for task termination. Task B creates and registers a mach port
using the name server port:
port_name_t machport;
ret = port_allocate(task_self(), &machport);
ret = netname_check_in(name_server_port, "foo",
task_self(), machport);
Task A creates a mach port to receive notifications and sets it as the
notify port for the task:
port_name_t nport;
ret = port_allocate(task_self(), &nport);
task_set_special_port(task_self(), TASK_NOTIFY_PORT, nport);
Then, task A acquires the port made available by task B and waits for a
notification message:
notification_t notify;
notify.notify_header.msg_local_port = nport;
notify.notify_header.msg_size = sizeof(notification_t);
ret = msg_receive(¬ify.header, MSG_OPTION_NONE, 0);
if ( (NOTIFY_PORT_DELETED == notify.notify_header.msg_id) ||
(NOTIFY_PORT_DESTROYED ==
notify.notify_header.msg_id) )
{
fprintf(stderr, "Received port notif.\n");
}
However, I have not been able to port this to OS X. I did find a
posting on Omnigroup's mailing list that said that you should use the
bootstrap_port instead of name_server_port. I modified accordingly by
using the bootstrap functions so that I can register and acquire a mach
port. But I haven't been able to figure out how to get notifications
about the port being deleted or destroyed. Any help is greatly
appreciated.
Thanks,
Rob Aulwes -
Check out mach_port_request_notification().
Mach 3.0 has a much more flexible notification mechanism than Mach 2.5.
So, instead of having a single notification port where all notifications
for that task are directed, individual notifications can be sent to any
port of your choosing. The change was made because certain
notifications (like no-more-sender notifications) must be sent to
particular ports (in the no-more-senders case, to the same port they are
about) in order to be interpreted correctly in multi-threaded servers.
One other change is that the notifications carry references to the port
name/rights in question. Again, this change is for multi-threaded
safety, but it means that the rights identified in the notification
message must be released as well.
In your specific case, the notification you are looking to request is a
"dead-name" (MACH_NOTIFY_DEAD_NAME) notification. That notification
means that you (Task A) continues to hold a send right to a port whose
receiver (Task B) went away. You get an extra send right to the (now
dead) port when this message is delivered.
Other notifications you can request include:
no-more-sender notifications (MACH_NOTIFY_NO_SENDERS). This allows a
receive right holder to get notified when the last send right to a port
goes away. This notification message does not carry and
rights/references to the port in question.
port-destroyed notifications (MACH_NOTIFY_PORT_DESTROYED). These are
trickier. Basically, they are ways of saying "this port is very
special" if anything ever tries to destroy the receive right for this
port, send it back to me instead. This notification message carries the
receive right for the port in question.
In addition to the successful delivery of dead-name, port-destroyed, and
no-more-senders notifications, the notification subsystem may deliver
one of the following notification messages:
port-deleted notification messages. Some other logic in your task
deleted the name that you had an outstanding notification request
against. Essentially, this is the notification mechanism's way of
informing you that the notification request is being cancelled. You
don't request these notifications explicitly, they come as a response to
other notifications. This notification does not carry any
rights/references for the port in question.
send-once notification messages. In Mach 3.0, there is the concept of a
send-once right. It gives the right to send only one (and exactly one)
message to a port. It is used extensively by MIG for RPC reply port
rights. If the sender deallocates the send-once right before using it
(explicitly, or through unexpected termination), the IPC system will
send a send-once notification to the target port in lieu of an actual
message from the client. It makes error recovery from
"never-going-to-complete" RPCs much simpler. This notification does not
carry any rights/references for the target port.
Hope this helps some,
--Jim
On Friday, September 21, 2001, at 01:46 PM, Rob Aulwes wrote:> Task A creates a mach port to receive notifications and sets it as the
> notify port for the task:
>
> port_name_t nport;
>
> ret = port_allocate(task_self(), &nport);
> task_set_special_port(task_self(), TASK_NOTIFY_PORT, nport);
>
> Then, task A acquires the port made available by task B and waits for a
> notification message:
>
> notification_t notify;
>
> notify.notify_header.msg_local_port = nport;
> notify.notify_header.msg_size = sizeof(notification_t);
> ret = msg_receive(¬ify.header, MSG_OPTION_NONE, 0);
> if ( (NOTIFY_PORT_DELETED == notify.notify_header.msg_id) ||
> (NOTIFY_PORT_DESTROYED ==
> notify.notify_header.msg_id) )
> {
> fprintf(stderr, "Received port notif.\n");
> }
>
>
> However, I have not been able to port this to OS X. I did find a
> posting on Omnigroup's mailing list that said that you should use the
> bootstrap_port instead of name_server_port. I modified accordingly by
> using the bootstrap functions so that I can register and acquire a mach
> port. But I haven't been able to figure out how to get notifications
> about the port being deleted or destroyed. Any help is greatly
> appreciated.
>
> Thanks,
>
> Rob Aulwes
>
> _______________________________________________
> MacOSX-dev mailing list
> <MacOSX-dev...>
> http://www.omnigroup.com/mailman/listinfo/macosx-dev
> -
Sorry for the delay, this got stuck as undeliverable and I acutally took
a weekend off.
As others have said: Check out mach_port_request_notification().
Mach 3.0 has a much more flexible notification mechanism than Mach 2.5.
So, instead of having a single notification port where all notifications
for that task are directed, individual notifications can be sent to any
port of your choosing. The change was made because certain
notifications (like no-more-sender notifications) must be sent to
particular ports (in the no-more-senders case, to the same port they are
about) in order to be interpreted correctly in multi-threaded servers.
One other change is that the notifications carry references to the port
name/rights in question. Again, this change is for multi-threaded
safety, but it means that the rights identified in the notification
message must be released as well.
In your specific case, the notification you are looking to request is a
"dead-name" (MACH_NOTIFY_DEAD_NAME) notification. That notification
means that you (Task A) continues to hold a send right to a port whose
receiver (Task B) went away. You get an extra send right to the (now
dead) port when this message is delivered (so your handler for this
notification message will likely have to release 2 send rights, the
original one you held and the one delivered in the notification).
Other notifications you can request include:
no-more-sender notifications (MACH_NOTIFY_NO_SENDERS). This allows a
receive right holder to get notified when the last send right to a port
goes away. This notification message does not carry and
rights/references to the port in question.
port-destroyed notifications (MACH_NOTIFY_PORT_DESTROYED). These are
trickier. Basically, they are ways of saying "this port is very
special" if anything ever tries to destroy the receive right for this
port, send it back to me instead. This notification message carries the
receive right for the port in question.
In addition to the successful delivery of dead-name, no-more-senders,
and port-destroyed notifications, the mach port notification subsystem
may deliver one of the following notification messages:
port-deleted notification messages. Some other logic in your task
deleted the name that you had an outstanding notification request
against. Essentially, this is the notification mechanism's way of
informing you that the notification request is being cancelled. You
don't request these notifications explicitly, they come as a response to
other notifications. This notification does not carry any
rights/references for the port in question.
send-once notification messages. In Mach 3.0, there is the concept of a
send-once right. It gives the right to send only one (and exactly one)
message to a port. It is used extensively by MIG for RPC reply port
rights. If the sender deallocates the send-once right before using it
(explicitly, or through unexpected termination), the IPC system will
send a send-once notification to the target port in lieu of an actual
message from the client. It makes error recovery from
"never-going-to-complete" RPCs much simpler. This notification does not
carry any rights/references for the target port.
Hope this helps some,
--Jim
On Friday, September 21, 2001, at 01:46 PM, Rob Aulwes wrote:> Task A creates a mach port to receive notifications and sets it as the
> notify port for the task:
>
> port_name_t nport;
>
> ret = port_allocate(task_self(), &nport);
> task_set_special_port(task_self(), TASK_NOTIFY_PORT, nport);
>
> Then, task A acquires the port made available by task B and waits for a
> notification message:
>
> notification_t notify;
>
> notify.notify_header.msg_local_port = nport;
> notify.notify_header.msg_size = sizeof(notification_t);
> ret = msg_receive(¬ify.header, MSG_OPTION_NONE, 0);
> if ( (NOTIFY_PORT_DELETED == notify.notify_header.msg_id) ||
> (NOTIFY_PORT_DESTROYED ==
> notify.notify_header.msg_id) )
> {
> fprintf(stderr, "Received port notif.\n");
> }
>
>
> However, I have not been able to port this to OS X. I did find a
> posting on Omnigroup's mailing list that said that you should use the
> bootstrap_port instead of name_server_port. I modified accordingly by
> using the bootstrap functions so that I can register and acquire a mach
> port. But I haven't been able to figure out how to get notifications
> about the port being deleted or destroyed. Any help is greatly
> appreciated.
>
> Thanks,
>
> Rob Aulwes
>
> _______________________________________________
> MacOSX-dev mailing list
> <MacOSX-dev...>
> http://www.omnigroup.com/mailman/listinfo/macosx-dev
> -
Until someone who knows what they're talking about shows up, you
might check out the 'mach_init' subproject of the system_cmds
project (in the Darwin repository). There're an alarming number of
references there to bootstrap_port.
Regards,
Justin
On Friday, September 21, 2001, at 01:46 PM, Rob Aulwes wrote:> Hi,
>
> I'm trying to use mach ports on OSX as a signaling mechanism
> between unrelated tasks. In particular, I'm using the mach ports
> to detect when a task terminates. I've been able to do this
> successfully on OS X Server 1.2 as follows. I have two tasks, A
> and B, where A is to monitor task B for task termination. Task B
> creates and registers a mach port using the name server port:
> port_name_t machport;
>
> ret = port_allocate(task_self(), &machport);
> ret = netname_check_in(name_server_port, "foo",
> task_self(), machport);
>
> Task A creates a mach port to receive notifications and sets it as
> the notify port for the task:
>
> port_name_t nport;
>
> ret = port_allocate(task_self(), &nport);
> task_set_special_port(task_self(), TASK_NOTIFY_PORT, nport);
>
> Then, task A acquires the port made available by task B and waits
> for a notification message:
>
> notification_t notify;
>
> notify.notify_header.msg_local_port = nport;
> notify.notify_header.msg_size = sizeof(notification_t);
> ret = msg_receive(¬ify.header, MSG_OPTION_NONE, 0);
> if ( (NOTIFY_PORT_DELETED == notify.notify_header.msg_id) ||
> (NOTIFY_PORT_DESTROYED ==
> notify.notify_header.msg_id) )
> {
> fprintf(stderr, "Received port notif.\n");
> }
>
>
> However, I have not been able to port this to OS X. I did find a
> posting on Omnigroup's mailing list that said that you should use
> the bootstrap_port instead of name_server_port. I modified
> accordingly by using the bootstrap functions so that I can
> register and acquire a mach port. But I haven't been able to
> figure out how to get notifications about the port being deleted
> or destroyed. Any help is greatly appreciated.
>
> Thanks,
>
> Rob Aulwes
> _______________________________________________
> darwin-development mailing list
> <darwin-development...>
> http://www.lists.apple.com/mailman/listinfo/darwin-development
---
Justin C. Walker, Curmudgeon-At-Large *
Institute for General Semantics |
Director of Technology | It's not whether you win
or lose...
Nexsi Systems Corp. | It's whether *I* win or lose.
1959 Concourse Drive |
San Jose, CA 95131 |
*--------------------------------------*-------------------------------* -
The relevant bits are in /usr/include/mach/mach/notify.h, but its
basically...
mach_port_request_notification(mach_task_self(),port_thats_gonna_die,MACH_NOTIFY_DEAD_NAME,
0,port_to_receive_notification,MACH_MSG_TYPE_MAKE_SEND_ONCE,&old_port_to_receive_notification)
;
-Ed
On Saturday, September 22, 2001, at 05:45 PM, Justin C. Walker wrote:> Until someone who knows what they're talking about shows up, you might
> check out the 'mach_init' subproject of the system_cmds project (in the
> Darwin repository). There're an alarming number of references there to
> bootstrap_port.
>
> Regards,
>
> Justin
>
> On Friday, September 21, 2001, at 01:46 PM, Rob Aulwes wrote:
>
>> Hi,
>>
>> I'm trying to use mach ports on OSX as a signaling mechanism between
>> unrelated tasks. In particular, I'm using the mach ports to detect
>> when a task terminates. I've been able to do this successfully on OS
>> X Server 1.2 as follows. I have two tasks, A and B, where A is to
>> monitor task B for task termination. Task B creates and registers a
>> mach port using the name server port:
>> port_name_t machport;
>>
>> ret = port_allocate(task_self(), &machport);
>> ret = netname_check_in(name_server_port, "foo",
>> task_self(), machport);
>>
>> Task A creates a mach port to receive notifications and sets it as the
>> notify port for the task:
>>
>> port_name_t nport;
>>
>> ret = port_allocate(task_self(), &nport);
>> task_set_special_port(task_self(), TASK_NOTIFY_PORT, nport);
>>
>> Then, task A acquires the port made available by task B and waits for
>> a notification message:
>>
>> notification_t notify;
>>
>> notify.notify_header.msg_local_port = nport;
>> notify.notify_header.msg_size = sizeof(notification_t);
>> ret = msg_receive(¬ify.header, MSG_OPTION_NONE, 0);
>> if ( (NOTIFY_PORT_DELETED == notify.notify_header.msg_id) ||
>> (NOTIFY_PORT_DESTROYED ==
>> notify.notify_header.msg_id) )
>> {
>> fprintf(stderr, "Received port notif.\n");
>> }
>>
>>
>> However, I have not been able to port this to OS X. I did find a
>> posting on Omnigroup's mailing list that said that you should use the
>> bootstrap_port instead of name_server_port. I modified accordingly by
>> using the bootstrap functions so that I can register and acquire a
>> mach port. But I haven't been able to figure out how to get
>> notifications about the port being deleted or destroyed. Any help is
>> greatly appreciated.
>>
>> Thanks,
>>
>> Rob Aulwes
>> _______________________________________________
>> darwin-development mailing list
>> <darwin-development...>
>> http://www.lists.apple.com/mailman/listinfo/darwin-development
>
> ---
> Justin C. Walker, Curmudgeon-At-Large *
> Institute for General Semantics |
> Director of Technology | It's not whether you win or
> lose...
> Nexsi Systems Corp. | It's whether *I* win or lose.
> 1959 Concourse Drive |
> San Jose, CA 95131 |
> *--------------------------------------*-------------------------------*
> _______________________________________________
> darwin-development mailing list
> <darwin-development...>
> http://www.lists.apple.com/mailman/listinfo/darwin-development -
CoreFoundation is another example of source code in Darwin which does
this. See the sources for CFMachPort.c. However, it monitors the "port
to be notified" via the run loop, so you will have to write the
mach_msg(RCV) part yourself (unless you could use CF), and of course
ignore all the things CFMachPort does that you don't need.
Chris Kane
Cocoa Frameworks, Apple
On Saturday, September 22, 2001, at 02:45 PM, Justin C. Walker wrote:> Until someone who knows what they're talking about shows up, you might
> check out the 'mach_init' subproject of the system_cmds project (in the
> Darwin repository). There're an alarming number of references there to
> bootstrap_port.
>
> Regards,
>
> Justin
>
> On Friday, September 21, 2001, at 01:46 PM, Rob Aulwes wrote:
>
>> Hi,
>>
>> I'm trying to use mach ports on OSX as a signaling mechanism between
>> unrelated tasks. In particular, I'm using the mach ports to detect
>> when a task terminates. I've been able to do this successfully on OS
>> X Server 1.2 as follows. I have two tasks, A and B, where A is to
>> monitor task B for task termination. Task B creates and registers a
>> mach port using the name server port:
>> port_name_t machport;
>>
>> ret = port_allocate(task_self(), &machport);
>> ret = netname_check_in(name_server_port, "foo",
>> task_self(), machport);
>>
>> Task A creates a mach port to receive notifications and sets it as the
>> notify port for the task:
>>
>> port_name_t nport;
>>
>> ret = port_allocate(task_self(), &nport);
>> task_set_special_port(task_self(), TASK_NOTIFY_PORT, nport);
>>
>> Then, task A acquires the port made available by task B and waits for
>> a notification message:
>>
>> notification_t notify;
>>
>> notify.notify_header.msg_local_port = nport;
>> notify.notify_header.msg_size = sizeof(notification_t);
>> ret = msg_receive(¬ify.header, MSG_OPTION_NONE, 0);
>> if ( (NOTIFY_PORT_DELETED == notify.notify_header.msg_id) ||
>> (NOTIFY_PORT_DESTROYED ==
>> notify.notify_header.msg_id) )
>> {
>> fprintf(stderr, "Received port notif.\n");
>> }
>>
>>
>> However, I have not been able to port this to OS X. I did find a
>> posting on Omnigroup's mailing list that said that you should use the
>> bootstrap_port instead of name_server_port. I modified accordingly by
>> using the bootstrap functions so that I can register and acquire a
>> mach port. But I haven't been able to figure out how to get
>> notifications about the port being deleted or destroyed. Any help is
>> greatly appreciated.
>>
>> Thanks,
>>
>> Rob Aulwes
>> _______________________________________________
>> darwin-development mailing list
>> <darwin-development...>
>> http://www.lists.apple.com/mailman/listinfo/darwin-development
>
> ---
> Justin C. Walker, Curmudgeon-At-Large *
> Institute for General Semantics |
> Director of Technology | It's not whether you win or
> lose...
> Nexsi Systems Corp. | It's whether *I* win or lose.
> 1959 Concourse Drive |
> San Jose, CA 95131 |
> *--------------------------------------*-------------------------------*
> _______________________________________________
> MacOSX-dev mailing list
> <MacOSX-dev...>
> http://www.omnigroup.com/mailman/listinfo/macosx-dev


