土法炼钢兴趣小组的算法知识备份

常见陷阱 (Pitfalls & FAQ)

目录

Libevent 虽然强大,但也很容易误用。以下是社区中最高频的“踩坑”记录。

1. 多线程噩梦

1.1. 忘记初始化锁

现象: 程序随机 Crash,GDB 堆栈指向 event_add 或链表操作。 原因: 多线程环境下未调用 evthread_use_pthreads()解决: 在 main 函数第一行调用它。

1.2. 回调“自杀”

现象: 在 bufferevent 的回调函数中调用 bufferevent_free(bev),导致 Use-after-free 或死锁。 原因: Libevent 内部可能还在使用这个 bev 对象。 解决: 使用 BEV_OPT_DEFER_CALLBACKS 选项创建 bufferevent,或者确保 free 后立即返回,不再触碰 bev。

2. 内存与缓冲

2.1. OOM (内存溢出)

现象: 内存占用持续飙升,最终被 OOM Killer 杀掉。 原因: 接收速度 > 处理速度,且未设置高水位。input buffer 无限膨胀。 解决: 务必设置 bufferevent_setwatermark(bev, EV_READ, 0, 1024*1024)

3. 进程模型

3.1. Fork 后失效

现象: fork 后子进程的事件循环没反应,或者报错。 原因: epoll fd 不能跨进程共享。 解决: 子进程必须调用 event_reinit(base)

4. 隐蔽的阻塞

4.1. DNS 查询

现象: 偶尔整个服务卡顿几秒。 原因: 在回调中使用了 gethostbynamemysql_connect 等阻塞函数。 解决: 使用 evdns 或线程池。

4.2. 日志打印

现象: 磁盘 I/O 繁忙时服务吞吐量下降。 原因: printf 或同步日志库阻塞了 Event Loop。 解决: 使用异步日志库 (spdlog async mode)。

5. 总结

Libevent 编程的核心原则:非阻塞、线程安全、资源管理。时刻牢记这三点,就能避开 90% 的坑。


上一篇: 07-hardening/performance.md - 性能调优 下一篇: 08-projects/transparent-proxy.md - 实战:透明代理

返回 Libevent 专题索引


By .