неправильное использование pthread для ожидания ответа сокетов - PullRequest
0 голосов
/ 19 апреля 2020

моя основная функция выглядит так:

void create_serv_and_init_client(client_t *cl)
{
    static int i = 0;
    pthread_t thread_serv;
    serv_t serv;

    if (i == 0) {
        //cl[0].content = retrieve_info();
        cl[0].connected = 1;
        //PORT = cl[0].content.port;
        serv = create_serv_socket();
        if (pthread_create(&thread_serv, NULL, waiting_connection, \
        (void *)&serv) < 0) {
            perror("could not create thread");
            exit(1);
        }
        cl[0] = create_client(0);
        printf("OK\n");
        i++;

    }
}

и функция ожидания pthread:

void *waiting_connection(void *server)
{
    serv_t *serv = (serv_t *)server;

    serv->newSocket = accept(serv->sockfd, (struct sockaddr*)&serv->newAddr, \
    &serv->addr_size);
    if (serv->newSocket < 0) {
        exit(1);
    }
    if ((serv->childpid = fork()) == 0) {
        close(serv->sockfd);
        while (recv(serv->newSocket, serv->buffer, 1024, 0) != 0) {
            printf("Client: %s\n", serv->buffer);
            send(serv->newSocket, serv->buffer, strlen(serv->buffer), 0);
            bzero(serv->buffer, sizeof(serv->buffer));
        }
    }

, если я комментирую вызов pthread_create и вызов после if функция waiting_connection, она будет работать, поэтому у меня проблема с моим pthread, но почему он не работает? еще раз спасибо!

Ответы [ 2 ]

2 голосов
/ 19 апреля 2020

У вас может быть состояние гонки, которое может привести к неопределенному поведению. В create_serv_and_init_client () вы определяете локальную переменную serv. Адрес этой переменной передается в поток. Когда create_serv_and_init_client завершает работу, serv go выходит из области видимости, даже если поток все еще использует его. В результате значение serv может перестать быть правильным.

0 голосов
/ 19 апреля 2020

Обратите внимание, что многопоточная программа действительно может только fork выполнить новую программу, используя execve. Например, из Linux руководств:

  • После fork() в многопоточной программе ребенок может безопасно вызывать только асин c -сигнал-безопасные функции (см. Signal-safety (7)) до тех пор, пока он не вызовет execve(2).

printf, например, не сможет заблокировать stdout. Если вы случайно подключитесь, пока блокировка printf удерживается другим потоком, сумасшедшие вещи могут произойти или не произойти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...