可能的死锁原因是在执行 clib_spinlock_lock(&dm->white_cache_lock);
后,如果在函数中间发生了异常或错误,导致没有执行对应的解锁操作 clib_spinlock_unlock(&dm->white_cache_lock);
,从而造成线程一直卡在该锁上无法继续执行。解决方法是使用 trylock
而不是 lock
,并在获取到锁后立即设置一个标志位,表示已经成功获得锁,并在最后释放锁之前检查该标志位是否已设置,如果已设置,则释放锁,否则不进行任何操作。这样能够避免死锁的情况。以下是修改后的代码示例:
static int vnet_add_cname_to_name(const char* domain,const char* cname,u32 cname_ttl) { if(!cname || !domain) {
return -1;
}
dns_resolve_main_t *dm = &dns_resolve_global_main; dns_resolve_white_entry_t *drw_entry = NULL; vlib_main_t *vm = &vlib_global_main; bool got_lock = false;
if(clib_spinlock_trylock(&dm->white_cache_lock)) {
got_lock = true;
//遍历白名单
vec_foreach (drw_entry, dm->white_cache_entry_by_name)
{
if(drw_entry == NULL)
{
break;
}
if((drw_entry->name) == 0 && domain == NULL)
{
return -1;
}
//正则匹配
if(regcomp_exe((char *)(domain),(drw_entry->regex_name)) >= 0)
{
int i = 0;
//匹配别名
for(i = 0;i < vec_len(drw_entry->dns_cname_info);i++)
{
//如果存在 直接返回
if(!clib_strncmp(cname,(char*)drw_entry->dns_cname_info->cname,strlen(cname)))
{
return -1;
}
}
//判断cname 长度
/* Add space for the dns_ip_info */
int vec_len_dns_cname = vec_len((drw_entry)->dns_cname_info);
if(vec_len_dns_cname < dm->max_num_of_domain_cnames)
{
if(vec_len(drw_entry->dns_cname_info) >= vec_max_len(drw_entry->dns_cname_info))
{
vec_validate(drw_entry->dns_cname_info,vec_len_dns_cname * 2);
}
}
else
{
return -1;
}
//别名没命中,则存储
dns_resolve_cname_info_t tmp_cname_elm;
clib_strcpy((char*)tmp_cname_elm.cname,(char*)cname);
f64 now = vlib_time_now (vm);
tmp_cname_elm.cname_ttl = cname_ttl + now;
vec_add1(drw_entry->dns_cname_info,tmp_cname_elm);
return 1;
}
}
}
if(got_lock) {
clib_spinlock_unlock(&dm->white_cache_lock);
}
return 1; }