Need notification when clients die

I have a task which effectively replaces the realtime timers (aka
timer_create, timer_settime, etc). I need to know if a task which
previously had created a timer goes away so I can cleanup behind it. Will
setting PULSE_CODE_DISCONNECT on my channel effectively give me this? And
if so, how do I get back at the rcvid which I previoulsy stored from the
pulse I receive?

Regards,
Richard.

Richard Doucetwrote:
I have a task which effectively replaces the realtime timers (aka
timer_create, timer_settime, etc). I need to know if a task which
previously had created a timer goes away so I can cleanup behind it.
Will
setting PULSE_CODE_DISCONNECT on my channel effectively give me
this?

Yes. it will. You might also want to conside_PULSE_CODE_UNBLOCK (see
the helpviewer docs for ChannelCreate).

And if so, how do I get back at the rcvid which I previoulsy stored
from the pulse I receive?

Regards,
Richard.

Why do you need to ? Data that is connection specific should be
located by the connection ID not the receive ID. _PULSE_CODE_UNBLOCK
handles the case where your server is processing a request on behalf
of the client, when the client unblocks.

Richard Doucet <doucetr@aecl.ca> wrote:

I have a task which effectively replaces the realtime timers (aka
timer_create, timer_settime, etc). I need to know if a task which
previously had created a timer goes away so I can cleanup behind it. Will
setting PULSE_CODE_DISCONNECT on my channel effectively give me this?

Yes, it will.

And
if so, how do I get back at the rcvid which I previoulsy stored from the
pulse I receive?

When you receive your first message from the client, you will have to
store away both rcvid and info.scoid (server connection id) which identifies
the client. When you get the disconnect pulse, you will use the
pulse.scoid to search your list of saved info.scoid fields to match the
client that is going away.

(Also, someone else mentioned handling unblock pulses – unless you are
keeping clients blocked, you don’t need that.)

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

David Gibbs wrote:

(Also, someone else mentioned handling unblock pulses – unless you are
keeping clients blocked, you don’t need that.)

I can’t imagine a useful server that doesn’t keep at least some clients blocked (i.e. hold off replying until there is something to
reply with) then again, maybe I just have a poor imagination :slight_smile:

Actually, I suppose a server that makes extensive use of async notification (so that all MsgSends are simply to retrieve data that is
already determined) fall into the category of useful, but with no need for PULSE_UNBLOCK.

Rennie

Rennie Allen <rallen@csical.com> wrote:

David Gibbs wrote:

(Also, someone else mentioned handling unblock pulses – unless you are
keeping clients blocked, you don’t need that.)

I can’t imagine a useful server that doesn’t keep at least some clients
blocked (i.e. hold off replying until there is something to
reply with) then again, maybe I just have a poor imagination > :slight_smile:

I can.

A queueing server that support add_to_queue() and remove_from_queue(),
with add failing on queue full, and remove failing on queue empty.
(e.g. a POSIX mqueue with O_NONBLOCK set.)

From my QNX 4 days: a pci BIOS server. (The CA_PCI* BIOS calls had some
special stack restrictions make them unsuitable for use in an application
that needed a shared library or largeish stack. I wrote a server that
accepted messages, did the call, returned a result. It had no need for
unblock notification as it never returned to a Receive() call before
first Reply()ing to the client.)

/dev/null
/dev/random

A driver for an A2D convertor where “get_data” is defined as get
last data value converted.

Actually, I suppose a server that makes extensive use of async
notification (so that all MsgSends are simply to retrieve data that is
already determined) fall into the category of useful, but with no need
for PULSE_UNBLOCK.

That’s another one.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

David Gibbs wrote:

I can.

I suppose “useful” was the wrong word, perhaps “of non-trivial nature” would have been a better choice. I’ll go ahead and make
comments as if my intent were clear.

A queueing server that support add_to_queue() and remove_from_queue(),
with add failing on queue full, and remove failing on queue empty.
(e.g. a POSIX mqueue with O_NONBLOCK set.)

Ah, but the actual Posix message queue server can and does operate with O_NONBLOCK unset… You present a toy implementation of a
server as an example. I bet the real mqueue does implement PULSE_UNBLOCK.

From my QNX 4 days: a pci BIOS server. (The CA_PCI* BIOS calls had some
special stack restrictions make them unsuitable for use in an application
that needed a shared library or largeish stack. I wrote a server that
accepted messages, did the call, returned a result. It had no need for
unblock notification as it never returned to a Receive() call before
first Reply()ing to the client.)
/dev/null
/dev/random

All of the above are extremely special cases and/or “of trivial nature” (most customers will not write a server whose only purpose is
to discard the data it receives or return a random number), although, I have to admit, these examples are indeed useful in spite of
their triviality (provides further evidence that I selected the wrong word).

A driver for an A2D convertor where “get_data” is defined as get
last data value converted.

While certainly this contrived example would not need to block clients, it is not typical of an actual A/D driver, and would probably
fall into the category of a “toy implementation”.

Rennie

I’m having some problems. I use the following code to create a dispatcher
in my application:

coid = ChannelCreate( channelFlags );
itsDispatcherPtr = _dispatch_create( coid, 0 );

// Do message attach to receive messages from dispatcher
msg_attr.flags = MSG_FLAG_DEFAULT_FUNC;
msg_attr.nparts_max = 1;
msg_attr.msg_max_size = itsRcvBufferSize;

if( -1 == message_attach( itsDispatcherPtr, &msg_attr, 0, 0,
&DispatchMsgHandler, this ) )
{
COMTRACE( ERROR, ARBITRARY, “ComReactor() - ERROR, failed to
message_attach, terminating” );
exit( -1 );
}


channelFlags is set to _NTO_CHF_DISCONNECT

My code later on does a

dispatcher_handler( itsContextPtr );

to handle messages. I then startup a client connect to this application,
which I then terminate via the slay commnd (I’ve verified that the client
does connect and send me messages). My application failes to get the any
pulse when the client terminates. Did I forget anything?


“David Gibbs” <dagibbs@qnx.com> wrote in message
news:daeh9m$dc2$1@inn.qnx.com

Richard Doucet <> doucetr@aecl.ca> > wrote:
I have a task which effectively replaces the realtime timers (aka
timer_create, timer_settime, etc). I need to know if a task which
previously had created a timer goes away so I can cleanup behind it.
Will
setting PULSE_CODE_DISCONNECT on my channel effectively give me this?

Yes, it will.

And
if so, how do I get back at the rcvid which I previoulsy stored from the
pulse I receive?

When you receive your first message from the client, you will have to
store away both rcvid and info.scoid (server connection id) which
identifies
the client. When you get the disconnect pulse, you will use the
pulse.scoid to search your list of saved info.scoid fields to match the
client that is going away.

(Also, someone else mentioned handling unblock pulses – unless you are
keeping clients blocked, you don’t need that.)

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Richard Doucet wrote:

to handle messages. I then startup a client connect to this application,
which I then terminate via the slay commnd (I’ve verified that the client
does connect and send me messages). My application failes to get the any
pulse when the client terminates. Did I forget anything?

Yes, you need to use pulse_attach() in order to register a handler for pulses.

Rennie

I believe pulse_attach() is only valid if you are a resource manager; this
application is not.

I’ve tried it anyways and still no pulse…

“Rennie Allen” <rallen@csical.com> wrote in message
news:42D2F9DD.6080703@csical.com

Richard Doucet wrote:

to handle messages. I then startup a client connect to this application,
which I then terminate via the slay commnd (I’ve verified that the client
does connect and send me messages). My application failes to get the any
pulse when the client terminates. Did I forget anything?


Yes, you need to use pulse_attach() in order to register a handler for
pulses.

Rennie

Richard Doucet wrote:

I believe pulse_attach() is only valid if you are a resource manager; this
application is not.

pulse_attach is valid if you are using the dispatch layer (upon which the resmgr layer is built).

You are calling dispatch_block() are you not ?

I’ve tried it anyways and still no pulse…

If you don’t call dispatch_block(), then you won’t.

I guess I don’t understand what you are doing.

Rennie

It’s all a bit complicated, I guess.

You are right, pulse_attach() works with the dispatch layer and need not be
related to a resource manager, although this is all irrelevant, as I don’t
need to do a pulse_attach to get the pulses. When I setup the dispatcher, I
do:

msg_attr.flags = MSG_FLAG_DEFAULT_FUNC; <— Get all messages,
even pulses, which are not being handled
msg_attr.nparts_max = 1;
msg_attr.msg_max_size = itsRcvBufferSize;

if( -1 == message_attach( itsDispatcherPtr, &msg_attr, 0, 0,
&DispatchMsgHandler, this ) )


Any pulse which are not handled via a seperate pulse_attach() will be sent
to the DispatchMsgHandler function, as this is the DEFAULT function to call
when no handlers are found.

I’ve figured out what is causing the missing pulses, but not why. See
attach example. If you comment out the name_attach(), you will get the
PULSE_CODE_DISCONNECT pulse. Leave it in and you won’t. Why is this? Bug?


“Rennie Allen” <rallen@csical.com> wrote in message
news:42D3EB98.5010103@csical.com

Richard Doucet wrote:
I believe pulse_attach() is only valid if you are a resource manager;
this
application is not.

pulse_attach is valid if you are using the dispatch layer (upon which the
resmgr layer is built).

You are calling dispatch_block() are you not ?

I’ve tried it anyways and still no pulse…

If you don’t call dispatch_block(), then you won’t.

I guess I don’t understand what you are doing.

Rennie

begin 666 TestNotifications.c
M(VEN8VQU9&4@/’-T9&QI8BYH/@T*(VEN8VQU9&4@/’-T9&EO+F@^#0HC:6YC
M;‘5D92 <WES+VYE=71R:6YO+F@^#0HC:6YC;‘5D92 <‘1H<F5A9"YH/@T*
M(VEN8VQU9&4@/’-Y<R]D:7-P871C:"YH/@T*(VEN8VQU9&4@/&5R<FYO+F@^
M#0HC:6YC;‘5D92 <’)O8V5S<RYH/@T*#0ID:7-P871C:%]T("H@7V1I<W!A
M=&-H7V-R96%T92AI;G0@8VAI9"P@:6YT(&1F;&%G<RD[#0H-“FEN=”!$:7-P
M871C:$US9TAA;F1L97(@&UE<W-A9V5?8V]N=&5X=%]TB!C=’ L(&EN="!C
M;V1E+"!U;G-I9VYE9"!F;&%G<RP@=F]I9" J:&%N9&QE0T>PT*“7-T<G5C
M=”!?<‘5L<V4)G @/2 H<W1R=6-T(%]P=6QS92 J2!C=’ M/FUS9SL-"@T*
M"7-W:71C:"@@<"T^8V]D92 I#0H)>PT*“6-A<V4@7U!53%-%7T-/1$5?5$A2
M14%$1$5!5$@Z#0H)“7!R:6YT9B@@(E1H<F5A9”!D:65<;B(@3L-"@D)8G)E
M86L[#0H)8V%S92!?4%5,4T5?0T]$15]$25-#3TY.14-4.@T
"0EP<FEN=&8H
M(”)$25-#3TY.14-47&XB("D[#0H)"6)R96%K.PT*"6-A<V4@7U!53%-%7T-/
M1$5?0T])1$1%051(.@T*“0EP<FEN=&8H(”)#3TE$($1%051(7&XB("D[#0H)
M"6)R96%K.PT*“61E9F%U;'0Z#0H)“7!R:6YT9B@@(D=O=”!U;FMO=VX@<'5L
M<V5<;B(@3L-"@D)37-G4F5P;'DH(&-T<"T^<F-V:60L(# L(# L(# @3L-
M"@D)8G)E86L[#0H)?0T
"7)E='5R;B P.PT
?0T*#0IV;VED(”!F=6YC=&EO
M;B@@:6YT(’!I9"P@:6YT(&-H:60@0T>PT*“6EN= D)8V]I9#L-”@T*#0IP
M<FEN=&8H(")#3VYN96-T:6YG(‘1O(’!I9" E9"!C:&ED(“5D7&XB+”!P:60L
M(&-H:60@3L-"@EC;VED(#T@0V]N;F5C=$%T=&%C:"@@,“P@<&ED+”!C:&ED
M+"!?3E1/7U-)1$5?0TA!3DY%3"P@," I.PT
"0T*“6EF*” M,2 A/2!C;VED
M(“D-”@E[#0H)“7!R:6YT9B@@(E-E;F1I;F<N+EQN(B I.PT*“0D-”@D)37-G
M4V5N9”@@8V]I9"P@(D%L;&\B+" U+"!.54Q,+" P(“D[#0H)“0T*“0ES;&5E
M<”@@,B I.PT*+R)“4-O;FYE8W1$971A8V@H(&-O:60@3L-"@D)#0H)?0T
M"7!R:6YT9B@@(E1E<FUI;F%T:6YG+BXN7&XB(“D[#0H)97AI=”@@,” I.PT*
M?0T*#0II;G0@;6%I;BAI;G0@87)G8RP@8VAA<B J87)G=EM=2 -"GL-"B @
M(’!T:’)E861?871T<E]T( EA='1R.PT
(” @9&ES<&%T8VA?= D)“2ID<W [
M#0H@(”!D:7-P871C:%]C;VYT97AT7W0@F-T<#L-"@EM97-S86=E7V%T=’)?
M= EM<V=?871T<CL-"@EI;G0)“0D)8VAI9#L-”@EI;G0)"0D)<&ED(#T@9V5T
M<&ED
"D[#0H-@EC:&ED(#T@0VAA;FYE;$-R96%T92@@7TY43U]#2$9?1$E3
M0T].3D5#5" I.PT*#0H):68H(“TQ(#T](&-H:60@0T"7L-”@D)<’)I;G1F
M*" B17)R;W(L(&-H:60@/3T@+3%<;B(@3L-"@D)97AI="@@," I.PT"7T-
M"@T*“61S<” ](%]D:7-P871C:%]C<F5A=&4H(&-H:60L(# @3L-"@T"2\O
M($1O(&UE<W-A9V4@871T86-H(‘1O(’)E8V5I=F4@;65S<V%G97,@9G)O;2!D
M:7-P871C:&5R#0H);65M<V5T*" F;7-G7V%T=’(L(# L(’-I>F5O9B@@;7-G
M7V%T=’(@2 I.PT"6US9U]A='1R+F9L86=S(#T@35-‘7T9,04=?1$5&055,
M5%]&54Y#.PT*“6US9U]A='1R+FYP87)T<U]M87@@/2 Q.PT*“6US9U]A='1R
M+FUS9U]M87A?<VEZ92 ](#(P-#@[#0H-“B @(”!I9B@@+3$@/3T@;65S<V%G
M95]A='1A8V@H(&1S<“P@)FUS9U]A='1R+” P+” P+” F1&ES<&%T8VA-<V=(
M86YD;&5R+" P(“D@2 -“B @(”![#0H@(" @"65X:70H("TQ(“D[#0H@(” @
M?0T
"0T*“6EF*” P(”$](&1S<" I#0H)>PT*"0T*“0EI9B@@,” ]/2!F;W)K
M*"D@0T"0E[#0H)“0EF=6YC=&EO;B@@<&ED+”!C:&ED("D[#0H)“7T-”@D)
M96QS90T*"0E["0T*"0D);F%M95]A=‘1A8V@H(&1S<“P@(E1%4U0B+” P("D[
M#0H)"0T*"0D)8W1P(#T@9&ES<&%T8VA?8V]N=&5X=%]A;&QO8R@@9’-P(“D[
M#0H)“0D-”@D)(” @(’=H:6QE*" Q(“D-”@D)(" @(‘L-"@D)“0EI9B@@8W1P
M(#T@9&ES<&%T8VA?8FQO8VLH(&-T<” I("D@#0H)"0D)>PT*"0D)“0ED:7-P
M871C:%]H86YD;&5R*”!C=’ @3L-"@D)“0E]#0H)“2 @(”!]#0H)“7T-”@E]
@#0H-”@ER971U<FX@15A)5%]354-#15-3.PT
?0T*#0H
end

I think name_attach() calls resmgr_attach(), which in turn calls
message_attach() for _PULSE_CODE_DISCONNECT; so it IS being handled, and
will never make it to the default function.

Murf

Richard Doucet wrote:

It’s all a bit complicated, I guess.

You are right, pulse_attach() works with the dispatch layer and need not be
related to a resource manager, although this is all irrelevant, as I don’t
need to do a pulse_attach to get the pulses. When I setup the dispatcher, I
do:

msg_attr.flags = MSG_FLAG_DEFAULT_FUNC; <— Get all messages,
even pulses, which are not being handled
msg_attr.nparts_max = 1;
msg_attr.msg_max_size = itsRcvBufferSize;

if( -1 == message_attach( itsDispatcherPtr, &msg_attr, 0, 0,
&DispatchMsgHandler, this ) )
.
.
.

Any pulse which are not handled via a seperate pulse_attach() will be sent
to the DispatchMsgHandler function, as this is the DEFAULT function to call
when no handlers are found.

I’ve figured out what is causing the missing pulses, but not why. See
attach example. If you comment out the name_attach(), you will get the
PULSE_CODE_DISCONNECT pulse. Leave it in and you won’t. Why is this? Bug?


“Rennie Allen” <> rallen@csical.com> > wrote in message
news:> 42D3EB98.5010103@csical.com> …

Richard Doucet wrote:

I believe pulse_attach() is only valid if you are a resource manager;
this
application is not.

pulse_attach is valid if you are using the dispatch layer (upon which the
resmgr layer is built).

You are calling dispatch_block() are you not ?


I’ve tried it anyways and still no pulse…

If you don’t call dispatch_block(), then you won’t.

I guess I don’t understand what you are doing.

Rennie
\

John A. Murphy wrote:

I think name_attach() calls resmgr_attach(), which in turn calls
message_attach() for _PULSE_CODE_DISCONNECT; so it IS being handled, and
will never make it to the default function.

Yup. My confusion came from the fact that Richard wanted to get the
disconnect pulse directly, but that he was still using the
(dispatch/iofunc/resmgr) api. Sorry for adding to the confusion.

Richard, if you want to completely handle all messages yourself, why not
just use name_attach() and MsgReceive ? Invoking the dispatch library
and then handling everything yourself, is an obfuscation.

When I write servers I use either name_attach() with MsgReceive (ala QNX2),
or the resmgr library (if I want posix semantics). Works very well, and
both are “simple” and effective.

Rennie

Richard,

How’s this for simplicity and clarity ?


int chid=ChannelCreate(…_NTO_CHF_DISCONNECT…);
dispatch_t dpp=_dispatch_create(chid, NULL);
int rcvid;
struct _pulse msg;
name_attach_t *name_attachp=name_attach(dpp, “…”);

rcvid=MsgReceive(name_attachp->chid, &msg, sizeof msg, NULL);
switch(rcvid) {
case 0:
switch(msg.code) {
case _PULSE_CODE_UNBLOCK:
Unblock(msg.value.sival_int);
break;
case _PULSE_CODE_DISCONNECT:
Disconnect(msg.scoid);
break;
default:
if(msg.code >= _PULSE_CODE_MINAVAIL && msg.code < _PULSE_CODE_MAXAVAIL) {
Pulse(&msg);
}
}
break;
default:
Msg(rcvid);
break;
}

Where:

Unblock == a function to handle unblocks
Disconnect == a function to handle disconnects

and

Msg == a function to handle messages

Richard, if you want to completely handle all messages yourself, why not
just use name_attach() and MsgReceive ? Invoking the dispatch library
and then handling everything yourself, is an obfuscation.

Had to, as I wanted to do multiple name_attach on a single channel. The
only way to do this was to use a dispatcher (or at least create one). Once
I had a dispatcher, it simply lead to using more and more of the api, such
as regmgr_attach(), select_attach(), etc.

When I write servers I use either name_attach() with MsgReceive (ala
QNX2),
or the resmgr library (if I want posix semantics). Works very well, and
both are “simple” and effective.

Rennie

If it was only that simple. The code which sets up the dispatcher is part
of our reusable framework which hides away most of the details of the OS.
Hence sometimes we need to support resource manager like functionality,
sometimes not.

So for my next question: if my thread is now a resource manager, how is it
notified when the process dies? Via a fabricated _IO_CLOSE message?

“Rennie Allen” <rallen@csical.com> wrote in message
news:42D43A34.1050901@csical.com

Richard,

How’s this for simplicity and clarity ?


int chid=ChannelCreate(…_NTO_CHF_DISCONNECT…);
dispatch_t dpp=_dispatch_create(chid, NULL);
int rcvid;
struct _pulse msg;
name_attach_t *name_attachp=name_attach(dpp, “…”);

rcvid=MsgReceive(name_attachp->chid, &msg, sizeof msg, NULL);
switch(rcvid) {
case 0:
switch(msg.code) {
case _PULSE_CODE_UNBLOCK:
Unblock(msg.value.sival_int);
break;
case _PULSE_CODE_DISCONNECT:
Disconnect(msg.scoid);
break;
default:
if(msg.code >= _PULSE_CODE_MINAVAIL && msg.code
_PULSE_CODE_MAXAVAIL) {
Pulse(&msg);
}
}
break;
default:
Msg(rcvid);
break;
}

Where:

Unblock == a function to handle unblocks
Disconnect == a function to handle disconnects

and

Msg == a function to handle messages

Richard Doucet wrote:

Via a fabricated _IO_CLOSE message?

Yup. For all the gory details, download the source from cvs.qnx.com.

Rennie