Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
b9105e13
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b9105e13
编写于
7月 24, 2019
作者:
A
Alexey Milovidov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Avoid deadlock in TraceCollector
上级
72d543f3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
49 addition
and
1 deletion
+49
-1
dbms/src/Common/ErrorCodes.cpp
dbms/src/Common/ErrorCodes.cpp
+1
-0
dbms/src/Common/QueryProfiler.cpp
dbms/src/Common/QueryProfiler.cpp
+28
-1
dbms/src/Common/TraceCollector.cpp
dbms/src/Common/TraceCollector.cpp
+20
-0
未找到文件。
dbms/src/Common/ErrorCodes.cpp
浏览文件 @
b9105e13
...
...
@@ -437,6 +437,7 @@ namespace ErrorCodes
extern
const
int
CANNOT_CREATE_TIMER
=
460
;
extern
const
int
CANNOT_SET_TIMER_PERIOD
=
461
;
extern
const
int
CANNOT_DELETE_TIMER
=
462
;
extern
const
int
CANNOT_FCNTL
=
463
;
extern
const
int
KEEPER_EXCEPTION
=
999
;
extern
const
int
POCO_EXCEPTION
=
1000
;
...
...
dbms/src/Common/QueryProfiler.cpp
浏览文件 @
b9105e13
...
...
@@ -16,6 +16,33 @@ extern LazyPipe trace_pipe;
namespace
{
/** Write to file descriptor but drop the data if write would block or fail.
* To use within signal handler. Motivating example: a signal handler invoked during execution of malloc
* should not block because some mutex (or even worse - a spinlock) may be held.
*/
class
WriteBufferDiscardOnFailure
:
public
WriteBufferFromFileDescriptor
{
protected:
void
nextImpl
()
override
{
size_t
bytes_written
=
0
;
while
(
bytes_written
!=
offset
())
{
ssize_t
res
=
::
write
(
fd
,
working_buffer
.
begin
()
+
bytes_written
,
offset
()
-
bytes_written
);
if
((
-
1
==
res
||
0
==
res
)
&&
errno
!=
EINTR
)
break
;
/// Discard
if
(
res
>
0
)
bytes_written
+=
res
;
}
}
public:
using
WriteBufferFromFileDescriptor
::
WriteBufferFromFileDescriptor
;
~
WriteBufferDiscardOnFailure
()
override
{}
};
/// Normally query_id is a UUID (string with a fixed length) but user can provide custom query_id.
/// Thus upper bound on query_id length should be introduced to avoid buffer overflow in signal handler.
constexpr
size_t
QUERY_ID_MAX_LEN
=
1024
;
...
...
@@ -33,7 +60,7 @@ namespace
sizeof
(
StackTrace
)
+
// collected stack trace
sizeof
(
TimerType
);
// timer type
char
buffer
[
buf_size
];
WriteBuffer
FromFileDescriptor
out
(
trace_pipe
.
fds_rw
[
1
],
buf_size
,
buffer
);
WriteBuffer
DiscardOnFailure
out
(
trace_pipe
.
fds_rw
[
1
],
buf_size
,
buffer
);
StringRef
query_id
=
CurrentThread
::
getQueryId
();
query_id
.
size
=
std
::
min
(
query_id
.
size
,
QUERY_ID_MAX_LEN
);
...
...
dbms/src/Common/TraceCollector.cpp
浏览文件 @
b9105e13
...
...
@@ -12,6 +12,10 @@
#include <Common/Exception.h>
#include <Interpreters/TraceLog.h>
#include <unistd.h>
#include <fcntl.h>
namespace
DB
{
...
...
@@ -21,6 +25,7 @@ namespace ErrorCodes
{
extern
const
int
NULL_POINTER_DEREFERENCE
;
extern
const
int
THREAD_IS_NOT_JOINABLE
;
extern
const
int
CANNOT_FCNTL
;
}
TraceCollector
::
TraceCollector
(
std
::
shared_ptr
<
TraceLog
>
&
trace_log
)
...
...
@@ -31,6 +36,21 @@ TraceCollector::TraceCollector(std::shared_ptr<TraceLog> & trace_log)
throw
Exception
(
"Invalid trace log pointer passed"
,
ErrorCodes
::
NULL_POINTER_DEREFERENCE
);
trace_pipe
.
open
();
/** Turn write end of pipe to non-blocking mode to avoid deadlocks
* when QueryProfiler is invoked under locks and TraceCollector cannot pull data from pipe.
*/
int
flags
=
fcntl
(
trace_pipe
.
fds_rw
[
1
],
F_GETFL
,
0
);
if
(
-
1
==
fcntl
(
trace_pipe
.
fds_rw
[
1
],
F_SETFL
,
flags
|
O_NONBLOCK
))
throwFromErrno
(
"Cannot set non-blocking mode of pipe"
,
ErrorCodes
::
CANNOT_FCNTL
);
/** Increase pipe size to avoid slowdown during fine-grained trace collection.
*/
int
pipe_size
=
fcntl
(
trace_pipe
.
fds_rw
[
1
],
F_GETPIPE_SZ
);
for
(
errno
=
0
;
errno
!=
EPERM
&&
pipe_size
<=
1048576
;
pipe_size
*=
2
)
if
(
-
1
==
fcntl
(
trace_pipe
.
fds_rw
[
1
],
F_SETPIPE_SZ
,
pipe_size
)
&&
errno
!=
EPERM
)
throwFromErrno
(
"Cannot increase pipe capacity to "
+
toString
(
pipe_size
),
ErrorCodes
::
CANNOT_FCNTL
);
thread
=
ThreadFromGlobalPool
(
&
TraceCollector
::
run
,
this
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录