我的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
之前锁已正确释放,所以出了什么问题在我的代码?我可以使用什么技术来解决问题?
答案 0 :(得分:2)
首先:
pthread_rwlock_rdlock(&(u->lock));
printf("find_user2\n");
p = u->head;
if(p == NULL)
{
return NULL;
}
find_user()
上面的代码会在p
为NULL
的情况下锁定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;
}
锁定获得但未释放。