Problem mit pthread_cond_timedwait

der_Kay

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

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;
}
 
Huhu,

ich vermute, dass abstime Dein Problem ist. Bin mir nicht sicher, aber hier muss wohl eine Zeit, keine Dauer angegeben werden, zumindest steht in man:

or if the system time reaches the time specified in abstime

Gruß
DeineMudda
 
Genau das ist die Ursache. Danke Dir! :)
 
Zurück
Oben Unten