共享内存出错

249 views
Skip to first unread message

大雄

unread,
Mar 5, 2018, 10:28:39 PM3/5/18
to openresty
hi, All
    最近遇到一个奇怪的报错
    日志: 2018/03/06 10:54:19 [alert] 841#0: shared memory zone "sess_key" was locked by 20038
    
    出现这个错误的问题操作是函数是:  Session:set("123456798", "abcde", 700)
    只要操作这个函数 就会出现以上日志,然后nginx 的子进程就会退出,接着 master 会重新起一个新的 子进程。
    以上结果无限循环。


    使用strace 追踪,最后是收到 SIGSEGV 信号。也就是 出现了  Segment fault 错误,大概猜想是 访问到了一个 空指针了吧。
    nginx -s reload 无法解决问题,如果把进程stop 再start 一次,就不能重现问题。
    目前只出现一次问题。

    使用版本: openresty  1.13.6.1

tokers

unread,
Mar 5, 2018, 10:40:12 PM3/5/18
to openresty
Hello!

> 日志: 2018/03/06 10:54:19 [alert] 841#0: shared memory zone "sess_key" was locked by 20038

这说明 20038 这个进程在锁住这块共享内存后,还没来得及释放,就因为一些问题异常退出了。

> nginx -s reload 无法解决问题,如果把进程stop 再start 一次,就不能重现问题。

reload 的时候,如果不修改共享内存大小,那么这块共享内存还是会被复用的,
猜测可能这块共享内存是否被写入了脏数据导致比如 slab 池的一些信息被损坏了。

题主有对应的 coredump 文件吗,最好可以导入到 gdb,打印一下堆栈,以便分析观察。

大雄

unread,
Mar 5, 2018, 10:52:45 PM3/5/18
to openresty
我写入的key 和 val 都是明文,是做 网站的session key 保存,格式也是很固定的,
 如:   Session:set("b026324c6904b2a9cb4b88d6d61c81d1", "admin&1520307864", 7200)  这就是我的设置命令,每条都是一样的格式。

我的环境在嵌入式环境,没有coredump,我尝试一下看能否使用coredump。


--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

hongli...@gmail.com

unread,
Mar 6, 2018, 1:18:09 AM3/6/18
to openresty
Hello!
   请问你除了用`ngx.shared` API操作`sess_key` 的shm zone之外还有没有别的nginx第三方module操作过呢?
   另外你的OpenResty版本是多少? 如何安装的呢?
   最好能根据你的代码提供一个最小化的复现样例以便我们分析.

在 2018年3月6日星期二 UTC+8上午11:52:45,大雄写道:
我写入的key 和 val 都是明文,是做 网站的session key 保存,格式也是很固定的,
 如:   Session:set("b026324c6904b2a9cb4b88d6d61c81d1", "admin&1520307864", 7200)  这就是我的设置命令,每条都是一样的格式。

我的环境在嵌入式环境,没有coredump,我尝试一下看能否使用coredump。

在 2018年3月6日 上午11:40,tokers <zcha...@gmail.com>写道:
Hello!

> 日志: 2018/03/06 10:54:19 [alert] 841#0: shared memory zone "sess_key" was locked by 20038

这说明 20038 这个进程在锁住这块共享内存后,还没来得及释放,就因为一些问题异常退出了。

> nginx -s reload 无法解决问题,如果把进程stop 再start 一次,就不能重现问题。

reload 的时候,如果不修改共享内存大小,那么这块共享内存还是会被复用的,
猜测可能这块共享内存是否被写入了脏数据导致比如 slab 池的一些信息被损坏了。

题主有对应的 coredump 文件吗,最好可以导入到 gdb,打印一下堆栈,以便分析观察。

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com

大雄

unread,
Mar 7, 2018, 3:47:08 AM3/7/18
to openresty
hello,
   openresty 版本是 1.13.6.1 ,  openresty 是在嵌入式环境运行,在x86环境 没见过, 目前在 mips 环境 出现 问题。
   现在我也没有好的办法让他复现,我再继续观察,如果能有好的复现  我尽快来反馈。


在 2018年3月6日星期二 UTC+8下午2:18:09,hongli...@gmail.com写道:

Zexuan Luo

unread,
Mar 7, 2018, 3:57:42 AM3/7/18
to open...@googlegroups.com
x86 没问题,MIPS 下才会出现,难道是 memory alignment 的问题?
x86 和现代 arm 里面,即使访问的内存地址没有对齐,也不会有问题。但是其他硬件架构就未必了。考虑到 Nginx/OpenResty
里面有不少内存分配上的 hack,说不定就是这个问题。
当然没看到 core dump,这个只是猜测。

大雄

unread,
Mar 7, 2018, 4:12:16 AM3/7/18
to openresty
好的, 到时候有复现时,我整一下 code dump 。
另外我想起一件事, 当时在mips环境编译不过去,我看一下错误, 改了一下让他编译过去,我觉得我这个改动是对的。

--- a/src/os/unix/ngx_atomic.h  2017-12-07 17:03:35.196488805 +0800
+++ b/src/os/unix/ngx_atomic.h  2017-12-07 17:03:28.687224371 +0800
@@ -266,7 +266,7 @@ typedef volatile ngx_atomic_uint_t  ngx_
 
 #if !(NGX_HAVE_ATOMIC_OPS)
 
-#define NGX_HAVE_ATOMIC_OPS  0
+#define NGX_HAVE_ATOMIC_OPS  1
 
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;

> 订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
> 发言: 请发邮件到 open...@googlegroups.com
> 退订: 请发邮件至 openresty+unsubscribe@googlegroups.com
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

Zexuan Luo

unread,
Mar 7, 2018, 4:28:08 AM3/7/18
to open...@googlegroups.com
……明明不支持 ATOMIC_OPS 的,你这么改之后会让 Nginx 误认为支持 ATOMIC_OPS,怎么可能会是对的呢

大雄

unread,
Mar 7, 2018, 4:34:31 AM3/7/18
to openresty
从它的宏定义看, 前面有一堆的检查 ATOMIC 是否支持,如果不支持的话 则 会重新封装函数,
从逻辑上看,也就是说 如果前面不支持 ATOMIC  会重新定义,并且 把 NGX_HAVE_ATOMIC_OPS  = 1 ,如果不是这样的话 
那么 它的这个逻辑就是 多余的 了
#if !(NGX_HAVE_ATOMIC_OPS)

#define NGX_HAVE_ATOMIC_OPS  0
....
....
#endif


所以,按我的理解 应该是  NGX_HAVE_ATOMIC_OPS = 0 的话 ,重新定义 ngx_atomic_cmp_set 和 ngx_atomic_fetch_add ,并且 把  NGX_HAVE_ATOMIC_OPS   = 1 。


>> > 订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
>> > 发言: 请发邮件到 open...@googlegroups.com
>> > 退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

>> > 归档: http://groups.google.com/group/openresty
>> > 官网: http://openresty.org/
>> > 仓库: https://github.com/agentzh/ngx_openresty
>> > 教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
>>
>> --
>> --
>> 邮件来自列表“openresty”,专用于技术讨论!
>> 订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
>> 发言: 请发邮件到 open...@googlegroups.com
>> 退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

>> 归档: http://groups.google.com/group/openresty
>> 官网: http://openresty.org/
>> 仓库: https://github.com/agentzh/ngx_openresty
>> 教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
>
>
> --
> --
> 邮件来自列表“openresty”,专用于技术讨论!
> 订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
> 发言: 请发邮件到 open...@googlegroups.com
> 退订: 请发邮件至 openresty+unsubscribe@googlegroups.com
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

大雄

unread,
Mar 7, 2018, 4:35:15 AM3/7/18
to openresty


Zexuan Luo

unread,
Mar 7, 2018, 4:42:55 AM3/7/18
to open...@googlegroups.com
那两个重新定义的 ngx_atomic_* 函数的实现并不是原子的,恐怕只是为了能够在不需要准确的原子操作的地方能够编译通过才定义的。

tokers

unread,
Mar 7, 2018, 4:47:06 AM3/7/18
to openresty
我比较好奇你这里的编译错误是什么?方便贴一下图吗?
不支持原子变量的时候,一些需要用到互斥锁的情况下,它会用文件锁来替代。

大雄

unread,
Mar 7, 2018, 4:54:17 AM3/7/18
to openresty
hello, 
    tokers
    我发邮件给你了 

订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

tokers

unread,
Mar 7, 2018, 5:02:40 AM3/7/18
to openresty
Hello!

从你的报错来看,是因为实现读写锁,依赖于这个原子变量。
我看了下读写锁的话,只有 upstream 模块的 zone 特性在用的,对应宏是 NGX_HTTP_UPSTREAM_ZONE,这个宏无条件设置为 1。
如果你的配置里没有用到 upstream 模块的 zone 的话,可以考虑把 NGX_HTTP_UPSTREAM_ZONE 关掉。

另外方便贴下你发我的报错截图吗?方便大家一起分析。

大雄

unread,
Mar 7, 2018, 5:05:46 AM3/7/18
to openresty



大雄

unread,
Mar 7, 2018, 5:11:40 AM3/7/18
to openresty
我编译时加参数  --without-http_upstream_zone_module 来关闭模块 可以吗 ?

大雄

unread,
Mar 7, 2018, 5:19:09 AM3/7/18
to openresty
我增加   --without-http_upstream_zone_module  参数,编译不会报错了。
按这样来看,因为我没有使用  upstream 模块 ,所以我遇到的共享内存问题,跟我打补丁其实是无关的是吗 ?

大雄

unread,
Mar 14, 2018, 12:34:11 AM3/14/18
to openresty

hi, tokers
    今天又重现问题,我已经把 coredump 导出来 发邮件给你了。

在 2018年3月7日星期三 UTC+8下午6:02:40,tokers写道:

tokers

unread,
Mar 14, 2018, 7:17:59 AM3/14/18
to openresty
Hello!

刚看了下,红黑树节点居然出现了空值,正常情况下,如果左儿子/右儿子空的话,都会赋值成 sentinel 节点。目前没有看出端倪。:(

大雄

unread,
Mar 15, 2018, 9:30:57 PM3/15/18
to openresty
hello,  tokers
出现空指针, 那会不会有某些地方 把值设为 NULL ,
我觉得应该 需要针对 NULL值 专门处理一下逻辑吧。
有没有临时的解决办法建议 让我打个patch 进去,比如 得到NULL 的时候 我让  ngx_rbtree_delete  的函数直接 return 是否可以?


在 2018年3月14日 下午7:17,tokers <zcha...@gmail.com>写道:
Hello!

刚看了下,红黑树节点居然出现了空值,正常情况下,如果左儿子/右儿子空的话,都会赋值成 sentinel 节点。目前没有看出端倪。:(

--

tokers

unread,
Mar 16, 2018, 1:54:29 AM3/16/18
to openresty
Hello!


> 出现空指针, 那会不会有某些地方 把值设为 NULL ,

据我所知应该是没有的。

> 我觉得应该 需要针对 NULL值 专门处理一下逻辑吧。
> 有没有临时的解决办法建议 让我打个patch 进去,比如 得到NULL 的时候 我让  ngx_rbtree_delete  的函数直接 return 是否可以?

通常删除节点是为了及时删除过期的共享内存节点。如果因为这个 bug 而不删除过期节点,
这块共享内存最终会被撑满,导致新节点无法加入,最终可能影响到业务。

所以感觉还是需要根治。建议把这个问题报告到 OpenResty github issue 列表吧。

Zexuan Luo

unread,
Mar 16, 2018, 3:18:20 AM3/16/18
to open...@googlegroups.com
你这个“节点为NULL”的错误,是在修改了 Nginx 源码之后才出现吗?
如果原本应该是原子操作的地方(比如获取锁)没有真正地进行原子操作,那么可能会有两个进程并发同时修改一个内存地址的情况,这时候难免会出现
NULL 之类数据结构被破坏的情况。

在 2018年3月16日 上午9:30,大雄 <daxio...@gmail.com> 写道:
> hello, tokers
> 出现空指针, 那会不会有某些地方 把值设为 NULL ,
> 我觉得应该 需要针对 NULL值 专门处理一下逻辑吧。
> 有没有临时的解决办法建议 让我打个patch 进去,比如 得到NULL 的时候 我让 ngx_rbtree_delete 的函数直接 return
> 是否可以?
>
>
> 在 2018年3月14日 下午7:17,tokers <zcha...@gmail.com>写道:
>>
>> Hello!
>>
>> 刚看了下,红黑树节点居然出现了空值,正常情况下,如果左儿子/右儿子空的话,都会赋值成 sentinel 节点。目前没有看出端倪。:(
>>
>> --
>> --
>> 邮件来自列表“openresty”,专用于技术讨论!
>> 订阅: 请发空白邮件到 openresty...@googlegroups.com
>> 发言: 请发邮件到 open...@googlegroups.com
>> 退订: 请发邮件至 openresty+...@googlegroups.com
> --
> --
> 邮件来自列表“openresty”,专用于技术讨论!
> 订阅: 请发空白邮件到 openresty...@googlegroups.com
> 发言: 请发邮件到 open...@googlegroups.com
> 退订: 请发邮件至 openresty+...@googlegroups.com

大雄

unread,
Mar 16, 2018, 9:24:43 PM3/16/18
to openresty
hello, zexuan luo
    上次 tokers 告诉我 那段代码 是 upstream 的,但是我并未使用那个功能。
    我后来把 重新编译 去掉 upstream 模块, 不修改代码 也可以正常编译。
    所以我觉得 我的修改编译通过 和 节点NULL 的问题应该是无关的(这是我个人猜测),
    最近我还会继续观察一下,去掉我的改动 用一段时间看看,如果 还是这样,我会退到 1.11.2.5 的版本 再测测看。
    我感觉 nginx 1.13 的主线版本 可能有什么bug 也说不定。

 后续有情况 我再来继续汇报。

在 2018年3月16日 下午3:18,Zexuan Luo <spacewa...@gmail.com>写道:
你这个“节点为NULL”的错误,是在修改了 Nginx 源码之后才出现吗?
如果原本应该是原子操作的地方(比如获取锁)没有真正地进行原子操作,那么可能会有两个进程并发同时修改一个内存地址的情况,这时候难免会出现
NULL 之类数据结构被破坏的情况。

在 2018年3月16日 上午9:30,大雄 <daxio...@gmail.com> 写道:
> hello,  tokers
> 出现空指针, 那会不会有某些地方 把值设为 NULL ,
> 我觉得应该 需要针对 NULL值 专门处理一下逻辑吧。
> 有没有临时的解决办法建议 让我打个patch 进去,比如 得到NULL 的时候 我让  ngx_rbtree_delete  的函数直接 return
> 是否可以?
>
>
> 在 2018年3月14日 下午7:17,tokers <zcha...@gmail.com>写道:
>>
>> Hello!
>>
>> 刚看了下,红黑树节点居然出现了空值,正常情况下,如果左儿子/右儿子空的话,都会赋值成 sentinel 节点。目前没有看出端倪。:(
>>
>> --
>> --
>> 邮件来自列表“openresty”,专用于技术讨论!
>> 订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
>> 发言: 请发邮件到 open...@googlegroups.com
>> 退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

>> 归档: http://groups.google.com/group/openresty
>> 官网: http://openresty.org/
>> 仓库: https://github.com/agentzh/ngx_openresty
>> 教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
>
>
> --
> --
> 邮件来自列表“openresty”,专用于技术讨论!
> 订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
> 发言: 请发邮件到 open...@googlegroups.com
> 退订: 请发邮件至 openresty+unsubscribe@googlegroups.com
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com
Reply all
Reply to author
Forward
0 new messages