2017-08-24 3 views
-1

Ich arbeite an einem Uni-Projekt, das aus einer Art Multithread-Server besteht ... Ich bemerkte, dass, wenn ein Testskript ausgeführt wird, das Programm normal endet, aber stecken bleibt bei der Rückgabeanweisung.C-Programm wird nicht beendet

Ausführlicher erklären, habe ich einen Haupt-Thread und mehrere andere Threads. Wenn das Testskript endet, sendet es ein SIGQUIT-Signal an den Prozess. Einer meiner Threads fängt dieses Signal ab, gibt einige Sachen frei und setzt ein Flag, das dem Hauptthread mitteilt, dass die Säuberung gestartet werden soll, dann wird es beendet.

Der Haupt-Thread führt die Bereinigung durch eine pthread_join auf allen anderen Threads zu tun und ruft dann Rückkehr 0.

I geprüft, indem ein printf vor der Rückkehr-Anweisung in der Signalbehandlungsroutine Gewinde und vor der Rücksprungbefehl in puttin das Haupt, und beide werden gedruckt, aber das Programm bleibt stecken.

(beachten Sie, dass für die Haupt-Thread die return-Anweisung zu erreichen, werden alle anderen Seite Threads beendet ist, wie ich für jede dieser wartete)

+0

Willkommen. Bitte lesen Sie die Seiten [Über] und [Fragen] bald. Viel dringender, es gibt nichts, was wir tun können, außer diese Frage zu halten, es sei denn, Sie zeigen uns den Code - wir brauchen einen MCVE ([MCVE]), um helfen zu können. Es gibt endlose Dinge, die schief gehen könnten, um Ihr Programm endlos zu machen; Ohne den Code können wir nicht anfangen zu erraten, wie erfinderisch und clever Sie gewesen sind. –

+0

Nun, ich weiß ehrlich nicht, welchen Code zu setzen, da es 7000+ Zeilen von ziemlich komplizierten Code ist ... Durch Zufall, das Problem selbst behoben, ich weiß nicht wie, aber nach ein paar Mal es erneut versuchen fing gerade an, gut zu arbeiten, ich denke, es war ein OS-Problem dann – NokiStrawby

+0

Und wir sollen raten, was Sie falsch in mehr als 7000 Zeilen Code haben. Hier kommt das M in MCVE (minimal) ins Spiel. Du musst an deinem Code arbeiten, ihn am Laufen halten (oder vielmehr auf die gleiche Art und Weise versagen), während du alles entfernst, was überflüssig ist. Siehe auch SSCCE ([Simple, Self-Contained, Complete/Compilable Beispiel] (http://sscce.org/)). –

Antwort

1

ich puttin ein printf vor der return-Anweisung überprüft in dem Signal-Handler-Thread

Wenn dieser „Faden“ ist eine tatsächliche Signal-Handler-Funktion durch so etwas wie signal() oder sigaction installiert ist, Anrufe an nicht-Asynchron-Signal sichere Funktionen macht aus einem Signal-Handler nicht sicher kannst . See the POSIX standard, wie Signale behandelt werden und die Liste der Funktionen, die Asynchron-Signal-safe sind erforderlich, um zu sein:

Jede Funktion nicht in der obigen Tabelle ist möglicherweise nicht sicher in Bezug auf Signale. Implementierungen können andere Schnittstellen async-signalsicher machen. Bei Vorhandensein von Signalen müssen sich alle Funktionen, die in diesem Volumen von POSIX.1-2008 definiert sind, wie beim Aufruf von definiert oder unterbrochen durch eine Signalfangfunktion verhalten, mit der Ausnahme, dass ein Signal eine unsichere Funktion unterbricht oder Äquivalent (z. B. die Verarbeitung entspricht exit() ausgeführt nach einer Rückkehr vom ersten Aufruf an main()) und die Signalfangfunktion ruft eine unsichere Funktion auf, das Verhalten ist nicht definiert.

Einer der möglichen Fehlermöglichkeiten für solche Aufrufe ist ein Deadlock, der Ihren Prozess stoppt.

Was passiert, ist zum Beispiel Ihr Prozess free() oder oder einer seiner Cousins, entweder direkt oder indirekt. Diese Funktionen können alle Sperren aufweisen, um Speicherzuweisungsdaten vor gleichzeitiger Modifikation und Beschädigung zu schützen. Während diese Sperre gehalten wird, wird der Thread durch ein Signal unterbrochen, und dann führt Ihr Signalhandler einen Aufruf aus, der die bereits gesperrte Sperre erfordert. So blockiert es im Signalhandler und wartet auf die Freigabe der Sperre. Das wird nie passieren, weil der Thread, der die Sperre hält, derselbe ist, der blockiert ist, der darauf wartet, die Sperre wieder zu bekommen.

Deadlock.

Und Funktionen wie printf() oft intern verwenden malloc() und free().

Wenn die Funktion nicht in der Liste der asynchronen Funktionen enthalten ist, können Sie sie nicht über einen Signalhandler aufrufen. Zeitraum.

Und unter Linux müssen Sie fork() zur Liste der unsicheren Funktionen hinzufügen, da die glibc-Implementierung nicht den POSIX-Standard erfüllt.

+0

Haben Sie irgendwelche Ansichten darüber, warum POSIX nicht denkt, dass 'strlen()' und verwandte Funktionen threadsicher sind (oder sollten)? –

+0

Es war nicht das, ich benutze keine sigaction, ich benutze einen separaten Thread, um die Signale zu behandeln, und ich mache das, um nicht asynchrone sichere Funktionen zu verwenden ... Es ist kein Deadlock Entweder plante ich jede Interaktion mit einem gemeinsamen Objekt, so dass Sperren einer strengen Reihenfolge folgen und freigegebene Objekte nicht frei werden können, wenn sie verwendet werden. Das Problem war eigentlich, dass Ubuntu einige seltsame Sachen mit Prozessen machte, ich bemerkte, dass ein Prozess immer noch aus irgendeinem Grund lief, und killall versuchte, diesen statt desjenigen zu beenden, der gemeint war ... – NokiStrawby

+0

@JonathanLeffler * Do Sie haben irgendwelche Ansichten darüber, warum POSIX nicht denkt, dass "strlen()" und verwandte Funktionen thread-sicher sind (oder sollten)? Nicht wirklich. Nun, da du mich dazu zwingst, darüber nachzudenken ;-), denke ich, es ist eine Kombination aus der Vermeidung von Implementierungsdetails und/oder dem Bikeshedding, während du auch wichtigere Dinge hast, um begrenzte Zyklen auszugeben, vor allem, wenn du ein bekanntes brauchst async-signal-safe 'strlen()' oder ähnliches können Sie in wenigen Minuten selbst schreiben. –

0

Das Problem war, Ubuntu hat ein Problem mit der Prozessbeendigung mit, i einige Prozesse beenden, die aus dem vorherigen Test im Hintergrund stecken geblieben waren, und es funktionierte auf Stack-Überlauf