Sockets on Linux questionWake up thread blocked on accept() call
Tengo un hilo de trabajo bloqueado en una llamada a accept(). Simplemente espera una conexión de red entrante, la maneja y luego vuelve a escuchar la siguiente conexión.
Cuando es hora de que el programa salga, ¿cómo señalo este hilo de trabajo de red (desde el hilo principal) para regresar desde la llamada accept() mientras aún puedo salir fácilmente de su ciclo y manejar su código de limpieza .
Algunas cosas que me trataron:
pthread_kill para enviar una señal. Se siente demasiado optimista para hacer esto, además de que no permite de manera confiable que el hilo haga su lógica de apagado. También hace que el programa finalice también. Me gustaría evitar las señales si es posible.
pthread_cancel. Lo mismo que arriba. Es una muerte dura en el hilo. Eso, y el hilo puede estar haciendo otra cosa.
Cerrando el conector de escucha del hilo principal para hacer que accept() aborte. Esto no funciona de manera confiable.
Algunas limitaciones:
Si la solución consiste en hacer que la toma no bloqueante escucha, que está muy bien. Pero no quiero aceptar una solución que implique el inicio de subprocesos a través de una llamada de selección cada pocos segundos para verificar la condición de salida.
La condición del hilo para salir no puede estar vinculada al proceso de salida.
Básicamente, la lógica que busco es la siguiente.
void* WorkerThread(void* args)
{
DoSomeImportantInitialization(); // initialize listen socket and some thread specific stuff
while (HasExitConditionBeenSet()==false)
{
listensize = sizeof(listenaddr);
int sock = accept(listensocket, &listenaddr, &listensize);
// check if exit condition has been set using thread safe semantics
if (HasExitConditionBeenSet())
{
break;
}
if (sock < 0)
{
printf("accept returned %d (errno==%d)\n", sock, errno);
}
else
{
HandleNewNetworkCondition(sock, &listenaddr);
}
}
DoSomeImportantCleanup(); // close listen socket, close connections, cleanup etc..
return NULL;
}
void SignalHandler(int sig)
{
printf("Caught CTRL-C\n");
}
void NotifyWorkerThreadToExit(pthread_t thread_handle)
{
// signal thread to exit
}
int main()
{
void* ptr_ret= NULL;
pthread_t workerthread_handle = 0;
pthread_create(&workerthread, NULL, WorkerThread, NULL);
signal(SIGINT, SignalHandler);
sleep((unsigned int)-1); // sleep until the user hits ctrl-c
printf("Returned from sleep call...\n");
SetThreadExitCondition(); // sets global variable with barrier that worker thread checks on
// this is the function I'm stalled on writing
NotifyWorkerThreadToExit(workerthread_handle);
// wait for thread to exit cleanly
pthread_join(workerthread_handle, &ptr_ret);
DoProcessCleanupStuff();
}
'pthread_kill()' envía una señal a un hilo, nada más y nada menos. Y no necesariamente "* hace que el programa termine *". – alk
"* pthread_cancel. Lo mismo que arriba. *" Err, ¿qué? No, 'pthread_cancel()' hace algo completamente diferente a 'pthread_kill()'! Por favor, RTFM. – alk
Una forma fácil de obtener accept() para devolver sería abrir una conexión TCP al puerto en el que está escuchando la llamada accept(). –