Потоки для подключения к различным серверам имеют непредсказуемый результат - PullRequest
1 голос
/ 21 апреля 2020

У меня есть два сервера, работающих на указанных портах.

Я пытаюсь подключиться к ним обоим параллельно, используя потоки.

Код работает, как требуется, когда я не многопоточен.

int main(){
    // Server 1
    char* ip1[]={"127.0.0.1","42069"};
    // Server 2
    char* ip2[]={"127.0.0.1","42070"};

    file_l *file = create_file_l("file.txt",ROOT);
    if(file->size != 0)
        return -1;
    // Common Data Structure that is sent to both threads to prevent overwriting
    file_n *filen = create_file_n(file);
    filen->part_size = 102416;

    add_seed(ip1, filen);
    add_seed(ip2, filen);
    return 1;
}

Функция add_seed подключается к данному серверу и создает новый поток для обработки данных с этого сервера.

int add_seed(char* ip[], file_n* n){
    // Connects to given address and goes file descriptor
    int cfd = connectTo(ip);
    if(cfd==-1)return -1;

    // Data Structure Used to pass parameters to both threads
    conn_det *cd  = malloc(sizeof *cd);
    cd->socket = cfd;cd->file = n;
    // Thread Creation
    pthread_t temp;
    pthread_create(&temp,NULL,initiate_data_transfer,cd);
    pthread_detach(temp);
    return 1;
}

Функция initiate_data_transfer отправляет запросы данных и обрабатывает их входящий ответ от сервера.

void* initiate_data_transfer(void *ptr){
    printf("Thread ID : %ld\n",syscall(SYS_gettid));
    conn_det *cd = ptr;
    file_n *n = cd->file;
    int socket = cd->socket;int rv=-1;
    long size = check_if_available(socket, n->local->name);
    printf("Recv Size : %ld Thread ID : %ld\n",size,syscall(SYS_gettid));

    // Checks if file size has been set by some other thread
    pthread_mutex_lock(&(n->mutex));
        if(n->local->size == 0){           // If not , assign file_size
            n->local->size = size;
            initialize_file_n(n);
        }else{
            if(n->local->size != size){    // If yes and size from this server does not match, then exit.
                pthread_mutex_unlock(&(n->mutex));
                return NULL;
            }
        }
    pthread_mutex_unlock(&(n->mutex));
    // Data Transfer Part.
    printf("Size : %ld Thread ID : %ld\n",n->local->size,syscall(SYS_gettid));
    while((rv=get_part(n)) != -1){
        printf("Handling Part : %d Thread ID : %ld\n",rv,syscall(SYS_gettid));
        send_fetch_request(socket,n,rv);
        recv_fetch_response(socket,n,rv);
    }

    close(socket);
}

Структуры данных, используемые для передачи информации в потоки.

typedef struct File_information_Network{
    long part_size;
    long total_parts;
    int* parts_recieved;
    file_l *local;
    pthread_mutex_t mutex;
}file_n;

typedef struct Connection_Details
{
    int socket;
    file_n *file;
}conn_det;

Проблема заключается в том, что только один из потоков достигает функции initiate_data_transfer большую часть времени.

Это видно из того факта, что printf("Thread ID : %ld\n", syscall(SYS_gettid));, который является первой строкой initiate_data_transfer, запускается один раз в большинстве случаев, тогда как я создал два потока. *1024*

Рассмотрим следующие журналы:

Терминал Клиента:

user@machine:~/Desktop/cn/FileShare/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3164
Connected to: 127.0.0.1
user@machine:~/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3169
Connected to: 127.0.0.1
user@machine:~/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3174
Connected to: 127.0.0.1
user@machine:~/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3179
Connected to: 127.0.0.1
Thread ID : 3180

Я не знаю, что идет не так, и использование printf для отладки не помогает мне понять это совсем. Любая помощь приветствуется.

1 Ответ

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

Я подозреваю, что основной поток просто завершает работу, прежде чем оба потока смогут достичь initiate_data_transfer и работать.

Несмотря на то, что вы отсоединили вновь созданные потоки, возврат из потока main все равно выйдет из процесса .

Таким образом, вместо:

return 1;

из main, выполните:

pthread_exit(0);

И это позволит потокам продолжаться. Когда завершится последний поток, процесс автоматически завершится.

...