<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Event Handler Timing Problem]]></title><description><![CDATA[<p>Hallo,</p>
<p>vielleicht hat jemand von euch eine gute Idee, die mir bei der Lösung eines Problems hilft. Ich hab´ das <a href="http://www.c-plusplus.net/forum/290838" rel="nofollow">Problem</a> gestern schon im VCL Forum gepostet, kann´s aber hier nochmal kurz zusammenfassen:</p>
<p>Ich habe einen TCP/IP Server, der eventgesteuert arbeitet. Zwei dieser Events sind <code>OnClientRead</code> und <code>OnClientDisconnect</code> . Im <code>OnClientRead</code> Event Handler lese ich Daten aus einer Socket in einen Puffer, der dem Socket zugeordnet ist (std::map, SocketID als Key, ein Puffer als Value). Im <code>OnClientDisconnect</code> Event Handler lösche ich den Eintrag für den geschlossenen Socket aus der map. Das Problem liegt darin, dass der Event Handler für das <code>OnClientDisconnect</code> Event sofort ausgeführt wird, auch wenn die CPU sich gerade im <code>OnClientRead</code> Event Handler befindet. Das führt dazu, dass der Puffer Eintrag für den geschlossenen Socket aus der map gelöscht wird. Anschließend kehrt die CPU in den <code>OnClientRead</code> Event Handler zurück, wo sie dann über eine dangling reference stolpert. Seltsamerweise findet dabei kein Threadwechsel statt, d.h. der gerade ausgeführte Thread wird nicht durch einen anderen unterbrochen. Damit greifen dann auch Synchronisierungsmaßnahmen wie Critical Sections nicht.</p>
<p>Als Lösung fallen mir da nicht wirklich schöne Sachen zu ein, außer weitere Informationen mit dem Puffer zusammen abzulegen und die ggf. zu prüfen. So könnte im <code>OnClientDisconnect</code> Handler der Socket als tot markiert werden und dieses Flag im <code>OnClientRead</code> Event Handler berücksichtigt werden. Das Markieren eines Socket müsste dann allerdings atomar sein, damit ich mir nicht andere Timing Probleme einfange.</p>
<p>Wenn da jemand einen brauchbaren Ansatz hätte fände ich das super.</p>
<p>PS:<br />
Externe Bibliotheken kommen leider nicht in Frage, leider wird mein Compiler (Codegear RAD Studio 2007) nur bis boost 1.34 unterstützt, sodass ich die boost::asio Bibliothek nicht benutzen kann.</p>
<p>Edit:<br />
(1) Typos fixed<br />
(2) Threadüberschrift angepasst</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/290881/event-handler-timing-problem</link><generator>RSS for Node</generator><lastBuildDate>Tue, 18 Aug 2026 02:28:02 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/290881.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 05 Aug 2011 08:31:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Event Handler Timing Problem on Fri, 05 Aug 2011 08:44:02 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>vielleicht hat jemand von euch eine gute Idee, die mir bei der Lösung eines Problems hilft. Ich hab´ das <a href="http://www.c-plusplus.net/forum/290838" rel="nofollow">Problem</a> gestern schon im VCL Forum gepostet, kann´s aber hier nochmal kurz zusammenfassen:</p>
<p>Ich habe einen TCP/IP Server, der eventgesteuert arbeitet. Zwei dieser Events sind <code>OnClientRead</code> und <code>OnClientDisconnect</code> . Im <code>OnClientRead</code> Event Handler lese ich Daten aus einer Socket in einen Puffer, der dem Socket zugeordnet ist (std::map, SocketID als Key, ein Puffer als Value). Im <code>OnClientDisconnect</code> Event Handler lösche ich den Eintrag für den geschlossenen Socket aus der map. Das Problem liegt darin, dass der Event Handler für das <code>OnClientDisconnect</code> Event sofort ausgeführt wird, auch wenn die CPU sich gerade im <code>OnClientRead</code> Event Handler befindet. Das führt dazu, dass der Puffer Eintrag für den geschlossenen Socket aus der map gelöscht wird. Anschließend kehrt die CPU in den <code>OnClientRead</code> Event Handler zurück, wo sie dann über eine dangling reference stolpert. Seltsamerweise findet dabei kein Threadwechsel statt, d.h. der gerade ausgeführte Thread wird nicht durch einen anderen unterbrochen. Damit greifen dann auch Synchronisierungsmaßnahmen wie Critical Sections nicht.</p>
<p>Als Lösung fallen mir da nicht wirklich schöne Sachen zu ein, außer weitere Informationen mit dem Puffer zusammen abzulegen und die ggf. zu prüfen. So könnte im <code>OnClientDisconnect</code> Handler der Socket als tot markiert werden und dieses Flag im <code>OnClientRead</code> Event Handler berücksichtigt werden. Das Markieren eines Socket müsste dann allerdings atomar sein, damit ich mir nicht andere Timing Probleme einfange.</p>
<p>Wenn da jemand einen brauchbaren Ansatz hätte fände ich das super.</p>
<p>PS:<br />
Externe Bibliotheken kommen leider nicht in Frage, leider wird mein Compiler (Codegear RAD Studio 2007) nur bis boost 1.34 unterstützt, sodass ich die boost::asio Bibliothek nicht benutzen kann.</p>
<p>Edit:<br />
(1) Typos fixed<br />
(2) Threadüberschrift angepasst</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2102150</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2102150</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Fri, 05 Aug 2011 08:44:02 GMT</pubDate></item><item><title><![CDATA[Reply to Event Handler Timing Problem on Fri, 05 Aug 2011 08:35:32 GMT]]></title><description><![CDATA[<p>Mach dir eine Queue mit Tasks. Wenn dein OnClientDisconnect Handler aufgerufen wurde, entfernst du alle entsprechenden Read-Tasks aus der Queue. Im Read Handler kannst du das prüfen, ob du noch in der Queue bist. Stattdessen kannst du auch einfach OnClientDisconnect im Read behandeln.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2102158</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2102158</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Fri, 05 Aug 2011 08:35:32 GMT</pubDate></item><item><title><![CDATA[Reply to Event Handler Timing Problem on Fri, 05 Aug 2011 08:50:47 GMT]]></title><description><![CDATA[<p>Zu 1)<br />
Das ist wieder ein Timing Problem, ich kann ja nicht vorhersagen, wann mir das <code>OnClientDisconnect</code> Event dazwischenfunkt. Folgendes Szenario könnte ja auch auftreten:</p>
<pre><code class="language-cpp">void OnClientRead()
{
   if( check_socket_state() )
   {
      receive();
      dispatch();
   }
}
</code></pre>
<p>Wenn <code>OnClientDisconnect</code> zwischen <code>check_socket_state</code> und <code>receive</code> auftritt habe ich das gleiche Problem.</p>
<p>Zu 2)<br />
Geht leider nicht, da sich die CPU nicht zwingend im <code>OnClientRead</code> Event Handler befindet. Wenn die Gegenstelle den Socket normal schließt, ohne jemals ein Telegramm verschickt zu haben bekäme der Server nichts davon mit.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2102175</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2102175</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Fri, 05 Aug 2011 08:50:47 GMT</pubDate></item><item><title><![CDATA[Reply to Event Handler Timing Problem on Fri, 05 Aug 2011 08:58:06 GMT]]></title><description><![CDATA[<p>Was, wenn du im Disconnect einen neuen Thread erstellst, und dann durch z.B. Mutexes absicherst?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2102180</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2102180</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Fri, 05 Aug 2011 08:58:06 GMT</pubDate></item><item><title><![CDATA[Reply to Event Handler Timing Problem on Fri, 05 Aug 2011 09:06:41 GMT]]></title><description><![CDATA[<p>Das könnte funktionieren, werd´s mal ausprobieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2102183</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2102183</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Fri, 05 Aug 2011 09:06:41 GMT</pubDate></item></channel></rss>