der_Kay
Aktives Mitglied
Thread Starter
- Dabei seit
- 02.09.2004
- Beiträge
- 1.765
- Reaktionspunkte
- 25
Hallo zusammen,
ich habe beim Aufruf von pthread_cond_timedwait das Problem, dass die Funktion sofort mit ETIMEOUT zurückkehrt; egal was als tatsächlicher Timeout-Wert angegeben wird.
Untenstehender Code setzt einen Signalhandler für INTERRUPTED (= CTRL-C), startet einen Thread ("server") und pausiert dann. Beim Eintreffen eines SIGINT soll der Signalhandler durch Ändern einer globalen Variablen (g_i_server_run) die Server-Schleife beenden und dann auf die Condition (g_cond_t_stop) warten. Funktioniert erwartungsgemäß, wenn ohne timeout mit pthread_cond_wait gewartet wird; nur pthread_cond_timedwait wird irgendwie ignoriert.
Die Präprozessordirektiven _TIMEDWAIT, SECONDS_2_W8 und SHUTDOWN_DELAY steuern das Beenden des Threads und Anwedung: Wenn _TIMEDWAIT definiert ist, wird pthread_cond_timedwait zum Warten auf die Beendigung des Threads verwendet. Der Hauptthread wartet innerhalb des Signalhandlers SECONDS_2_W8 lang darauf, dass der Serverthread die Condition signalisiert. Der Serverthread tut das mit der Verzögerung SHUTDOWN_DELAY.
Wenn also SHUTDOWN_DELAY echt größer SECONDS_2_W8 gewählt wird, sollte schliesslich nach Ablauf der Wartezeit ein ETIMEOUT auftreten. Genau das passiert nicht.
Ich konnte keinen offensichtlichen Fehler in meinem Code finden; was mach ich verkehrt? Ist der Signalhandler das Problem? Habe mal herumgesucht und es scheint, dass pthread_cond_timedwait gern mal buggy ist...
Meine Umgebung:
sw_vers
ProductName: Mac OS X
ProductVersion: 10.4.7
BuildVersion: 8J135
gcc -v
Using built-in specs.
Target: powerpc-apple-darwin8
Configured with: /private/var/tmp/gcc/gcc-5247.obj~4/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --build=powerpc-apple-darwin8 --host=powerpc-apple-darwin8 --target=powerpc-apple-darwin8
Thread model: posix
gcc version 4.0.1 (Apple Computer, Inc. build 5247)
Vielen Dank fürs Draufschauen,
Kay
ich habe beim Aufruf von pthread_cond_timedwait das Problem, dass die Funktion sofort mit ETIMEOUT zurückkehrt; egal was als tatsächlicher Timeout-Wert angegeben wird.
Untenstehender Code setzt einen Signalhandler für INTERRUPTED (= CTRL-C), startet einen Thread ("server") und pausiert dann. Beim Eintreffen eines SIGINT soll der Signalhandler durch Ändern einer globalen Variablen (g_i_server_run) die Server-Schleife beenden und dann auf die Condition (g_cond_t_stop) warten. Funktioniert erwartungsgemäß, wenn ohne timeout mit pthread_cond_wait gewartet wird; nur pthread_cond_timedwait wird irgendwie ignoriert.
Die Präprozessordirektiven _TIMEDWAIT, SECONDS_2_W8 und SHUTDOWN_DELAY steuern das Beenden des Threads und Anwedung: Wenn _TIMEDWAIT definiert ist, wird pthread_cond_timedwait zum Warten auf die Beendigung des Threads verwendet. Der Hauptthread wartet innerhalb des Signalhandlers SECONDS_2_W8 lang darauf, dass der Serverthread die Condition signalisiert. Der Serverthread tut das mit der Verzögerung SHUTDOWN_DELAY.
Wenn also SHUTDOWN_DELAY echt größer SECONDS_2_W8 gewählt wird, sollte schliesslich nach Ablauf der Wartezeit ein ETIMEOUT auftreten. Genau das passiert nicht.
Ich konnte keinen offensichtlichen Fehler in meinem Code finden; was mach ich verkehrt? Ist der Signalhandler das Problem? Habe mal herumgesucht und es scheint, dass pthread_cond_timedwait gern mal buggy ist...
Meine Umgebung:
sw_vers
ProductName: Mac OS X
ProductVersion: 10.4.7
BuildVersion: 8J135
gcc -v
Using built-in specs.
Target: powerpc-apple-darwin8
Configured with: /private/var/tmp/gcc/gcc-5247.obj~4/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --build=powerpc-apple-darwin8 --host=powerpc-apple-darwin8 --target=powerpc-apple-darwin8
Thread model: posix
gcc version 4.0.1 (Apple Computer, Inc. build 5247)
Vielen Dank fürs Draufschauen,
Kay
PHP:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
/* Auskommentieren für unbegrenztes Warten */
/* #define _TIMEDWAIT */
/* Wartezeit */
#define SECONDS_2_W8 10
/* Server shutdown delay in Sekunden */
#define SHUTDOWN_DELAY 2
int g_i_server_run;
pthread_t g_pthread_t_server;
pthread_mutex_t g_mutex_t_run;
pthread_cond_t g_cond_t_stop;
#define __TEST_EXIT(cmd) if ( 0 != (errcode = (cmd))) { \
fprintf (stderr, "%s:%d:%s->%s\n", __FILE__, __LINE__,#cmd, \
strerror(errcode)); exit(1);}
void sigint_handler_shutdown( )
{
int errcode;
sigset_t mask_set;
struct timespec ts;
ts.tv_sec=SECONDS_2_W8;
ts.tv_nsec=0;
signal(SIGINT, sigint_handler_shutdown);
sigfillset(&mask_set);
sigprocmask(SIG_SETMASK, &mask_set, NULL);
/* shutdown http server */
g_i_server_run = 0;
fprintf( stdout, "shutdown server...");
fflush(stdout);
#ifdef _TIMEDWAIT
__TEST_EXIT(pthread_cond_timedwait (&g_cond_t_stop, &g_mutex_t_run, &ts ))
#else
__TEST_EXIT(pthread_cond_wait (&g_cond_t_stop, &g_mutex_t_run ))
#endif
fprintf(stdout, "ok.\n");
exit(0);
}
void* server_routine( void* p_arg )
{
int errcode;
while ( g_i_server_run )
{
printf(".");
fflush (stdout );
sleep( 1) ;
}
/* merklich verzögern */
sleep( SHUTDOWN_DELAY ) ;
__TEST_EXIT(pthread_cond_signal(&g_cond_t_stop));
return NULL;
}
int main (int argc, char** argv )
{
int errcode;
if( SIG_ERR == sigset(SIGINT, sigint_handler_shutdown))
{
fprintf( stderr, "%s: %d sigset(): %s.\n",
__FILE__, __LINE__, strerror(errno));
exit(1);
}
g_i_server_run = 1;
/* server mutex */
__TEST_EXIT(pthread_mutex_init(&g_mutex_t_run, NULL ));
/* condition */
__TEST_EXIT(pthread_cond_init(&g_cond_t_stop, NULL));
/* server mutex */
__TEST_EXIT(pthread_mutex_lock(&g_mutex_t_run));
/* start server */
fprintf(stdout, "start server...");
__TEST_EXIT(pthread_create(&g_pthread_t_server, NULL,
server_routine, NULL));
fprintf(stdout, "ok\n");
pause();
/* cleanup mutex & cond */
pthread_mutex_destroy( &g_mutex_t_run );
pthread_cond_destroy( &g_cond_t_stop );
return 0;
}