现象:
程序陷入死循环,消耗cpu 100%
backtrace:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
(gdb) bt #0 0x00bc098a in ?? () from /usr/lib/libcurl.so.3 #1 0x00be1be4 in Curl_llist_remove () from /usr/lib/libcurl.so.3 #2 0x00be1ca3 in Curl_llist_destroy () from /usr/lib/libcurl.so.3 #3 0x00be1e34 in Curl_hash_clean () from /usr/lib/libcurl.so.3 #4 0x00bc1dca in Curl_global_host_cache_dtor () from /usr/lib/libcurl.so.3 #5 0x00be00a5 in curl_global_cleanup () from /usr/lib/libcurl.so.3 #6 0x00866437 in zm_shutdown_curl (type=1, module_number=41) at /tmp/mongodb-mongo-php-driver-bffec80/curl/interface.c:866 #7 0x0128613e in module_destructor (module=0x83b2978) at /data0/software/php-5.3.3/Zend/zend_API.c:2098 #8 0x0128cea8 in zend_hash_apply_deleter (ht=0x15c5e60, p=0x83b2948) at /data0/software/php-5.3.3/Zend/zend_hash.c:611 #9 0x0128d0e8 in zend_hash_graceful_reverse_destroy (ht=0x15c5e60) at /data0/software/php-5.3.3/Zend/zend_hash.c:646 #10 0x01281aee in zend_shutdown () at /data0/software/php-5.3.3/Zend/zend.c:759 #11 0x01230faa in php_module_shutdown () at /data0/software/php-5.3.3/main/main.c:2139 #12 0x0123105b in php_module_shutdown_wrapper (sapi_globals=0x15af680) at /data0/software/php-5.3.3/main/main.c:2111 #13 0x012ffba3 in php_apache_child_shutdown (tmp=0x0) at /data0/software/php-5.3.3/sapi/apache2handler/sapi_apache2.c:399 #14 0x001250ed in run_cleanups (cref=0x8427080) at memory/unix/apr_pools.c:2308 #15 0x00125cdd in apr_pool_destroy (pool=0x8427070) at memory/unix/apr_pools.c:779 #16 0x08089344 in clean_child_exit (code=0) at prefork.c:196 #17 0x080897d0 in child_main (child_num_arg=<value optimized out>) at prefork.c:212 #18 0x08089a17 in make_child (s=0x817afa0, slot=479) at prefork.c:758 #19 0x0808a370 in ap_mpm_run (_pconf=0x81790a8, plog=0x81a7160, s=0x817afa0) at prefork.c:893 #20 0x080648b5 in main (argc=135753888, argv=0x8427070) at main.c:740 (gdb) |
bug相关代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
int Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, void *user) { if(e == NULL || list->size == 0) return 1; if(e == list->head) { list->head = e->next; if(list->head == NULL) list->tail = NULL; else e->next->prev = NULL; } else { e->prev->next = e->next; if(!e->next) list->tail = e->prev; else e->next->prev = e->prev; } list->dtor(user, e->ptr); e->ptr = NULL; e->prev = NULL; e->next = NULL; free(e); --list->size; return 1; } void Curl_llist_destroy(struct curl_llist *list, void *user) { if(list) { while(list->size > 0) // 请看函数Curl_llist_remove(..)的实现,如果 list->tail == null && list->size > 0 ; 那么这里就进入了死循环了。解决办法: 至少两遍判断条件要一致吧 Curl_llist_remove(list, list->tail, user); free(list); } } |
给curl官方提交了一个bug: https://sourceforge.net/tracker/?func=detail&aid=3583103&group_id=976&atid=100976