Ich erstelle einen Thread und versetze ihn in eine Endlosschleife. Ich bekomme Speicherlecks, wenn ich den Code mit überprüfe Valgrind. Hier ist mein Code:
#include <pthread.h>
#include <time.h>
void thread_do(void){
while(1){}
}
int main(){
pthread_t th;
pthread_create(&th, NULL, (void *)thread_do, NULL);
sleep(2);
/* I want to kill thread here */
sleep(2);
return 0;
}
Also wird ein Thread in main erstellt und führt die ganze Zeit nur thread_do() aus. Gibt es eine Möglichkeit, es von innen zu töten? hauptsächlich nach 2 Sekunden? Ich habe beides ausprobiert pthread_detach(th)
und pthread_cancel(th)
aber ich bekomme immer noch Lecks.
Wie @sarnold betonte, kann Ihr Thread standardmäßig nicht mit abgebrochen werden pthread_cancel()
ohne Aufruf von Funktionen, die Abbruchpunkte sind … aber dies kann mit geändert werden pthread_setcanceltype()
um den Abbruchtyp des Threads auf asynchron statt auf verzögert festzulegen. Dazu fügen Sie etwas hinzu wie pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
am Anfang Ihrer Thread-Funktion, bevor Sie die Schleife starten. Sie könnten dann den Thread durch einen Aufruf beenden pthread_cancel(th)
aus main()
.
Beachten Sie jedoch, dass das Abbrechen von Threads auf diese Weise (ob asynchron oder nicht) keine in der Thread-Funktion zugewiesenen Ressourcen bereinigt (wie von Kevin in einem Kommentar angemerkt). Um dies sauber zu tun, können Sie:
- Stellen Sie sicher, dass der Thread nichts tut, was er vor dem Beenden aufräumen muss (zB using
malloc()
um einen Puffer zuzuweisen)
- Stellen Sie sicher, dass Sie eine Möglichkeit haben, nach dem Thread an anderer Stelle aufzuräumen, nachdem der Thread beendet wurde
- Verwenden
pthread_cleanup_push()
und pthread_cleanup_pop()
um Bereinigungshandler hinzuzufügen, um Ressourcen zu bereinigen, wenn der Thread abgebrochen wird. Beachten Sie, dass dies immer noch riskant ist, wenn der Abbruchtyp asynchron ist, da der Thread zwischen dem Zuweisen einer Ressource und dem Hinzufügen des Bereinigungshandlers abgebrochen werden könnte.
- Vermeide das Benutzen
pthread_cancel()
und lassen Sie den Thread eine Bedingung prüfen, um zu bestimmen, wann er beendet werden soll (was in lang andauernden Schleifen geprüft würde). Da Ihr Thread dann selbst auf Terminierung prüft, kann er nach der Prüfung alle erforderlichen Aufräumarbeiten durchführen.
Eine Möglichkeit, die letzte Option zu implementieren, besteht darin, einen Mutex als Flag zu verwenden und damit zu testen pthread_mutex_trylock()
in eine Funktion verpackt, die in den Schleifentests verwendet werden soll:
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
/* Returns 1 (true) if the mutex is unlocked, which is the
* thread's signal to terminate.
*/
int needQuit(pthread_mutex_t *mtx)
{
switch(pthread_mutex_trylock(mtx)) {
case 0: /* if we got the lock, unlock and return 1 (true) */
pthread_mutex_unlock(mtx);
return 1;
case EBUSY: /* return 0 (false) if the mutex was locked */
return 0;
}
return 1;
}
/* Thread function, containing a loop that's infinite except that it checks for
* termination with needQuit()
*/
void *thread_do(void *arg)
{
pthread_mutex_t *mx = arg;
while( !needQuit(mx) ) {}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
pthread_mutex_t mxq; /* mutex used as quit flag */
/* init and lock the mutex before creating the thread. As long as the
mutex stays locked, the thread should keep running. A pointer to the
mutex is passed as the argument to the thread function. */
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
sleep(2);
/* unlock mxq to tell the thread to terminate, then join the thread */
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
sleep(2);
return 0;
}
Wenn der Thread nicht getrennt ist (das ist im Allgemeinen nicht standardmäßig der Fall), sollten Sie anrufen pthread_join()
nach Beendigung des Threads. Wenn der Thread getrennt ist, müssen Sie ihm nicht beitreten, aber Sie wissen nicht genau, wann er endet (oder sogar ungefähr, es sei denn, Sie fügen eine andere Möglichkeit hinzu, um seinen Ausgang anzuzeigen).
Ein paar kleine Gedanken:
- Sie versuchen, Ihren Thread zu stornieren, aber wenn die geltenden Stornierungsrichtlinien eine verzögerte Stornierung vorsehen, ist Ihre
thread_do()
wird niemals abgebrochen, da es niemals Funktionen aufruft, die Abbruchpunkte sind:
A thread's cancellation type, determined by
pthread_setcanceltype(3), may be either asynchronous or
deferred (the default for new threads). Asynchronous
cancelability means that the thread can be canceled at any
time (usually immediately, but the system does not guarantee
this). Deferred cancelability means that cancellation will
be delayed until the thread next calls a function that is a
cancellation point. A list of functions that are or may be
cancellation points is provided in pthreads(7).
- Sie treten dem Thread in Ihrem einfachen Beispielcode nicht bei; Anruf
pthread_join(3)
vor dem Ende Ihres Programms:
After a canceled thread has terminated, a join with that
thread using pthread_join(3) obtains PTHREAD_CANCELED as the
thread's exit status. (Joining with a thread is the only way
to know that cancellation has completed.)
Das Abbrechen von pthreads bedeutet, dass der Thread keine Chance hat, den ihm zugewiesenen Speicher zu bereinigen.
– Lily Ballard
31. Oktober 2011 um 23:44 Uhr
Ok, ich habe das gelöst, indem ich einfach ein globales habe
keepalive=1
. Dann habe ich die geändertwhile(1)
zuwhile(keepalive)
. Um den Thread jetzt zu beenden, muss ich nur den Wert der Variable keepalive auf 0 ändern und voila!– Pithikos
3. November 2011 um 14:08 Uhr