Sven Lanoster
2016-09-10 20:33:52 UTC
Moin, moin.
Der Anwender meldet, dass unregelmäßig nach einiger Zeit die Buttons
nicht mehr auf Mausklicks reagieren. Zum Beispiel kommt beim Schließen
eines Fensters die Nachfrage "Sollen die Änderungen gespeichert werden?
[Ja] [Nein] [Abbrechen]". Wenn man mit der Maus auf einen der drei
Buttons zeigt, sieht man, dass der Button den Fokus bekommt, aber der
Klick wird nicht ausgelöst. Der Button ändert sich beim Klick optisch
nicht und es passiert auch sonst nichts. Mit der Tastatur läßt sich der
Button jedoch bedienen und ein Mausklick auf das System-X rechts oben
zum Schließen des Fensters funktioniert auch.
Außerdem funktionieren Comboboxen plötzlich nicht mehr. Das
Dropdown-Fenster klappt sofort wieder zu. Da es in dem Programm
Ereignis-Handler für OnDropDown gibt, in dem die DropDown-Liste
dynamisch gefüllt wird, nahm ich an, hier läge der Hase im Pfeffer. Aber
auch nach intensivem meditativem Draufstarren kann ich dort nichts
auffälliges finden.
Auffällig in dem Code ist, dass beim Start ein Timer erzeugt wird
(create(NIL)) mit 100 ms Intervall, der im Ontimer prüft, ob das Form
bereits sichtbar ist. Wenn es das ist, wird der Timer deaktiviert und
eine Initialisierung (eigenes DropDown in die Comboboxen eintragen)
angeworfen. Der Timer wird nicht freigegeben und an keiner anderen
Stelle deaktiviert.
Wenn das Programm im Fehlerzustand ist (Comboboxen und Buttons reagieren
nicht mehr richtig auf Mausklick) und man es schließt, verschwindet das
Programm-Symbol aus der Windows-Startleiste und danach hagelt es
Schutzverletzungen in variabler Anzahl und Adressen (sowohl
dereferenzierte NULL-Pointer als auch sehr große Adressen).
Die Umgebung ist etwas unübersichtlich. Das Programm ist ein
Fremdprodukt (groß, komplex, für Unternehmen, ClientServer,
Multithreaded, Terminalserver, usw.), welches Erweiterungen über
Interfaces zulässt.
Mein Quellcode ist also in einer DLL in einer Klasse, die über mehrere
Ecken von TForm erbt, ein Interface implementiert und per RegisterClass
instanzierbar ist. Das echte Form wird in einer Init-Prozedur übergeben,
so dass ich dort eigene Komponenten hinzufügen und die vorhandenen
manipulieren kann.
Und selbstverständlich ist das Verhalten nicht auf Befehl
reproduzierbar, von mir selbst gar nicht, tritt aber bei den Anwendern
mehrmals am Tag auf. Und ein Programm-Update ist umständlich,
langwierig, bürokratisch, teuer und deswegen möglichst zu vermeiden. Ich
kann also nicht mal eben etwas ändern und mit "probieren Sie mal so..."
kommen.
Per Debug-Logs habe ich festgestellt, dass der 100ms-Timer während das
Fenster noch unsichtbar ist, nur alle 500 bis 800 ms überhaupt zum
Schuss kommt. Ich vermute, dass es ein Anwender schaffen könnte, das
Fenster per [ESC] zu schließen, bevor der Timer im OnTimer deaktiviert
wird (das passiert ja nur, wenn das Fenster sichtbar ist). Da der Timer
nicht freigegeben wird (der Rest drumherum jedoch schon), werden weiter
WM_TIMER-Nachrichten an die Applikation geschickt, die ja direkt die
Speicheradresse der OnTimer-Prozedur enthalten, also anders als sonstige
Messages behandelt werden. Was mit diesen Messages dann passiert, ist
mir unklar.
Die Frage ist jetzt: Gibt es einen denkbaren Zusammenhang zwischen dem
amoklaufenden Timer und dem Mausklick-Fehler?
Sowohl die Combobox als auch der Button haben ein OnDropDown...-Event,
das (indirekt) über Messages gefeuert wird. Kann es sein, dass diese
Messages "liegen bleiben" bis zum Programmende?
Gruß,
Sven.
Der Anwender meldet, dass unregelmäßig nach einiger Zeit die Buttons
nicht mehr auf Mausklicks reagieren. Zum Beispiel kommt beim Schließen
eines Fensters die Nachfrage "Sollen die Änderungen gespeichert werden?
[Ja] [Nein] [Abbrechen]". Wenn man mit der Maus auf einen der drei
Buttons zeigt, sieht man, dass der Button den Fokus bekommt, aber der
Klick wird nicht ausgelöst. Der Button ändert sich beim Klick optisch
nicht und es passiert auch sonst nichts. Mit der Tastatur läßt sich der
Button jedoch bedienen und ein Mausklick auf das System-X rechts oben
zum Schließen des Fensters funktioniert auch.
Außerdem funktionieren Comboboxen plötzlich nicht mehr. Das
Dropdown-Fenster klappt sofort wieder zu. Da es in dem Programm
Ereignis-Handler für OnDropDown gibt, in dem die DropDown-Liste
dynamisch gefüllt wird, nahm ich an, hier läge der Hase im Pfeffer. Aber
auch nach intensivem meditativem Draufstarren kann ich dort nichts
auffälliges finden.
Auffällig in dem Code ist, dass beim Start ein Timer erzeugt wird
(create(NIL)) mit 100 ms Intervall, der im Ontimer prüft, ob das Form
bereits sichtbar ist. Wenn es das ist, wird der Timer deaktiviert und
eine Initialisierung (eigenes DropDown in die Comboboxen eintragen)
angeworfen. Der Timer wird nicht freigegeben und an keiner anderen
Stelle deaktiviert.
Wenn das Programm im Fehlerzustand ist (Comboboxen und Buttons reagieren
nicht mehr richtig auf Mausklick) und man es schließt, verschwindet das
Programm-Symbol aus der Windows-Startleiste und danach hagelt es
Schutzverletzungen in variabler Anzahl und Adressen (sowohl
dereferenzierte NULL-Pointer als auch sehr große Adressen).
Die Umgebung ist etwas unübersichtlich. Das Programm ist ein
Fremdprodukt (groß, komplex, für Unternehmen, ClientServer,
Multithreaded, Terminalserver, usw.), welches Erweiterungen über
Interfaces zulässt.
Mein Quellcode ist also in einer DLL in einer Klasse, die über mehrere
Ecken von TForm erbt, ein Interface implementiert und per RegisterClass
instanzierbar ist. Das echte Form wird in einer Init-Prozedur übergeben,
so dass ich dort eigene Komponenten hinzufügen und die vorhandenen
manipulieren kann.
Und selbstverständlich ist das Verhalten nicht auf Befehl
reproduzierbar, von mir selbst gar nicht, tritt aber bei den Anwendern
mehrmals am Tag auf. Und ein Programm-Update ist umständlich,
langwierig, bürokratisch, teuer und deswegen möglichst zu vermeiden. Ich
kann also nicht mal eben etwas ändern und mit "probieren Sie mal so..."
kommen.
Per Debug-Logs habe ich festgestellt, dass der 100ms-Timer während das
Fenster noch unsichtbar ist, nur alle 500 bis 800 ms überhaupt zum
Schuss kommt. Ich vermute, dass es ein Anwender schaffen könnte, das
Fenster per [ESC] zu schließen, bevor der Timer im OnTimer deaktiviert
wird (das passiert ja nur, wenn das Fenster sichtbar ist). Da der Timer
nicht freigegeben wird (der Rest drumherum jedoch schon), werden weiter
WM_TIMER-Nachrichten an die Applikation geschickt, die ja direkt die
Speicheradresse der OnTimer-Prozedur enthalten, also anders als sonstige
Messages behandelt werden. Was mit diesen Messages dann passiert, ist
mir unklar.
Die Frage ist jetzt: Gibt es einen denkbaren Zusammenhang zwischen dem
amoklaufenden Timer und dem Mausklick-Fehler?
Sowohl die Combobox als auch der Button haben ein OnDropDown...-Event,
das (indirekt) über Messages gefeuert wird. Kann es sein, dass diese
Messages "liegen bleiben" bis zum Programmende?
Gruß,
Sven.
--
Seltsam? Aber so steht es geschrieben...
Seltsam? Aber so steht es geschrieben...