Schnittstelle zu dem Code, der select () aufruft

Ich schreibe eine Haskell-Bindung an einige der Bibliothek und es gibt eine Funktion void foo() , die select() innerhalb aufruft. Wenn ich diese Funktion von Haskell aus aufrufen, beginnt der select() -Aufruf EINTR . Dies verwirrt den Bibliothekscode und es beginnt für immer zu loopen.

Im #haskell IRC-Kanal wurde mir gesagt, dass ich foo() von einem gebundenen Thread ausführen soll. Ich habe dafür runInBoundThread verwendet und jetzt scheint alles zu funktionieren. Aber in einigen seltenen Fällen bekomme ich Alarm Nachricht in der Konsole ( Ok, ich habe gefunden, dass die App SIGALRM fängt ).

Ich bin mir nicht sicher, ob es richtig ist, dieses Problem zu behandeln, und ich möchte nicht auf Control.Concurrency angewiesen sein. Was soll ich machen?

5
nl ja ru
Ich höre GHC verwendet intern SIGALRM und SIGVTALRM für Thread-Management. Wenn der fremde Code-Thread für diese Signale empfindlich ist, sollten Sie sie für diesen Thread blockieren. Siehe z.B. withRTSSignalsBlocked aus Database.HDBC.MySQL.RTS .
hinzugefügt der Autor n.m., Quelle
Control.Concurrent ist Teil der Standardbibliothek - je nachdem, ob es sich um Haskell handelt. Warum willst du dieses Modul nicht benutzen? (Obwohl ich zugeben muss, dass die Alarmmeldungen seltsam sind, habe ich das nie gesehen)
hinzugefügt der Autor luqui, Quelle

2 Antworten

Die Ursache von SIGALRM war die Laufzeit von GHC, die einen alten Codepath zur Verwaltung von Timer-Daten verwendete. Dieser alte Codepath wurde aktiviert, weil das GHC configure-Skript bei der Überprüfung der create_timer() -Funktion eine gewisse Art von Linuxismus aufwies. Durch die Korrektur hat GHC denselben Mechanismus verwendet, der auf allen Plattformen verwendet wird, und den Fehler beseitigt.

Relevant Phabricator Diff: https://phabricator.haskell.org/D831

2
hinzugefügt

n.m.'s comment is correct: the code in withRTSSignalsBlocked will hide signals from your ffi'd code: http://hackage.haskell.org/packages/archive/HDBC-mysql/0.6.6.1/doc/html/Database-HDBC-MySQL.html#v:withRTSSignalsBlocked

Dies sollte auch die Notwendigkeit für runInBoundThread beseitigen, denke ich.

1
hinzugefügt
Dann ist es klar, dass die Aktion, die Sie aufrufen, die von rTSSignalsBlocked überwacht wird, nicht diejenige ist, die den Fehler verursacht, oder etwas mit trägsamem IO tut. d. h. das Blockieren der Signale funktioniert, aber sie werden irgendwo anders gefangen als beim Ausführen der Aktion.
hinzugefügt der Autor sclv, Quelle
withRTSSignalsBlocked act = runInBoundThread. alloca $ \ set -> do ... Hmm ... okay, ich werde es trotzdem versuchen.
hinzugefügt der Autor arrowd, Quelle
Das hat mir nicht geholfen. Wenn ich runInBoundThread und pthread_sigmask den Aufruf von rhs von finally lösche, funktioniert es. Aber es ist völlig falsch, wenn ich es richtig verstehe.
hinzugefügt der Autor arrowd, Quelle
Okay, ich habe runInBoundThread durch forkOS ersetzt, den zweiten pthread_unmask -Aufruf entfernt und es hat funktioniert. Dies kostete mich eine Fähigkeit, den Wert des Auslandsanrufs zu erhalten, aber ich brauche es glücklicherweise nicht. Trotzdem, es ist sooo hackish):
hinzugefügt der Autor arrowd, Quelle