Connect reset 原因 定位分析
1. 问题表现
继第一篇《问题描述 & 初步分析定位》, 问题表现为:
-
s3cmd error message:
error: [Errno 104] Connection reset by peer
-
radosgw error message:
ERROR: flush_read_list(): d->client_cb->handle_data() returned -5
2. 定位radosgw error code -5
2.1. 在ceph radosgw 中定位报错代码
rgw_rados.cc:
int RGWRados::flush_read_list(struct get_obj_data *d)
{
...
r = d->client_cb->handle_data(bl, 0, bl.length());
if (r < 0) {
dout(0) << "ERROR: flush_read_list(): d->client_cb->handle_data() returned " << r << dendl;
break;
}
...
}
-
从上面代码可以看出:
d->client_cb->handle_data(bl, 0, bl.length());
函数报错 -
现在我们需要进一步定位handle_data()报错原因,以及-5代码含义
2.2. 定位handle_data()失败原因
通过gdb等手段,确认handle_data()函数调用堆栈为:
flush_read_list()
RGWGetObj::get_data_cb()
RGWGetObj_ObjStore_S3::send_response_data()
dump_body()
......
civetweb.c: push_all()
civetweb.c: push()
Linux socket send()
从调用堆栈中看出,是网络的send()
失败,导致最上层的失败。
civetweb.c: push()的代码如下:
static int
push(struct mg_context *ctx,
FILE *fp,
SOCKET sock,
SSL *ssl,
const char *buf,
int len,
double timeout)
{
......
n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
err = (n < 0) ? ERRNO : 0;
if ((n > 0) || (n == 0 && len == 0)) {
/* some data has been read, or no data was requested */
return n;
}
if (n == 0) {
/* shutdown of the socket at client side */
return -1;
}
i