程序挂在pthread_rwlock_wrlock上?

时间:2014-03-10 13:25:36

标签: c linux pthreads

我的user_queue实现:

user_queue.h

#ifndef USER_QUEUE_H
#define USER_QUEUE_H
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>

typedef struct user_t
{
    uint32_t uid;
    uint32_t timestamp;
    struct user_t *next;
}user_t;

typedef struct u_queue_t
{
    pthread_rwlock_t lock;
    user_t *head;
    user_t *tail;
}u_queue_t;

#define NOW() (get_timestamp())

void init_user_queue(u_queue_t *u);
void add_user(u_queue_t *u, user_t *user);
void delete_user(u_queue_t *u, uint32_t uid);
user_t *find_user(u_queue_t *u, uint32_t uid);
void update_user_timestamp(u_queue_t *u, uint32_t uid, uint32_t now);
uint32_t get_timestamp(void);
extern u_queue_t user_queue;

#endif

user_queue.c

#include "user_queue.h"

u_queue_t user_queue;

void init_user_queue(u_queue_t *u)
{
    pthread_rwlock_init(&(u->lock), NULL);
    u->head = NULL;
    u->tail = NULL;
}

void add_user(u_queue_t *u, user_t *user)
{
    printf("add user0\n");
    pthread_rwlock_wrlock(&(u->lock));
    printf("add_user1\n");
    if(u->head == NULL)
    {
        u->head = user;
        u->tail = user;
        user->next = NULL;
    }
    else
    {
        u->tail->next = user;
        u->tail = user;
        user->next = NULL;
    }
    printf("add_user2\n");
    pthread_rwlock_unlock(&(u->lock));
}

void delete_user(u_queue_t *u, uint32_t uid)
{
    user_t *p = u->head;
    user_t *tmp;


    pthread_rwlock_wrlock(&(u->lock));
    if(p == NULL)
    {
        fprintf(stderr, "Error: empty user queue\n");
        return;
    }
    else
    {
        if(p->uid == uid)
        {
            u->head = p->next;
            u->tail = p->next;
        }
        free(p);
    }

    while(p->next != NULL)
    {
        if(p->next->uid == uid)
        {
            break;
        }
        else
        {
            p = p->next;
        }
    }

    tmp = p->next;
    p->next = tmp->next;
    if(tmp == u->tail)
    {
        u->tail = p;
    }
    free(tmp);
    pthread_rwlock_unlock(&(u->lock));
}

user_t *find_user(u_queue_t *u, uint32_t uid)
{
    user_t *p;
    printf("find_user1\n");
    pthread_rwlock_rdlock(&(u->lock));
    printf("find_user2\n");
    p = u->head;
    if(p == NULL)
    {
        return NULL;
    }

    while(p != NULL)
    {
        if(p->uid == uid)
        {
            break;
        }
    }
    pthread_rwlock_unlock(&(u->lock));
    return p;
}

uint32_t get_timestamp(void)
{
    return (uint32_t)time(NULL);
}

void update_user_timestamp(u_queue_t *u, uint32_t uid, uint32_t now)
{
    user_t *p = find_user(u, uid);
    if(p == NULL)
    {
        fprintf(stderr, "update_user_timestamp error: invalid user id\n");
        return;
    }

    p->timestamp = now;
}

我用户user_queue的代码如下:

if(uid)
{
    user_t *p;
    p = find_user(&user_queue, uid);
    printf("test\n");
    if(p == NULL)
    {
        memcpy(data, LOGIN_SUCCESS_MESSAGE, sizeof(server_login_message_t));
        m = message_new(MESSAGE_LOGIN, MAX_MESSAGE_SIZE, uid, data);
        status = create_node((void *)m, n->client_fd);
        u = (user_t *)malloc(sizeof(user_t));
        u->uid = uid;
        printf("test4\n");
        add_user(&user_queue, u);
        printf("test5\n");
        produce_message(&message_out_queue, status); 
        free(n);
    }
    else
    {
        printf("login again\n");
        memcpy(data, LOGIN_REPEAT_MESSAGE, sizeof(server_login_message_t));
        m = message_new(MESSAGE_LOGIN, MAX_MESSAGE_SIZE, uid, data);
        status = create_node((void *)m, n->client_fd);
        uint32_t now = NOW();
        update_user_timestamp(&user_queue, uid, now);
        produce_message(&message_out_queue, status); 
        free(n);
    }
}  

我使用pstack并发现线程在函数pthread_rwlock_wrlock()的{​​{1}}语句中挂起,但我认为在调用add_user之前锁已正确释放,所以出了什么问题在我的代码?我可以使用什么技术来解决问题?

2 个答案:

答案 0 :(得分:2)

首先:

  pthread_rwlock_rdlock(&(u->lock));
  printf("find_user2\n");
  p = u->head;
  if(p == NULL)
  {
    return NULL;
  }

find_user()上面的代码会在pNULL的情况下锁定rw-lock。致命的。

delete_user()中存在类似的错误。


此外,代码应该真正测试pthread*()调用的结果,因为至少这会在调试过程中帮助你。

答案 1 :(得分:2)

删除用户

pthread_rwlock_wrlock(&(u->lock));
if(p == NULL)
{
    fprintf(stderr, "Error: empty user queue\n");
    return;
}

在查找用户

pthread_rwlock_rdlock(&(u->lock));
printf("find_user2\n");
p = u->head;
if(p == NULL)
{
    return NULL;
}

锁定获得但未释放。