Alain Achkar <js@simplytech.com> wrote:
This is a multi-part message in MIME format.
--------------020103060400030809080504
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Thanks David! This helps clarify things for me and gives me some options
to choose from. I still have some questions/remarks though:
David Gibbs wrote:
Alain Achkar <> js@simplytech.com> > wrote:
3. The docs say that name_attach() will call ChannelCreate() with
flags=0, however, it seems that the effect is that flags =
_NTO_CHF_UNBLOCK. (See attached zip file)
Where do the docs say that name_attach() will call ChannelCreate()
with flags=0? If the docs do say this, they are wrong. But, my
version of the documentation does not say any such thing. (It does say,
somewhat confusingly, that it “calls dispatch_create() and resmgr_attach()
to create a channel, however it doesn’t set any channel flags by itself.”
I will admit this description is not the clearest, and it should probably
be extended to say which channel flags are set by default by those pieces
as that information doesn’t seem to be covered.)
Sorry, my mistake. Since the docs say “to create a channel”, I made the
wrong assumption that ChannelCreate() will be called. And since “it
doesn’t set any flag”, I assumed that _NTO_CHF_UNBLOCK will be cleared.
As I said, the docs are quite confusing there – you came to a very
reasonable conclusion from what they said. I’ve issued a PR to have
better information put in there.
But, the example code also clearly shows the name_attach() server handling
_PULSE_CODE_UNBLOCK (as well as handling _PULSE_CODE_DISCONNECT, and with
comments about getting _PULSE_CODE_COIDDEATH and _PULSE_CODE_THREADDEATH)
which should be a further indications that name_attach() does set these
channel flags.
What makes this example confusing is that the _PULSE_CODE_UNBLOCK
section never gets called when the client times out (as can be
demonstrated by the attached name_attach2.c, which is the same example
with 'printf’s added). The only way to execute that section is to
modify the code (as in my previous post attachment) so that the server
goes back to the MsgReceive() while the client is REPLY-blocked and
times out. Only then will the pulse be received.
This is intentional.
You can’t receive a pulse unless you go back to the MsgReceive(). If
you take a while, the client “times out”, the unblock pulse is queued,
then without calling MsgReceive(), you unblock the client (by replying,
for example), then the unblock pulse is removed (not delivered) because
it is no longer needed – the client has already been unblocked, so
there is no longer any need to tell the server it needs to unblock the
client. (Also, delivering it could cause a race condition… e.g. if
the client is unblocked, sets it’s priority higher, then sends to the
server again. The new send would arrive ahead of the (old) unblock
pulse, the server would get the new request, then the unblock pulse,
and assume it was an unblock for the new message, not the old.)
Also, [maybe I’m doing something wrong?] name_attach() doesn’t seem to
be sending an _IO_CONNECT message, as can be seen with the printf in the
same attachment.
sigh
Do I have to talk about this one?
Ok… I’m not sure what the “proper” behaviour is at the moment.
See, it used to be that name_attach()/name_open() only worked locally
(on the same node). And no _IO_CONNECTs were sent. Then, the ability
to do global (accross networks) attachs/open was added, but to resolve
the server accross the network required a message to be sent, so an
_IO_CONNECT message was sent by name_open(). But, this broke existing
applications. So, there was an argument about not breaking existing
applications vs being consistent in the network vs local case. And
I don’t know how the argument finished. So, I don’t know what the
“right” behaviour is at the moment, or whether the docs are right or
wrong, or whether I need to PR something (again).
Probably more than you wanted to know, but there you go.
- Is there a way that I can set a TimerTimeout before a MsgSend and be
guaranteed that I will unblock if the timeout expires? It doesn’t seem
logical to me to have to wait for the server to allow the client to
unblock if the client’s timeout expires (or at least, we should have the
option to enable/disable this feature).
Choice 1: have the server properly and quickly handle the unblock
notification. See my above discussion of various race conditions
as to why I think this is a GOOD idea.
Choice 2: have the channel NOT set the UNBLOCK notification flag. This
is a bit trickier if you’re using name_attach().
So, if I don’t have control over the server (someone else wrote it - QNX
or a third party), then I’m out-of-luck ? >
Yup.
Or, at least, you HOPE they handle the unblock notification properly,
and bug them to fix any bugs you find with it.
Try:
dispatch_t *_dispatch_create( int chid, unsigned flags );
It worked! >
I looked everwhere for this funcion, but could not find it. Is it
undocumented? If so, what is the ‘flags’ parameter ?
It is not documented. I thought I said it wasn’t documented. If
not, I should have said it was undocumented.
The line:
dpp = _dispatch_create( chid, 0 );
is giving:
server.c:66: warning: assignment makes pointer from integer without a
cast.
Did you prototype it? If you didn’t, it will default to returning
an int, and when you assign it to a dispatch_t *, it will give that
warning.
Can this be safely ignored?
Better to fix it.
Currently, I think that an int and a pointer are the same on all
our platforms – but that may not always be true.
I know that readcond() was mentioned but its resolution is 1/10 of a
second, so I would still like to concentrate on the following and see if
I’m doing anything wrong in tst1.c attached. You can run it by typing:
tst1 timeout_ms
where timeout_ms is the time in milliseconds that you would like to wait
for the read() function to return. Type any characters to stop the
read() from timing out, or do not type any characters to let it time out.
If I only set:
flags = _NTO_TIMEOUT_REPLY ;
then, sometimes at random, the read() will not return.
tst1 is REPLY-blocked on devc-pty, however, devc-pty is RECEIVE-blocked!
That might be a bug. Just spent a while looking through the kernel
trying to figure out what is happening. Not sure what is happening.
If, however, I set:
flags = _NTO_TIMEOUT_REPLY | _NTO_TIMEOUT_SEND ;
then it works (times out everytime).
And, you want to set this anyway. If your time expires while
you are SEND blocked (before the server receives), you want to
timeout immediately, so probably want to include the _NTO_TIMEOUT_SEND.
(What I speculate is happening, though I’m not sure, is that the
tiemout happens while you are SEND block, you aren’t REPLY blocked
at that point, so don’t timeout, and that the expired timeout for
REPLY is not caught on the transition to REPLY.)
However, when it times out, it does not return ETIMEDOUT, it returns EINTR.
Unfortunate, but yes. I think I may have mentioned this, but the
event that the server gets does not have room to tell the server
why you need to unblock (e.g. cancel, timeout, or signal), so the
server can’t do the “right” MsgError(), and just chooses EINTR.
The documentation should probably be updated to reflect this.
-David
David Gibbs
QNX Training Services
dagibbs@qnx.com