程序在现场运行,发生了一系列的崩溃, 定位在 rte_mempool_get/rte_mempool_put和 enqueue_msg/dequeue_msg.
需要盘查 rte_mempool_get/rte_mempool_put 内存节点在各个线程之间来回穿梭,
当 rte_mempool_get 获取成功之后 enqueue入队列马上再 rte_mempool_put 释放,
一定会导致 dequeue 出队列的一方持有了一个野指针对象, 会发生一系列的莫名其妙的崩溃.
那么现在 盘查出 到底是哪里 发生了 上面这种场景.
低压力不能触发崩溃, 需要高压力才能触发.
整个项目中, 充斥着大量的, 诸如这类的代码,将近有70多个文件中
很明显, 直接改每个源文件,是最拙劣的方法!
1 2 3 4 5 6 7 8 9
| 1类: if(rte_mempool_get(obj_mempool, (void**)&obj_new) < 0) { ... }
2类: if的语句没有花括号 if(enqueue_msg(obj_new) < 0) rte_mempool_put(obj_mempool, (void *)obj_new);
|
提示:
如果我在 rte_mempool_put/rte_mempool_put 函数里面修改, 就得不到 调用者的文件名/行号信息
实现 仿函数
1 2 3
| /usr/local/include/dpdk/rte_mempool.h #define rte_mempool_get_debug(a,b) ({int rc=rte_mempool_get(a,b);printf("get obj %p %s:%u\n",*b,__FILE__,__LINE__);rc;}) #define rte_mempool_put_debug(a,b) ({rte_mempool_put(a,b);printf("put obj %p %s:%u\n",b,__FILE__,__LINE__);})
|
原始代码:获取
1 2 3 4 5 6
| { if (rte_mempool_get(tbl_log_mempool, (void **)&obj_new) < 0) { return PKT_OK; } }
|
原始代码:释放(注意if语句没有花括号)
1 2 3 4 5
| { if (write_tbl_log(obj_new) != 1) rte_mempool_put(obj_mempool, (void *)obj_new); return; }
|
一顿操作:
1 2
| sed -i 's@\brte_mempool_get\b@rte_mempool_get_debug@g' `grep -inrwl rte_mempool_get` sed -i 's@\brte_mempool_put\b@rte_mempool_put_debug@g' `grep -inrwl rte_mempool_put`
|
恢复代码
1 2
| sed -i 's@\brte_mempool_get_debug\b@rte_mempool_get@g' `grep -inrwl rte_mempool_get_debug` sed -i 's@\brte_mempool_put_debug\b@rte_mempool_put@g' `grep -inrwl rte_mempool_put_debug`
|
新的代码:获取
1 2 3 4 5 6
| { if (({int rc=rte_mempool_get(tbl_log_mempool,(void **)&obj_new);printf("get obj %p %s:%u\n",*(void **)&obj_new,"xxx.c",283);rc;}) < 0) { return PKT_OK; } }
|
新的代码:释放(注意if语句没有花括号)
1 2 3 4 5
| { if (write_tbl_log(obj_new) != 1) ({rte_mempool_put(obj_mempool,(void *)obj_new); printf("put obj %p %s:%u\n", (void *)obj_new, "xxx.c", 433);}); return; }
|
参考: list.h
1
| #define container_of(ptr, type, member) ({const typeof(((type*)0)->member)*__mptr=(ptr);(type*)((char*)__mptr-offsetof(type,member));})
|