C pthread не запускается - PullRequest
       4

C pthread не запускается

0 голосов
/ 27 февраля 2020

Я пишу простой сервер котировок на C и работаю на Linux. Он должен выбрать случайную цитату из текстового файла и затем запустить две темы:

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

Моя проблема в том, что, хотя поток соединения работает нормально, другой даже не запускается.

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

Я также добавил некоторый код для проверки возвращаемого значения pthread_create(), скопированного со страницы руководства, но я не уверен, работает ли оно на самом деле, поскольку не обнаруживает никаких ошибок.

У меня есть привязан к тому, чтобы сначала запустить «поток таймера» и вообще не запускать поток соединения, но он все равно не выполняется. Ниже приведен соответствующий код, полный исходный код вы можете найти на GitHub :

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>

#define handle_error_en(en, msg) \
               do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

pthread_mutex_t quoteLock=PTHREAD_MUTEX_INITIALIZER;
pthread_t checkForNewDayThread, connectionHandlerThread;

void * timer_thread_code(){ //The thread will act as a timer checking every hour if a day has passed
    while (true) {
        sleep(3600);
        if (a_day_has_passed()) {
            pthread_mutex_lock(&quoteLock);
            QOTD = read_random_quote_from_file(pathToQOTDfile);
            pthread_mutex_unlock(&quoteLock);
        }
    }
}

void * connection_thread_code(int port){    //Code for the thread to handle connections
    struct sockaddr_in address;
    int server_fd, new_socket, opt = 1, addrlen = sizeof(address);

    // Creating socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // Forcefully attaching socket to the port 1717
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))==-1)
    {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons( port );

    // Forcefully attaching socket to the port 1717
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 100) < 0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("Listening on port %i\n", port);

    while(1) {  //connection handler loop
        if ((new_socket = accept(server_fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) {
            perror("accept");
            exit(EXIT_FAILURE);
        }
        pthread_mutex_lock(&quoteLock);
        send(new_socket, QOTD, strlen(QOTD), 0);
        pthread_mutex_unlock(&quoteLock);
        close(new_socket);
    }
}

int main(int argc, char const *argv[])
{
    int thread1, thread2, join;
    thread1=pthread_create(&connectionHandlerThread, NULL, connection_thread_code(port), NULL);
    if(thread1!=0) handle_error_en(thread1, "pthread_create");
    thread2=pthread_create(&checkForNewDayThread, NULL, timer_thread_code(), NULL);
    if(thread2!=0) handle_error_en(thread2, "pthread_create");
    join=pthread_join(connectionHandlerThread, NULL);
    if(join!=0) handle_error_en(join, "pthread_join");
    return 0;
}

Примечание: я поставил только один pthread_join(), потому что оба потока должны работать вечно, чтобы предотвратить возврат от основного должно хватить только одного из двух.

Заранее спасибо всем, кто мне помогает

1 Ответ

1 голос
/ 27 февраля 2020

Когда вы вызываете pthread_create, как в вашем коде:

thread1=pthread_create(&connectionHandlerThread, NULL, connection_thread_code(port), NULL);

Вы фактически сначала вызываете connection_thread_code(port) в главном потоке и передаете возвращаемое значение этого вызова функции в качестве параметра pthread_create.

Это не то, что вы хотите сделать. Вы хотите передать указатель функции в качестве параметра в pthread_create, а также аргументы для его передачи:

int port = 1234; /* <-- make sure this is in scope for the duration of the thread ! */
thread1 = pthread_create(&connectionHandlerThread, NULL, connection_thread_code, &port);
/* ... */
pthread_join(connectionHandlerThread, NULL);

Чтобы это работало, ваша функция потока должна иметь такую ​​сигнатуру:

void* connection_thread_code(void* port_ptr);

И получить порт следующим образом:

int port = *((int*) port_ptr);

Подробнее о передаче параметра int в функцию потока здесь .

Аналогично для второго потока (перед вызовом функции передайте указатель на функцию и измените подпись).

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