一个有趣的nginx问题引发的小问题
最近处理一个nginx问题,故障现象是:所有的work进程,都在等锁。调用的是sem_wait
根据对应的堆栈,查看一下大家等的锁都一样,看看这把锁被谁拿了:
锁的结构是:
typedef struct { #if (NGX_HAVE_ATOMIC_OPS) ngx_atomic_t *lock; #if (NGX_HAVE_POSIX_SEM) ngx_atomic_t *wait; ngx_uint_t semaphore; sem_t sem; #endif #else ngx_fd_t fd; u_char *name; #endif ngx_uint_t spin; } ngx_shmtx_t;
加锁的时候,方法是:
void ngx_shmtx_lock(ngx_shmtx_t *mtx) { ngx_uint_t i, n; ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock"); for ( ;; ) { if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { return; } 。。。。。
当没有人锁住的时候,ngx_pid的地址会设置到mtx->lock这个指针里面去,这样别人来取的时候就知道被占用了。这个是原子的比较和赋值。
发现是一个编号为【22308】的进程,而这个进程目前在ps -ef 中grep不到,
怀疑是一个死去的线程,查看message日志,果然如此,有一个段错误的打印。
反汇编对应的地址:错误在ngx_selective_cache_purge_sync_database_timer_wake_handler ,这是个扩展模块,没有堆栈,直接不太好分析。
按道理这个线程在退出之前,会给父进程发送信号,然后父进程处理该子进程对应的资源释放,但是error.log中没有看到这个打印。
由于多台设备出现了这个问题,这样复现概率就很高,我们打算复现,首先就得解决core文件的生成问题。
打开coredump文件。
一般我们在程序启动前,通过ulimit -c ulimited来设置core文件的大小,也可以修改/etc/security/limits.conf文件,添加如下信息:
admin soft core 1000000
admin hard core 1000000
也可以直接修改nginx的配置文件,添加如下配置项:
worker_rlimit_core 10000m;
但这两种方式都有硬伤,就是得复位,不管是复位进程还是复位服务器,我们也不想复位,怎么让之前已经运行的nginx进程生效呢?搜索了一下,找到一个命令:
在https://unix.stackexchange.com/questions/108603/do-changes-in-etc-security-limits-conf-require-a-reboot
中,我找到了prlimit 命令,看这个帖子下面的评论,很多人跟我一样不了解这个命令,有点可惜,共享出来。
cat /proc/4822/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes--------------------要把这行改成ulimited Max resident set unlimited unlimited bytes Max processes 1415172 1415172 processes Max open files 1024 4096 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 1415172 1415172 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us
改完之后的效果:
[root@localhost sys]# prlimit --pid 4822 --core=1024:2048 [root@localhost sys]# cat /proc/4822/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 1024 2048 bytes------------改过之后。 Max resident set unlimited unlimited bytes Max processes 1415172 1415172 processes Max open files 1024 2048 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 1415172 1415172 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us
等待复现中。。。。。。