{"id":1128,"date":"2015-01-03T11:54:24","date_gmt":"2015-01-03T10:54:24","guid":{"rendered":"http:\/\/blog.m-ri.de\/?p=1128"},"modified":"2015-01-03T11:54:24","modified_gmt":"2015-01-03T10:54:24","slug":"wenn-man-nicht-genau-aufpasst-mit-overlapped-io-und-cancelio-vergisst","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2015\/01\/03\/wenn-man-nicht-genau-aufpasst-mit-overlapped-io-und-cancelio-vergisst\/","title":{"rendered":"Wenn man nicht genau aufpasst mit Overlapped I\/O und CancelIo vergisst"},"content":{"rendered":"<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms686358(v=vs.85).aspx\" target=\"_blank\"><em>Overlapped I\/O<\/em><\/a> ist eine Standardtechnik, die ja jeder kennt, der mit Datenquellen arbeitet, die &#8222;irgendwann&#8220; mal Informationen liefert, man aber in der Zeit evtl. noch anderes zu tun hat \ud83d\ude09<\/p>\n<p>In meinem Fall, den ich hier schildere, benutzte unser Programm einen Service, mit dem es \u00fcber <em>Named Pipes<\/em> kommuniziert. Das entsprechende Modul, ist schon ziemlich alt und hat seit ca. 3 Jahren keine \u00c4nderung erfahren. Aber jetzt auf einmal h\u00e4uften sich Meldungen, dass unser Programm beim Beenden einen UAE ausl\u00f6st.<\/p>\n<p>Entsprechende Minidumps wurden angefordert und deren Analyse zeigte eigentlich nicht viel wirklich erhellendes.\u00a0 Es sah alles danach aus, als ob ein Speicherblock freigegeben wird, der bereits freigegeben wurde.<br \/>\nLeider konnte das Szenario in unserem Testfeld nicht einfach nachgestellt werden. Und auch mehrfache Analyse des Sourcecodes brachte erst einmal nichts. Man ist manchmal einfach betriebsblind \ud83d\ude41<\/p>\n<p>Auff\u00e4llig war aber, dass diese Meldungen erst vereinzelt auftraten nachdem unsere Software auf <em>VS-2013 Update 3<\/em> umgestellt war und diese an Kunden ausgerollt wurde. Und weiterhin konnten wir feststellen, dass alle diejenigen, die diesen Fehler gemeldet haben, relativ leistungsf\u00e4hige Rechner hatten.<\/p>\n<p>Schlie\u00dflich gelang es mir, das Szenario auf einem meiner Entwicklungsrechner nachzustellen.<\/p>\n<p>Das passierte:<\/p>\n<ol>\n<li>Das Programm erhielt den Befehl zum Beenden.<\/li>\n<li>Irgendwann wurde auch dem Thread, der mit dem Service interagiert gesagt, dass er sich beim Dienst ausloggen soll.<\/li>\n<li>Der Dienst gibt auch brav den Befehl &#8222;Logoff&#8220; an den Service.<\/li>\n<li>Der Thread der in einer Schleife immer auf einen Response des Dienstes wartet beendet sofort.<\/li>\n<li>Und nun erfolgte der Crash.<\/li>\n<\/ol>\n<p>Die Ursache war ein fehlender <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa363791(v=vs.85).aspx\" target=\"_blank\"><em>CancelIo<\/em><\/a>. Damit das Beenden m\u00f6glichst schnell vonstatten geht, wurde darauf verzichtet, auf eine Antwort des Services zu warten, ob der <em>Logoff<\/em> Befehl verstanden wurde, denn kurz danach wird sowieso die Pipe geschlossen. Keine gute Idee in diesem Fall! Das hatte auch den Grund darin, dass<\/p>\n<p>Was ist also passiert \u2753<\/p>\n<ul>\n<li>Die OVERLAPPED Struktur f\u00fcr den Lesevorgang lag auf dem Stack innerhalb einer <em>while<\/em> Schleife, die auf verschiedene Events wartet.<\/li>\n<li>Die Funktion in der diese Struktur deklariert war wurde aber bereits verlassen.<\/li>\n<li>Wenn dann sehr schnell die Antwort des Dienstes kam, wurde in die alte Adresse der OVERLAPPED Struktur ein Wert ver\u00e4ndert.<\/li>\n<li>&#8230; und damit wurde der Stack an dieser Stelle zerst\u00f6rt.<\/li>\n<\/ul>\n<p>Es waren in meinem Fall nur 4 Bytes und in manchen F\u00e4llen w\u00fcrde eine R\u00fccksprungadresse ver\u00e4ndert und es kam zum Crash. In anderen F\u00e4llen wurde Speicher ver\u00e4ndert, der nicht mehr benutzt wurde. Das ganze passierte eben auch nur auf den Systemen, die sehr schnell auf die Antwort des Dienstes reagierten. Kam die Antwort sp\u00e4t genug, war die \u00c4nderung des Speichers nicht mehr gef\u00e4hrlich.<\/p>\n<p>Der Fehler blieb jahrelang unentdeckt, weil scheinbar das Stacklayout, das durch den VS-2010 Compiler erzeugt wurde, gegen diesen Fehler unempfindlich war, weil nur Speicher ver\u00e4ndert wurde, der nicht zu einem Fehler f\u00fchrte.<\/p>\n<p>Was lerne ich daraus:<br \/>\nWenn ich einen <em>ReadFile<\/em> mit <em>OVERLAPPED<\/em> verwende, sollte ich immer darauf achten, dass im Bedarfsfall auch dieser Vorgang abgebrochen wird durch ein <em>CancelIo \u2757 <\/em>Ein <em>CancelIo <\/em>mehr kann nicht schaden, wenn man den Block verl\u00e4sst, in der eine OVERLAPPED Struktur definiert war.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Overlapped I\/O ist eine Standardtechnik, die ja jeder kennt, der mit Datenquellen arbeitet, die &#8222;irgendwann&#8220; mal Informationen liefert, man aber in der Zeit evtl. noch anderes zu tun hat \ud83d\ude09 In meinem Fall, den ich hier schildere, benutzte unser Programm einen Service, mit dem es \u00fcber Named Pipes kommuniziert. Das entsprechende Modul, ist schon ziemlich &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2015\/01\/03\/wenn-man-nicht-genau-aufpasst-mit-overlapped-io-und-cancelio-vergisst\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eWenn man nicht genau aufpasst mit Overlapped I\/O und CancelIo vergisst\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[30,11,3,172,338],"tags":[370,205,137,136,209],"class_list":["post-1128","post","type-post","status-publish","format-standard","hentry","category-c","category-debugging","category-programmieren","category-vs2010","category-vs-2013-programmieren","tag-c","tag-crash","tag-crashdump","tag-qualitaetssicherung","tag-service"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/1128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=1128"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/1128\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=1128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=1128"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=1128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}