26.02.2014 Views

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

© 2009, <strong>QNX</strong> <strong>Software</strong> <strong>Systems</strong> GmbH & Co. KG. Pulses<br />

_NTO_CHF_SENDER_LEN<br />

The kernel delivers the client’s message size as part of the information given to<br />

the server (the srcmsglen member of the struct _msg_info structure).<br />

_NTO_CHF_REPLY_LEN<br />

The kernel delivers the client’s reply message buffer size as part of the<br />

information given to the server (the dstmsglen member of the struct<br />

_msg_info structure).<br />

_NTO_CHF_COID_DISCONNECT<br />

The kernel delivers a pulse whenever any connection owned by this process is<br />

terminated due to the channel on the other end going away.<br />

_NTO_CHF_UNBLOCK<br />

Let’s look at the _NTO_CHF_UNBLOCK flag; it has a few interesting wrinkles for<br />

both the client and the server.<br />

Normally (i.e., where the server does not specify the _NTO_CHF_UNBLOCK flag)<br />

when a client wishes to unblock from a MsgSend() (and related MsgSendv(),<br />

MsgSendvs(), etc. family of functions), the client simply unblocks. The client could<br />

wish to unblock due to receiving a signal or a kernel timeout (see the TimerTimeout()<br />

function in the <strong>Neutrino</strong> Library Reference, and the Clocks, Timers, and <strong>Getting</strong> a<br />

Kick Every So Often chapter). The unfortunate aspect to this is that the server has no<br />

idea that the client has unblocked and is no longer waiting for a reply. Note that it isn’t<br />

possible to write a reliable server <strong>with</strong> this flag off, except in very special situations<br />

which require cooperation between the server and all its clients.<br />

Let’s assume that you have a server <strong>with</strong> multiple threads, all blocked on the server’s<br />

MsgReceive() function. The client sends a message to the server, and one of the<br />

server’s threads receives it. At this point, the client is blocked, and a thread in the<br />

server is actively processing the request. Now, before the server thread has a chance to<br />

reply to the client, the client unblocks from the MsgSend() (let’s assume it was because<br />

of a signal).<br />

Remember, a server thread is still processing the request on behalf of the client. But<br />

since the client is now unblocked (the client’s MsgSend() would have returned <strong>with</strong><br />

EINTR), the client is free to send another request to the server. Thanks to the<br />

architecture of <strong>Neutrino</strong> servers, another thread would receive another message from<br />

the client, <strong>with</strong> the exact same receive ID! The server has no way to tell these two<br />

requests apart! When the first thread completes and replies to the client, it’s really<br />

replying to the second message that the client sent, not the first message (as the thread<br />

actually believes that it’s doing). So, the server’s first thread replies to the client’s<br />

second message.<br />

This is bad enough; but let’s take this one step further. Now the server’s second thread<br />

completes the request and tries to reply to the client. But since the server’s first thread<br />

already replied to the client, the client is now unblocked and the server’s second thread<br />

gets an error from its reply.<br />

April 30, 2009 Chapter 2 • Message Passing 119

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!