Real time issue for register / unregister to READER_STATE_CHANGE event.
REVILLON Olivier <[email protected]> Tue, 4 Jul 2017 12:20:00 +0000
| Newsgroups | gmane.comp.lib.muscle |
|---|---|
| Message-ID | <[email protected]> |
--===============5296039881279328347==
Content-Language: fr-FR
Content-Type: multipart/alternative;
boundary="_000_149917087126193619akkaeu_"
--_000_149917087126193619akkaeu_
Content-Type: text/plain; charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable
Hello,
We have detected rare real time issue with the SCardGetStatusChange functio=
n.
But become more frequent by using SCardGetStatusChange with 0 value as time=
out and without using SCARD_STATE_UNAWARE.
The real time issue appends between the timeout of the CMD_WAIT_READER_STAT=
E_CHANGE command and the sending of the CMD_STOP_WAITING_READER_STATE_CHANG=
E command.
If we consider :
* T0 is the time when timeout is detected in the function MessageSendWi=
thHeader for the CMD_WAIT_READER_STATE_CHANGE on the library part.
* T1 is the time when the function MessageSendWithHeader is called on t=
he library part.
* T2 is the time of the call EHSignalEventToClients on the daemon part.
If in the daemon part =93PCSCD=94, a signal is sent between T0 and T1 (T0 <=
T2 < T1) this signal is considered as the response of the CMD_STOP_WAITING=
_READER_STATE_CHANGE. But the response is not =93consumed=94 on the socket.=
According to the implementation done before SCardGetStatusChange we can ha=
ve invalid data and / or error.
At this point the next behavior depends to the caller implementation. We re=
mark for our implementation that a new call of SCardGetStatusChange can =93=
repair=94 the socket shift but it can result by having an =93event register=
=94 in the daemon started without being unregistered (=3D twice register). =
So an EHSignalEventToClients event can append at any time if the client is =
not in the SCardGetStatusChange function.
We have studied this solution for a possible correction :
At daemon side:
We suggest that =930=94 is set for timeout if the message is a =93Signal=94=
message (parameter not used for the moment). In order to identify that thi=
s message is a signal instead of the response of an unregister request.
LONG MSGSignalClient(uint32_t filedes, LONG rv)
{
uint32_t ret;
struct wait_reader_state_change waStr;
Log2(PCSC_LOG_DEBUG, "Signal client: %d", filedes);
waStr.timeOut =3D 0; /* To identify message as a signal */
waStr.rv =3D rv;
WRITE_BODY_WITH_COMMAND("SIGNAL", waStr)
return ret;
} /* MSGSignalClient */
At library side:
When receiving the response of the STOP command verify if the received mess=
age is the response. For that, set timeOut to 1. If it is a signal the valu=
e is 0 then wait for the response message.
Part of SCardGetStatusChange function :
/* timeout */
if (SCARD_E_TIMEOUT =3D=3D rv)
{
/* ask server to remove us from the event li=
st */
waitStatusStruct.timeOut =3D 1; /* <=3D ADDE=
D to set a value different as 0 to identify the response. */
rv =3D MessageSendWithHeader(CMD_STOP_WAITIN=
G_READER_STATE_CHANGE,
=
currentContextMap->dwClientID,
=
sizeof(waitStatusStruct), &waitStatusStruct);
if (rv !=3D SCARD_S_SUCCESS)
goto end;
/* Read a message from the server */
rv =3D MessageReceive(&waitStatusStruct,
=
sizeof(waitStatusStruct),
=
currentContextMap->dwClientID);
if (rv !=3D SCARD_S_SUCCESS)
goto end;
/* ADDED =3D> */
if (waitStatusStruct.timeOut =3D=3D 0)
{
rv =3D MessageReceive(&waitStatusStr=
uct,
=
sizeof(waitStatusStruct),
=
currentContextMap->dwClientID);
/* We don=92t test rv value, in this cas=
e it is for sure an error. */
}
/* <=3D ADDED */
}
The issue shows us that it is possible to be registered twice. Is can bette=
r to test it when register :
LONG EHRegisterClientForEvent(int32_t filedes)
{
(void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
int pos =3D list_locate(l, data);
if (pos < 0)
{
(void)list_append(&ClientsWaitingForEvent, &=
filedes);
}
(void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
return SCARD_S_SUCCESS;
} /* EHRegisterClientForEvent */
And finally we can add but not necessary an exit condition when timeout is =
0. In fact if timeout is 0, the library doesn=92t wait so it is not necessa=
ry to register. This is in order to optimize the code.
Part of SCardGetStatusChange function :
/* Break if UNAWARE is set and all readers have been checke=
d */
if ( (dwBreakFlag =3D=3D 1) || (0 =3D=3D dwTime))
break;
Best Regards,
Olivier REVILLON
--_000_149917087126193619akkaeu_
Content-Type: text/html; charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3DWindows-1=
252">
<style type=3D"text/css" style=3D"display:none"><!-- p { margin-top: 0px; m=
argin-bottom: 0px; }--></style>
</head>
<body dir=3D"ltr" style=3D"font-size:12pt;color:#000000;background-color:#F=
FFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;">
<p>Hello,</p>
<p> </p>
<p>We have detected rare real time issue with the SCardGetStatusChange func=
tion.</p>
<p>But become more frequent by using SCardGetStatusChange with 0 value as t=
imeout and without using SCARD_STATE_UNAWARE.</p>
<p> </p>
<p>The real time issue appends between the timeout of the CMD_WAIT_READER_S=
TATE_CHANGE command and the sending of the CMD_STOP_WAITING_READER_STATE_CH=
ANGE command.</p>
<p>If we consider : </p>
<ul>
<li>T0 is the time when timeout is detected in the function MessageSendWith=
Header for the CMD_WAIT_READER_STATE_CHANGE on the library part.</li><li>T1=
is the time when the function MessageSendWithHeader is called on the libra=
ry part.</li><li>T2 is the time of the call EHSignalEventToClients on the d=
aemon part.</li></ul>
<p>If in the daemon part =93PCSCD=94, a signal is sent between T0 and T1 (T=
0 < T2 < T1) this signal is considered as the response of the CMD_STO=
P_WAITING_READER_STATE_CHANGE. But the response is not =93consumed=94 on th=
e socket. According to the implementation done
before SCardGetStatusChange we can have invalid data and / or error.</p>
<p> </p>
<p>At this point the next behavior depends to the caller implementation. We=
remark for our implementation that a new call of SCardGetStatusChange can =
=93repair=94 the socket shift but it can result by having an =93event regis=
ter=94 in the daemon started
<span lang=3D"EN-US" style=3D"text-decoration: underline;">without being un=
registered (=3D twice register)</span>. So an EHSignalEventToClients event =
can append at any time if the client is not in the SCardGetStatusChange fun=
ction.</p>
<p> </p>
<p>We have studied this solution for a possible correction :</p>
<p><span lang=3D"EN-US" style=3D"text-decoration: underline;">At daemon sid=
e</span>:</p>
<p>We suggest that =930=94 is set for timeout if the message is a =93Signal=
=94 message (parameter not used for the moment). In order to identify that =
this message is a signal instead of the response of an unregister request.<=
/p>
<p>LONG MSGSignalClient(uint32_t filedes, LONG rv)<br>
{<br>
&nb=
sp; uint32_t ret;<br>
&nb=
sp; struct wait_reader_state_change waStr;</p>
<p> =
Log2(PCSC_LOG_DEBUG, "Signal client: %d", file=
des);</p>
<p><strong> &nbs=
p; waStr.timeOut =3D 0;</strong><strong> </st=
rong><strong>/* To identify message as a signal */</strong><br>
&nb=
sp; waStr.rv =3D rv;<br>
&nb=
sp; WRITE_BODY_WITH_COMMAND("SIGNAL", waStr)</p>
<p> =
return ret;<br>
} /* MSGSignalClient */</p>
<p> </p>
<p><span lang=3D"EN-US" style=3D"text-decoration: underline;">At library si=
de</span>:<br>
When receiving the response of the STOP command verify if the received mess=
age is the response. For that, set timeOut to 1. If it is a signal the valu=
e is 0 then wait for the response message.</p>
<p>Part of SCardGetStatusChange function :<br>
&nb=
sp; /* timeout */<br>
&nb=
sp; if (SCARD_E_TIMEOUT =3D=3D rv)<br>
&nb=
sp; {<br>
&nb=
sp; =
/* ask server to remove us from the event li=
st */<br>
&nb=
sp; =
<strong>waitStatusStruct.timeOut =3D 1; /* &=
lt;=3D ADDED to set a value different as 0 to identify the response. */</st=
rong><br>
&nb=
sp; =
rv =3D MessageSendWithHeader(CMD_STOP_WAITIN=
G_READER_STATE_CHANGE,<br>
&nb=
sp; =
&nb=
sp; =
&nb=
sp; =
&nb=
sp; currentContextMap->dwClientID,<br>
&nb=
sp; =
&nb=
sp; =
&nb=
sp; =
&nb=
sp; sizeof(waitStatusStruct), &waitStatus=
Struct);</p>
<p> =
&nb=
sp; if (rv !=3D SCARD_S_SUCCESS)<br>
&nb=
sp; =
&nb=
sp; goto end;</p>
<p> =
&nb=
sp; /* Read a message from the server */<br>
&nb=
sp; =
rv =3D MessageReceive(&waitStatusStruct,=
<br>
&nb=
sp; =
&nb=
sp; =
&nb=
sp; =
sizeof(waitStatusStruct),<br>
&nb=
sp; =
&nb=
sp; =
&nb=
sp; =
currentContextMap->dwClientID);</p>
<p> =
&nb=
sp; if (rv !=3D SCARD_S_SUCCESS)<br>
&nb=
sp; =
&nb=
sp; goto end;<br>
&nb=
sp; =
<strong> /* ADDED =3D> */</strong><b=
r>
&nb=
sp; <strong> &nb=
sp; </strong><strong>if (waitStatusStru=
ct.timeOut =3D=3D 0)</strong><br>
<strong> &=
nbsp; &nbs=
p; {</strong><br>
<strong> &=
nbsp; &nbs=
p; =
rv =3D MessageReceive(&waitStatusStruct,</strong><br>
<strong> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p;
</strong><strong> </strong><strong>sizeof(waitStatusStruc=
t),</strong><br>
<strong> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p;
</strong><strong> </strong><strong>currentContextMap->=
dwClientID);</strong><br>
<strong> &=
nbsp; &nbs=
p; /* We don=92=
t test rv value, in this case it is for sure an error. */</strong><br>
<strong> &=
nbsp; &nbs=
p; }</strong><br>
<strong> &=
nbsp; &nbs=
p; /* <=3D ADDED */</strong><br>
&nb=
sp; }</p>
<p> </p>
<p> </p>
<p>The issue shows us that it is possible to be registered twice. Is can be=
tter to test it when register :</p>
<p>LONG EHRegisterClientForEvent(int32_t filedes)<br>
{<br>
&nb=
sp; (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);=
</p>
<p><strong> &nbs=
p; int pos =3D list_locate(l, data);</strong><br>
<strong> &=
nbsp; </strong><strong>if (pos < 0)</strong><br>
<strong> &=
nbsp; </strong><strong>{</strong><br>
&nb=
sp; =
(void)list_append(&ClientsWaitingForEven=
t, &filedes);<br>
<strong> &=
nbsp; </strong><strong>}</strong></p>
<p> =
(void)pthread_mutex_unlock(&ClientsWaitingForEvent_l=
ock);</p>
<p> =
return SCARD_S_SUCCESS;<br>
} /* EHRegisterClientForEvent */</p>
<p> </p>
<p>And finally we can add but not necessary an exit condition when timeout =
is 0. In fact if timeout is 0, the library doesn=92t wait so it is not nece=
ssary to register. This is in order to optimize the code.</p>
<p> </p>
<p>Part of SCardGetStatusChange function :<br>
&nb=
sp; /* Break if UNAWARE is set and all readers have been checke=
d */<br>
&nb=
sp; if ( (dwBreakFlag =3D=3D 1) <strong>|| (0 =3D=3D dwTime)</s=
trong>)<br>
&nb=
sp; =
break;</p>
<p> <br>
Best Regards,</p>
<p> </p>
<p>Olivier REVILLON</p>
</body>
</html>
--_000_149917087126193619akkaeu_--
--===============5296039881279328347==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Pcsclite-muscle mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pcsclite-muscle
--===============5296039881279328347==--