Модераторы: xvr

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C]Потоки в linux, вопрос по pthread. 
V
    Опции темы
Alkash
Дата 14.3.2012, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Доброго времени суток господа, возникла небольшая проблема. Возможно с пониманием вопроса. Есть программа, которая слушает сокет - и при получении какой-либо информации - делает некие действия. Она выполняется в потоке main. Так же есть 2 подпрограммы: таймер и мордочка на xlib к нему, которые призваны - показывать отсчет времени, если на сокет придет необходимая директива с количеством времени. Подпрограммы имеют следующие методы:
Код

window_init();//создание окна
timer_init();//инициализация таймера
add_time_str("20");//установка времени
window_loop();// Обработка событий окна
window_destroy();

Если в данной последовательности выполнить их в main - то замечательно работает все, время добавляется, отсчитывается, отображается - красота. Однако - необходимо в main выполнять сокетную рутину, а эти методы засунуть в отдельный поток. В отдельный поток пытаюсь поместить следующим способом:
Код

void* initTimer(void* arg)
{
    window_init();
    timer_init();
    window_loop();
}

int main(){
pthread_t thread;
     sigset_t sigmask;
    int terror,arg;
    if( terror = pthread_create(&thread,NULL,initTimer,(void*)arg)) {
                        printf("Thread creation failed: %d\n", terror);
                    }
    pthread_sigmask(SIG_BLOCK,&sigmask,0);                
    //pthread_join (thread, NULL); 
//тут огромная куча кода, отлаженного и работающего

}
 И ловлю сегфолт. Если раскомментировать join - то сегфолт не ловлю, но соответственно - работает только таймер с мордочкой. Вопрос - каким образом мне заставить эти 2 подпрограммы работать в отдельном потоке, с возможностью вызова add_time_str?



--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
boostcoder
Дата 14.3.2012, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 16
Всего: 110



Цитата(Alkash @  14.3.2012,  16:33 Найти цитируемый пост)
(void*)arg)

Цитата(Alkash @  14.3.2012,  16:33 Найти цитируемый пост)
void* initTimer(void* arg)

arg нигде не используется?
PM WWW   Вверх
svlary
Дата 14.3.2012, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата(Alkash @  14.3.2012,  16:33 Найти цитируемый пост)
Если раскомментировать join - то сегфолт не ловлю
 - Но ведь это означает, что сигфолт у Вас ЗА (!!!) joint...
А точнее, вот здесь : 

Цитата
//тут огромная куча кода, отлаженного и работающего


Ну и повтыкайте там кучу контрольных печатей, что бы выяснить более детально - где именно сигфолт происходит... А насчет "отлаженного и работающего|" - не надо так горячиться! ;-)
PM MAIL   Вверх
Alkash
Дата 15.3.2012, 08:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Да нет же-)) Сегфолт - происходит, либо из-за необработки какого-то сигнала, либо - из-за window_loop. Потому как после - там идет чтение и разбор конфига, создание и обслуживание сокета, etc.
Собственно таймер:
Код

#include "stdio.h"
#include "stdlib.h"
#include "signal.h"
#include "sys/time.h"
#include "time.h"
#include "timer.h"
#include "window.h"

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();
}

void timer_str(char *str)
{
    int hour, min, sec;

    if (timer_value)
    {
        hour = timer_value / 3600;
        min = timer_value % 3600 / 60;
        sec = timer_value % 3600 - min * 60;
    }
    else
    {
        time_t t = time(NULL);

        struct tm *lt = localtime(&t);

        hour = lt->tm_hour;
        min = lt->tm_min;
        sec = lt->tm_sec;
    }

    sprintf(str, "%.2i:%.2i:%.2i", hour, min, sec);
}

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

void timer_add_time(char *min_str)
{
    int sec = (int)(atof(min_str) * 60);

    timer_value += sec;
}


метод window_loop:
Код

void window_loop()
{
    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;
        }
        }
    }
}
//ну и repaint
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);
}


Это сообщение отредактировал(а) Alkash - 15.3.2012, 08:11


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 15.3.2012, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Соберите программу с отладочной информацией и запуститесь под gdb. Посмотрите, где происходит SIGSEGV

Цитата(Alkash @  14.3.2012,  16:33 Найти цитируемый пост)
 Вопрос - каким образом мне заставить эти 2 подпрограммы работать в отдельном потоке, с возможностью вызова add_time_str?

Кстати, и где ее (add_time_str) код?

PM MAIL   Вверх
Alkash
Дата 15.3.2012, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Метод называется: timer_add_time, приведен выше-)
 
Прикрутил поток обработки сигналов,
Код




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, и главное - как это победить?

Это сообщение отредактировал(а) Alkash - 15.3.2012, 15:03


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 15.3.2012, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(Alkash @  15.3.2012,  10:26 Найти цитируемый пост)
- теперь известно, что все падает вот тут

'Вот тут' - это где? У вас там почти 40 строк. На какой строке падает?

PM MAIL   Вверх
Alkash
Дата 15.3.2012, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Код

timer_str(timer_message);

Прям вот в этой месте.

Добавлено через 1 минуту и 26 секунд
Второе падение - при вызове window_repaint_send(),
в строке XSendEvent(display, window, 0, ExposureMask, (XEvent *) &expose);.


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
svlary
Дата 15.3.2012, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата(Alkash @  15.3.2012,  08:07 Найти цитируемый пост)
Сегфолт - происходит

Если под "Сегфолт" Вы понимаете :

SIGSEGV         11      /* Segmentation violation (ANSI).  */

То происходит оно по одной-единственной причине : Ошибка адресации, вызванная некорректным указателем или некорректным индексом массива. 
И все ! Больше никаких причин нет и быть не может.
Но, не так уж и важно, чем вызвано прерывание. А важно - ГДЕ оно возникает.

А теперь, смотрим на Ваш код : Когда срабатывает вызов pthread_joint(...), он НЕ ПУСКАЕТ поток управления через себя. И прерывание не происходит.
Когда Вы комментарите вызов  pthred_joint , поток управления проходит сквозь него и натыкается на ОШИБКУ В ПРОГРАММЕ, приводящую к прерыванию и
расположенную НИЖЕ этого вызова. 
PM MAIL   Вверх
Alkash
Дата 15.3.2012, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Цитата

А теперь, смотрим на Ваш код : Когда срабатывает вызов pthread_joint(...), он НЕ ПУСКАЕТ поток управления через себя. И прерывание не происходит.
Когда Вы комментарите вызов  pthred_joint , поток управления проходит сквозь него и натыкается на ОШИБКУ В ПРОГРАММЕ, приводящую к прерыванию и
расположенную НИЖЕ этого вызова. 

Однако - если удалить строки с потоком - то никакого сигфолта. Сокет создается, слушается, принимает - отдает. Я чего-то видимо упускаю...


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
Alkash
Дата 16.3.2012, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



обедив прошлую проблему с помощью XLockDisplay, XUnlockDisplay. Таймер бодренько отрабатывает, окошко бодренько прорисовывается. Но где-то я косякнул, и - работают только потоки.
Код

int make_socket (uint16_t port){
    int sock;
    struct sockaddr_in name;
    sock = socket (AF_INET, SOCK_STREAM, 0);
    if (sock < 0){
        perror ("socket");
        exit (EXIT_FAILURE);
    }
    name.sin_family = AF_INET;
    name.sin_port = htons (port);
    name.sin_addr.s_addr = htonl (INADDR_ANY);
    if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
        {
            perror ("bind");
            exit (EXIT_FAILURE);
        }
    return sock;
}

int parseCommand(char *cmd){
  Display *dsp;
  Window wnd;
  char *param, *value;
  param = strtok(cmd, "/");
  value = strtok(NULL, "/");
 if (strcmp(param, "cmd")==0)
  {
      if (strcmp(value, "start")==0)// cmd/start/
      {
          printf("%s\n", value);
         unlockDisplay(&dsp,&wnd);
    // Добавляем время
    //       timer_add_time("0.01");
      }
      else if (strcmp(value, "exit")==0) // cmd/exit/
           {
            //printf("%s\n", value);
            if(blockDisplay(&dsp,&wnd) < 0){
                fprintf(stderr,"Cannot open Display\n");
                exit(-1);
            }
           }
      else if (strcmp(value, "block")==0) // cmd/block/
           {
            printf("%s\n", value);
            if(blockDisplay(&dsp,&wnd) < 0){
                fprintf(stderr,"Cannot open Display\n");
                exit(-1);
            }
           }
 }
  else if (strcmp(param, "settime")==0) // settime/60/ (settime/количество минут)
        {
           //printf("%s\n", value);
           unlockDisplay(&dsp,&wnd);
        //   window_init();
    // Добавляем время
          timer_add_time(value);
    
        }
return 0;
    //return(0);
}

int read_from_client (int filedes){
    char buffer[MAXMSG];
    int nbytes;
    nbytes = read (filedes, buffer, MAXMSG);
    if (nbytes < 0){
        perror ("read");
        exit (EXIT_FAILURE);
    }
    else if (nbytes == 0)
        return -1;
    else{
        buffer[nbytes-1] = '\0';
        parseCommand(buffer);
        return 0;
    }
}

int main()
{    
extern int make_socket (uint16_t port);
    int sock;
    fd_set active_fd_set, read_fd_set;
    int i;
    struct sockaddr_in clientname;
    size_t size;
    uint16_t PORT;
    pthread_t tthread,wthread;
    pthread_t sthread;
     sigset_t sigmask;
    int tterror,wterror,arg,arg1;
    int sign;
    if ( sign = pthread_create(&sthread,NULL,checkSignal,NULL)!= 0){
        printf("TThread creation failed: %d\n", sign);
    }
    if( wterror = pthread_create(&wthread,NULL,initWindow,(void*)arg1)) {
                        printf("TThread creation failed: %d\n", wterror);
                    }
    pthread_sigmask(SIG_BLOCK,&sigmask,0); 
    if( tterror = pthread_create(&tthread,NULL,initTimer,(void*)arg)) {
                        printf("TThread creation failed: %d\n", tterror);
                    }
//    pthread_sigmask(SIG_BLOCK,&sigmask,0);    
    
                    
    //pthread_join (thread, NULL); 
    struct ccafe_params parms;
    printf ("Initializing parameters to default values...\n");
    init_parameters (&parms);
    printf ("Reading config file...\n");
    parse_config (&parms);
    printf ("Final values:\n");
    printf ("port: %s, MSG: %s\n", parms.port,parms.MMSG);
    MAXMSG = atoi(parms.MMSG);
    PORT = atoi(parms.port);
    sock = make_socket(PORT);
   // printf ("sock: %s",(char*)sock);
    if (listen (sock, 1) < 0){
        perror ("listen");
        exit (EXIT_FAILURE);
    }
    FD_ZERO (&active_fd_set);
    FD_SET (sock, &active_fd_set);
    while (1){
        read_fd_set = active_fd_set;
        if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0){
            perror ("select");
            exit (EXIT_FAILURE);
        }
        for (i = 0; i < FD_SETSIZE; ++i)
            if (FD_ISSET (i, &read_fd_set)){
                if (i == sock){
                    int new;
                    size = sizeof (clientname);
                    new = accept (sock,(struct sockaddr *) &clientname,&size);
                    if (new < 0){
                        perror ("accept");
                        exit (EXIT_FAILURE);
                    }
                //    fprintf (stderr,"Server: connect from host %s, port %hd.\n",inet_ntoa (clientname.sin_addr),ntohs (clientname.sin_port));
                    FD_SET (new, &active_fd_set);
                }
                else{

                    if (read_from_client (i) < 0){
                        close (i);
                        FD_CLR (i, &active_fd_set);
                    }
                }
            }
    }
    for(;;)  {}
    //pthread_join (sthread, NULL); 
  return 0;
}


Сокет - создается, слушается. Но - ничего не принимает, второе приложение - с ним соединяется - и все. Не ответа, ни привета. В чем может быть затык?


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 16.3.2012, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(Alkash @  15.3.2012,  16:08 Найти цитируемый пост)
Прям вот в этой месте.

Тут падать не на чем

Цитата(Alkash @  15.3.2012,  16:08 Найти цитируемый пост)
Второе падение - при вызове window_repaint_send(),
в строке XSendEvent(display, window, 0, ExposureMask, (XEvent *) &expose);. 

Проверьте, что вы передаете в expose. И попробуйте сделать эту переменную статической (на всякий случай)

Цитата(Alkash @  16.3.2012,  10:07 Найти цитируемый пост)
Сокет - создается, слушается. Но - ничего не принимает,

Замысловато у вас подключение и чтение сокетов сделано. accept срабатывает?

PM MAIL   Вверх
Alkash
Дата 16.3.2012, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Цитата(xvr @ 16.3.2012,  10:58)
Цитата(Alkash @  15.3.2012,  16:08 Найти цитируемый пост)
Прям вот в этой месте.

Тут падать не на чем

Цитата(Alkash @  15.3.2012,  16:08 Найти цитируемый пост)
Второе падение - при вызове window_repaint_send(),
в строке XSendEvent(display, window, 0, ExposureMask, (XEvent *) &expose);. 

1) Проверьте, что вы передаете в expose. И попробуйте сделать эту переменную статической (на всякий случай)

Цитата(Alkash @  16.3.2012,  10:07 Найти цитируемый пост)
Сокет - создается, слушается. Но - ничего не принимает,

2) Замысловато у вас подключение и чтение сокетов сделано. accept срабатывает?

1) Проблема была во множественном подключении к display. Мне помог XLockDisplay XUnlockDisplay.

2) Отрабатывает, но...Спустя длительное время. Например отправил на сокет 
Код

byte[] data = Encoding.UTF8.GetBytes("cmd/block/");
                int sent = client.Send(data);
 - с пару минут ничего не происходило, затем - внезапно отработал код.
При том, что если потоки снести из main, то сокетная часть работает на ура.

Это сообщение отредактировал(а) Alkash - 16.3.2012, 11:14


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 16.3.2012, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(Alkash @  16.3.2012,  11:13 Найти цитируемый пост)
- с пару минут ничего не происходило, затем - внезапно отработал код.
При том, что если потоки снести из main, то сокетная часть работает на ура.

Странно. А у вас никакой поток случайно 100% CPU не съел? 
И еще попробуйте убрать pthread_sigmask, может с сигналами что то не то (хотя на сокеты они влиять не должны)

PM MAIL   Вверх
Alkash
Дата 16.3.2012, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



В system monitor висит как в ожидании, памяти отжирает 240 килобайт. В top - 80% проца свободно. На всякий случай привожу полный код window.c и timer.c
window.c
Код

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "timer.h"
#include "window.h"
#include "X11/Xlib.h"
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/xpm.h>
#include "ccafe.xpm"
#include "Locked.xpm"
#include "pthread.h"
//объявляем переменные-с для блокировщика
Window root,wnd,logo,logo2;
int x,y,dW,dH;
int running = 0;
char *background = NULL;

// Соединение с сервером
Display *display;

// Окно
Window window;

// Ширина и высота окна
int window_width    = 80;
int window_height    = 30;

void* initWindow(void* arg)
{
    //pthread_t lthread;
    int ret;
    //pthread_attr_t tattr;
    XInitThreads();
    window_init();
    printf("Window Thread\n");
    window_loop();
 //   ret = pthread_attr_init(&tattr); 
//    ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);

//    if( ret = pthread_create(&lthread, &tattr,window_loop , NULL) != 0) {
  //  printf("TThread creation failed: %d\n", ret);
 // }
}

void window_init()
{
    display = XOpenDisplay(NULL);
    if (display == NULL)
    {
        exit(EXIT_FAILURE);
    }

    int screen_number = DefaultScreen(display);

    int display_width = DisplayWidth(display, screen_number);
    int display_height = DisplayHeight(display, screen_number);

    int window_pos_x = display_width - window_width;
    int window_pos_y = display_height - window_height;
    XLockDisplay(display);
    window = XCreateSimpleWindow(display, RootWindow(display, screen_number),
            window_pos_x, window_pos_y, window_width, window_height, 0,
            BlackPixel(display, screen_number),WhitePixel(display, screen_number));
    //window = XCreateWindow(display, RootWindow(display, screen_number),
        //                window_pos_x, window_pos_y, window_width, window_height, 0,
         //               CopyFromParent,CopyFromParent,CopyFromParent,0, 0);

    XSelectInput(display, window, ExposureMask/* | ResizeRedirectMask*/);
    //XRaiseWindow(display, window);

    SetNoBorder(display, window,RootWindow(display, screen_number));

    //убираемся из панели задач и pager
    Atom a = XInternAtom(display, "_NET_WM_STATE", True);
    if (a != None) {
    Atom prop = XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", True);
    XChangeProperty(display, window, a, XA_ATOM, 32, PropModeAppend, (unsigned char *) &prop, 1);
    Atom prop1 = XInternAtom(display, "_NET_WM_STATE_SKIP_PAGER", True);
    XChangeProperty(display, window, a, XA_ATOM, 32, PropModeAppend, (unsigned char *) &prop1, 1);
    Atom prop2 = XInternAtom(display, "_NET_WM_STATE_ABOVE", True);
    XChangeProperty(display, window, a, XA_ATOM, 32, PropModeAppend, (unsigned char *) &prop2, 1);
    }
    XMapWindow(display, window);
    XStoreName(display, window, "CCafe");
    XMoveWindow(display, window, display_width, display_height);
    XUnlockDisplay(display);
    XFlush(display);
}
//убираем к хуям рамочки вокруг окна.

void SetNoBorder(Display *dpy, Window win, Window root)
{ int set = 0;
  Atom WM_HINTS;
  WM_HINTS = XInternAtom(dpy, "_MOTIF_WM_HINTS", True);
  if(WM_HINTS != None)
  {
    struct
    { unsigned long flags;
      unsigned long functions;
      unsigned long decorations;
      long input_mode;
      unsigned long status;
    } MWMHints = { (1L << 1), 0, 0, 0, 0 };

    XChangeProperty(dpy, win, WM_HINTS, WM_HINTS, 32,
                    PropModeReplace, (unsigned char *)&MWMHints,
                    sizeof(MWMHints)/sizeof(long));
    set = 1;
  }
  WM_HINTS = XInternAtom(dpy, "KWM_WIN_DECORATION", True);
  if(WM_HINTS != None)
  { long KWMHints = 0;

    XChangeProperty(dpy, win, WM_HINTS, WM_HINTS, 32,
                    PropModeReplace, (unsigned char *)&KWMHints,
                    sizeof(KWMHints)/sizeof(long));
    set = 1;
  }

  WM_HINTS = XInternAtom(dpy, "_WIN_HINTS", True);
  if(WM_HINTS != None)
  { long GNOMEHints = 0;

    XChangeProperty(dpy, win, WM_HINTS, WM_HINTS, 32,
                    PropModeReplace, (unsigned char *)&GNOMEHints,
                    sizeof(GNOMEHints)/sizeof(long));
    set = 1;
  }
  if(! set)
    XSetTransientForHint(dpy, win, root);
}
//ну-с...блокировка экрана
int blockDisplay (Display **dsp,Window *wnd1)
{
    XSetWindowAttributes attr,attr1,attr2;
    Pixmap shape,pic,lock,shp, bg_pic, bg_shp;
    unsigned long white;
    int snumber = 0;
    long win_mask = CWBackPixel|CWBorderPixel|CWOverrideRedirect;
if(running == 1)
    return 0;
    running = 1;
    x=5;
    y=35;
    (*dsp) = XOpenDisplay(0);
    if((*dsp) == NULL)
        return(-1);
    //dsp = XOpenDisplay(getenv("DISPLAY"));
    dW = XDisplayWidth(*dsp,snumber);
    dH = XDisplayHeight(*dsp,snumber);
    root = XRootWindow(*dsp,snumber);

    if(background != NULL)
      {
        if(XpmReadFileToPixmap(*dsp,root,background,&bg_pic,&bg_shp,NULL) != XpmOpenFailed)
          win_mask = CWBackPixmap|CWBorderPixel|CWOverrideRedirect;
      }
    white = XWhitePixel(*dsp,0);
    attr.background_pixel =white ;
    attr.background_pixmap = bg_pic;
    attr.border_pixel = 100;
    attr.override_redirect = True;
    XLockDisplay(*dsp);
    (*wnd1) = XCreateWindow(*dsp, root, 0, 0, dW, dH,0,
         CopyFromParent, CopyFromParent,CopyFromParent,
         win_mask
        ,&attr);
    XMapRaised(*dsp,*wnd1);

    XpmCreatePixmapFromData(*dsp,*wnd1,ccafe_xpm,&pic,&shape,NULL);
    attr1.background_pixel =white ;
    attr1.background_pixmap = pic;
    logo = XCreateWindow(*dsp,*wnd1,dW-150,0,150,30,0,CopyFromParent,CopyFromParent,CopyFromParent,CWBackPixmap,&attr1);
    XMapWindow(*dsp,logo);
    //logo2 = XCreateSimpleWindow(*dsp, *wnd1, 0, 0, dW-150, 30, 0, 0,300);
    //XMapWindow(*dsp,logo2);

    XpmCreatePixmapFromData(*dsp,*wnd1,Locked_xpm,&lock,&shp,NULL);
    attr2.background_pixmap = lock;
    wnd = XCreateWindow(*dsp,*wnd1,dW/4+20,dH/4,600,600,0,CopyFromParent,CopyFromParent,CopyFromParent,CWBackPixmap,&attr2);
    //wnd = XCreateSimpleWindow(*dsp, *wnd1, x, y, 200, 200, 1, 0, 400);
    XMapWindow(*dsp,wnd);

    XGrabPointer(*dsp,*wnd1,False,ButtonPressMask|ButtonReleaseMask|PointerMotionMask,GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
    XGrabKeyboard(*dsp,*wnd1,False,GrabModeAsync,GrabModeAsync,CurrentTime);
    XSelectInput(*dsp,*wnd1,KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask);
    XUnlockDisplay(*dsp);
    return(0);
}

//разблокируем дисплей
int unlockDisplay(Display **dsp,Window *wnd1){
    if(running == 1){
        XLockDisplay(*dsp);
        XDestroyWindow(*dsp,*wnd1);
        XUnlockDisplay(*dsp);
        XCloseDisplay(*dsp);
        running = 0;
    }
    return(0);
}

void window_destroy()
{
    XDestroyWindow(display, window);
    XCloseDisplay(display);
}

void window_loop()
{
    int ret;
    XEvent event;
    for (;;)
    {
    //    printf("Loop Thread\n");
    XLockDisplay(display);
        XNextEvent(display, &event);
    XUnlockDisplay(display);    
        switch (event.type)
        {
        case Expose:
        {
            window_repaint();
        //    printf("Loop Thread_1\n");
            break;
        }
        case ResizeRequest:
        {
            XResizeRequestEvent *resize = (XResizeRequestEvent *) &event;

            window_width = resize->width;
            window_height = resize->height;
           // printf("Loop Thread_2\n");
            break;
        }
        default:
        {
            break;
        }
        }
    }
}

void window_repaint_send()
{
    XExposeEvent expose = { Expose, 0, 1, display, window, 0, 0, window_width, window_height, 0 };
    XLockDisplay(display);
    XSendEvent(display, window, 0, ExposureMask, (XEvent *) &expose);
    XUnlockDisplay(display);
    //printf("repaint_send\n");
    XFlush(display);
}

void window_repaint()
{
  //  printf("repaint\n");
  XLockDisplay(display);
    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));
    }
    XUnlockDisplay(display);

    XFreeGC(display, gc);
}



timer.c
Код

#include "stdio.h"
#include "stdlib.h"
#include "signal.h"
#include "sys/time.h"
#include "time.h"
#include "timer.h"
#include "window.h"


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();
}

void timer_str(char *str)
{
    int hour, min, sec;

    if (timer_value)
    {
        hour = timer_value / 3600;
        min = timer_value % 3600 / 60;
        sec = timer_value % 3600 - min * 60;
    }
    else
    {
        time_t t = time(NULL);

        struct tm *lt = localtime(&t);

        hour = lt->tm_hour;
        min = lt->tm_min;
        sec = lt->tm_sec;
    }

    sprintf(str, "%.2i:%.2i:%.2i", hour, min, sec);
}

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

void timer_add_time(char *min_str)
{
    int sec = (int)(atof(min_str) * 60);

    timer_value += sec;
}




--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 16.3.2012, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Пока вижу только, что window_repaint_send будет блокироваться (из за XLockDisplay), пока в ваше окно не свалится какой нибудь event.
И будет это происходить внутри обработчика сигнала. Вполне может все повиснуть


PM MAIL   Вверх
Alkash
Дата 16.3.2012, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Спасибо, убрал XLock\XUnlock из window_repaint_send win_loop - заработало.

Добавлено через 8 минут и 19 секунд
Рано порадовался-))) Теперь первое обращение к сокету - замечательно, работает. А вот второго уже дождаться не суждено. В связи с чем экран блокируется, ну и уже не разблокируется.


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 16.3.2012, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(Alkash @  16.3.2012,  12:10 Найти цитируемый пост)
Теперь первое обращение к сокету - замечательно, работает. А вот второго уже дождаться не суждено.

У вас сокет не закрывается (shutdown + close), а очередь вы себе заказали на 1 сокет (2й параметр в listen). Вот они больше и не подсоединяются

PM MAIL   Вверх
Alkash
Дата 16.3.2012, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Он закрываться должен - с выходом из приложения. Я к нему присоединяюсь из клиента, отсылаю необходимое - и клиентом отсоединяюсь до следующего коннекта. В принципе - работает. Но - когда я вызываю 
Код

blockDisplay();

 - после этого он не реагирует. При этом если отправить команды вызова unblockDisplay() или назчения времени - то все в порядке, принимает - отправляет. Чую - что где-то тут корень всех моих бед.


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
Alkash
Дата 16.3.2012, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



Выхлоп valgrind:
Код

Timer Thread
Initializing parameters to default values...
--2146-- REDIR: 0x421d8e0 (strncpy) redirected to 0x4029217 (strncpy)
Reading config file...
--2146-- REDIR: 0x421d890 (strncmp) redirected to 0x4022499 (_vgnU_ifunc_wrapper)
--2146-- REDIR: 0x42c7b30 (__strncmp_ssse3) redirected to 0x4029449 (strncmp)
--2146-- REDIR: 0x421e7c0 (memset) redirected to 0x4022499 (_vgnU_ifunc_wrapper)
--2146-- REDIR: 0x42bd370 (__memset_sse2) redirected to 0x402aa22 (memset)
--2146-- REDIR: 0x421e230 (memchr) redirected to 0x4029b00 (memchr)
--2146-- REDIR: 0x421d0d0 (strcpy) redirected to 0x402907b (strcpy)
==2146== Source and destination overlap in strcpy(0xbefa9f5c, 0xbefa9f5c)
==2146==    at 0x4029139: strcpy (mc_replace_strmem.c:311)
==2146==    by 0x804ADE4: trim (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x804AEF2: parse_config (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x80499CB: main (in /home/cynic/CCafe/CClient_/cclient)
==2146== 
value: 9030
--2146-- REDIR: 0x421e700 (memmove) redirected to 0x4022499 (_vgnU_ifunc_wrapper)
--2146-- REDIR: 0x42c0370 (__memmove_ssse3) redirected to 0x402aab3 (memmove)
--2146-- REDIR: 0x4219d20 (realloc) redirected to 0x40288a0 (realloc)
--2146-- REDIR: 0x421d620 (strlen) redirected to 0x4022499 (_vgnU_ifunc_wrapper)
--2146-- REDIR: 0x4224010 (__strlen_sse2_bsf) redirected to 0x402900f (strlen)
Final values:
port: 9030, MSG: 512
Window Thread
--2146-- REDIR: 0x421d060 (__GI_strcmp) redirected to 0x4029a0a (__GI_strcmp)
--2146-- REDIR: 0x421fe30 (rawmemchr) redirected to 0x402abd0 (rawmemchr)
Server: connect from host 127.0.0.1, port -18981.
block
--2146-- REDIR: 0x421eba0 (strcasecmp) redirected to 0x4029518 (strcasecmp)
--2146-- Reading syms from /usr/lib/i386-linux-gnu/libXcursor.so.1.0.2 (0x4030000)
--2146--   Considering /usr/lib/i386-linux-gnu/libXcursor.so.1.0.2 ..
--2146--   .. CRC mismatch (computed 27b8283e wanted cf02d89f)
--2146--    object doesn't have a symbol table
--2146-- Reading syms from /usr/lib/i386-linux-gnu/libXrender.so.1.3.0 (0x5f6c000)
--2146--   Considering /usr/lib/i386-linux-gnu/libXrender.so.1.3.0 ..
--2146--   .. CRC mismatch (computed ca4b965a wanted ab7c529f)
--2146--    object doesn't have a symbol table
--2146-- Reading syms from /usr/lib/i386-linux-gnu/libXfixes.so.3.1.0 (0x403b000)
--2146--   Considering /usr/lib/i386-linux-gnu/libXfixes.so.3.1.0 ..
--2146--   .. CRC mismatch (computed 966dfda3 wanted 7165e6b6)
--2146--    object doesn't have a symbol table
--2146-- REDIR: 0x421cea0 (index) redirected to 0x4028bc7 (index)
--2146-- REDIR: 0x421e3d0 (bcmp) redirected to 0x4022499 (_vgnU_ifunc_wrapper)
--2146-- REDIR: 0x42c9520 (__memcmp_ssse3) redirected to 0x402a64c (bcmp)
--2146-- REDIR: 0x421d010 (strcmp) redirected to 0x4022499 (_vgnU_ifunc_wrapper)
--2146-- REDIR: 0x42c66c0 (__strcmp_ssse3) redirected to 0x40299b8 (strcmp)
==2146== Syscall param writev(vector[...]) points to uninitialised byte(s)
==2146==    at 0x42711A5: writev (writev.c:56)
==2146==    by 0x40004: ???
==2146==  Address 0x4b7fe42 is 66 bytes inside a block of size 16,384 alloc'd
==2146==    at 0x402732C: calloc (vg_replace_malloc.c:467)
==2146==    by 0x406A551: XOpenDisplay (in /usr/lib/i386-linux-gnu/libX11.so.6.3.0)
==2146==    by 0x804A261: blockDisplay (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x804958F: parseCommand (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049788: read_from_client (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049C67: main (in /home/cynic/CCafe/CClient_/cclient)
==2146== 
start
==2146== Use of uninitialised value of size 4
==2146==    at 0x4058524: XDestroyWindow (in /usr/lib/i386-linux-gnu/libX11.so.6.3.0)
==2146==    by 0x80494CB: parseCommand (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049788: read_from_client (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049C67: main (in /home/cynic/CCafe/CClient_/cclient)
==2146== 
==2146== Invalid read of size 4
==2146==    at 0x4058524: XDestroyWindow (in /usr/lib/i386-linux-gnu/libX11.so.6.3.0)
==2146==    by 0x80494CB: parseCommand (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049788: read_from_client (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049C67: main (in /home/cynic/CCafe/CClient_/cclient)
==2146==  Address 0x4d0 is not stack'd, malloc'd or (recently) free'd
==2146== 
==2146== 
==2146== Process terminating with default action of signal 11 (SIGSEGV)
==2146==  Access not within mapped region at address 0x4D0
==2146==    at 0x4058524: XDestroyWindow (in /usr/lib/i386-linux-gnu/libX11.so.6.3.0)
==2146==    by 0x80494CB: parseCommand (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049788: read_from_client (in /home/cynic/CCafe/CClient_/cclient)
==2146==    by 0x8049C67: main (in /home/cynic/CCafe/CClient_/cclient)




--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
xvr
Дата 16.3.2012, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Может ему не нравится что вы открываете дисплей (XOpenDisplay) несколько раз?

PM MAIL   Вверх
Alkash
Дата 16.3.2012, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


коллекционер жизни
**


Профиль
Группа: Участник
Сообщений: 516
Регистрация: 5.7.2004
Где: /

Репутация: нет
Всего: нет



О...а ведь точно-) Не заметил-) Спасибо!


--------------------
Подпись >> /dev/null
PM MAIL ICQ MSN   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0854 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.