И так...загоняю таймер в поток:void* initTimer(void* arg)
{
timer_init();
printf("Timer Thread\n");
}
int timer_value;
void timer_init()
{
signal(SIGALRM, &timer_callback);
struct timeval interval = { 1, 0 };
struct timeval value = { 1, 0 };
struct itimerval timerval;
timerval.it_interval = interval;
timerval.it_value = value;
setitimer(ITIMER_REAL, &timerval, 0);
}
void timer_callback(int sign)
{
if (timer_value > 0)
{
timer_value--;
}
window_repaint_send();
}
*****
pthread_t tthread;
int tterror,arg;
if( tterror = pthread_create(&tthread,NULL,initTimer,(void*)arg)) {
printf("TThread creation failed: %d\n", tterror);
}
*****
Когда окно в основном потоке, таймер в дополнительном - замечательно все.
Затем, вывожу окно в другой поток. И на уровне window_loop - получаю Interrupted system call.
Код window_loop() с необходимыми методами:
void window_loop()
{
int ret;
XEvent event;
for (;;)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
{
window_repaint();
break;
}
case ResizeRequest:
{
XResizeRequestEvent *resize = (XResizeRequestEvent *) &event;
window_width = resize->width;
window_height = resize->height;
break;
}
default:
{
break;
}
}
}
}
void window_repaint_send()
{
XExposeEvent expose = { Expose, 0, 1, display, window, 0, 0, window_width, window_height, 0 };
XSendEvent(display, window, 0, ExposureMask, (XEvent *) &expose);
XFlush(display);
}
void window_repaint()
{
XClearArea(display, window, 0, 0, window_width, window_height, 0);
XFontStruct *font = XLoadQueryFont(display, "10x20");
if (!font)
{
exit(EXIT_FAILURE);
}
GC gc = XCreateGC(display, window, 0, NULL);
XSetFont(display, gc, font->fid);
char timer_message[100];
timer_str(timer_message);
int timer_message_pos_x = window_width / 2 - XTextWidth(font, timer_message, strlen(timer_message)) / 2;
int timer_message_pos_y = window_height / 2 ;
XDrawString(display, window, gc, timer_message_pos_x, timer_message_pos_y, timer_message, strlen(timer_message));
char attention_message[100];
if (timer_get_message(attention_message))
{
int attention_message_pos_x = window_width / 2 - XTextWidth(font, attention_message, strlen(attention_message)) / 2;
int attention_message_pos_y = window_height / 2 + 30;
XDrawString(display, window, gc, attention_message_pos_x, attention_message_pos_y, attention_message, strlen(attention_message));
}
XFreeGC(display, gc);
}
Догадываюсь, что проблема в недрах window_loop, при обращении таймера к window_repaint_send и соответственным вызовом window_repaint. Пробовал через mutex заблокировать repaint, и вызывать его из таймера по готовности, но как-то это не принесло дивидендов. Видимо я как-то неправильно обрабатываю евент Expose, пробовал loop вынести в отдельный поток - получил segfault. Вообщем - я что-то делаю определенно неправильно, но что - понять не могу.
Пользователь решил продолжить мысль 15 Марта 2012, 15:55:49:
Прикрутил поток обработки сигналов,
void* checkSignal()
{
sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGALRM);
//sigthreadmask(SIG_BLOCK, &set, NULL);
pthread_sigmask(SIG_BLOCK, &set, NULL);
while (1) {
sigwait(&set, &sig);
switch (sig) {
case SIGINT:
/* обработка прерываний */
break;
case SIGQUIT:
/* обработка выхода */
break;
case SIGTERM:
/* обработка завершения */
break;
case SIGALRM:
/* обработка сигналов*/
timer_callback(sig);
break;
default:
/* сигнал, отличный от ожидаемого */
pthread_exit((void *)-1);
}
}
}
- теперь известно, что все падает вот тут:
void window_repaint()
{
printf("repaint\n");
XClearArea(display, window, 0, 0, window_width, window_height, 0);
XFontStruct *font = XLoadQueryFont(display, "10x20");
if (!font)
{
exit(EXIT_FAILURE);
}
GC gc = XCreateGC(display, window, 0, NULL);
XSetFont(display, gc, font->fid);
char timer_message[100];
timer_str(timer_message);
int timer_message_pos_x = window_width / 2 - XTextWidth(font, timer_message, strlen(timer_message)) / 2;
int timer_message_pos_y = window_height / 2 ;
XDrawString(display, window, gc, timer_message_pos_x, timer_message_pos_y, timer_message, strlen(timer_message));
char attention_message[100];
if (timer_get_message(attention_message))
{
int attention_message_pos_x = window_width / 2 - XTextWidth(font, attention_message, strlen(attention_message)) / 2;
int attention_message_pos_y = window_height / 2 + 30;
XDrawString(display, window, gc, attention_message_pos_x, attention_message_pos_y, attention_message, strlen(attention_message));
}
XFreeGC(display, gc);
}
Вопрос - на чем оно тут может гипотетически падать с interrupt system call, и главное - как это победить?