Доброго времени суток господа. Возникла проблема следующего рода. Есть подпрограмма таймер и подпрограмма создающая окно при помощи xlib, в котором отображается отсчет таймера. Когда обе подпрограмма выполняются в потоке main - все замечательно отрабатывает, но - мне необходимо раскидать их по разным потокам. Естественно использую pthread. Так вот - при попытке это сделать - ловлю необъяснимый Interrupted system call. Точнее - уже объяснимый. Вообщем - отделаю таймер от формы и выполняю в потоке - все замечательно, все работает. Запихиваю форму в отдельный поток: Interrupted system call.
Таймер связан с формой следующим образом:
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();
}Обработка событий окна:
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, но как-то это не принесло дивидендов. А потому и спрашиваю вашего совета.
> и подпрограмма создающая окно при помощи xlib, в котором отображается отсчет
> таймера. Когда обе подпрограмма выполняются в потоке main - все замечательно
> отрабатывает, но - мне необходимо раскидать их по разным потокам. Естественно
> использую pthread.Посмотрите в "Xlib − C Language X Interface"
"Using Xlib with Threads"проверьте - собрана ли она у вас с поддержкой тредов.
>> и подпрограмма создающая окно при помощи xlib, в котором отображается отсчет
>> таймера. Когда обе подпрограмма выполняются в потоке main - все замечательно
>> отрабатывает, но - мне необходимо раскидать их по разным потокам. Естественно
>> использую pthread.
> Посмотрите в "Xlib − C Language X Interface"
> "Using Xlib with Threads"
> проверьте - собрана ли она у вас с поддержкой тредов.XInitThreads() - отрабатывает корректно, собрана с поддержкой.
> XInitThreads() - отрабатывает корректно, собрана с поддержкой.
> Пробовал через mutex заблокировать repaint, но как-то это не принесло дивидендов.Должно приносить.
Попробуйте локировать в window_repaint_send
через XLockDisplay/UnLockа что проиисходит в timer_get_message?
и зачем вы каждый раз создаете GC и выбираете фонты когда перерисовываете окно?
это, довольно, накладно.
>> XInitThreads() - отрабатывает корректно, собрана с поддержкой.
>> Пробовал через mutex заблокировать repaint, но как-то это не принесло дивидендов.
> Должно приносить.
> Попробуйте локировать в window_repaint_send
> через XLockDisplay/UnLock
> а что проиисходит в timer_get_message?
> и зачем вы каждый раз создаете GC и выбираете фонты когда перерисовываете
> окно?
> это, довольно, накладно.Попробую, спасибо. Но завтра.
Код timer_get_message()int timer_get_message(char *str)
{
int min = 0;if (timer_value <= 60)
{
min = 1;
}
else if (timer_value <= 180)
{
min = 3;
}
else if (timer_value <= 300)
{
min = 5;
}
else
{
return 0;
}sprintf(str, "Attention! Less than %i minutes!", min);
return 1;
}
>[оверквотинг удален]
> {
> min = 5;
> }
> else
> {
> return 0;
> }
> sprintf(str, "Attention! Less than %i minutes!", min);
> return 1;
> }XLockDispay и XUnlockDisplay помогли. Спасибо огромное.
> Код timer_get_message()я плохо знаю многопоточность, но, как я понимаю,
timer_get_message() и timer_callback у вас крутятся в разных тредах,
тогда работу с timer_value надо, то же, локировать,
например, при инкрементировании