Skip to content

Commit 924bf0f

Browse files
iddqdexblinkov
authored andcommitted
Use Google Breakpad in ydbd (#12994)
1 parent 7871206 commit 924bf0f

File tree

8 files changed

+127
-12
lines changed

8 files changed

+127
-12
lines changed

ydb/apps/ydbd/ya.make

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ PEERDIR(
6969
yql/essentials/udfs/common/url_base
7070
yql/essentials/udfs/common/yson2
7171
yql/essentials/udfs/logs/dsv
72-
ydb/public/sdk/cpp/src/client/persqueue_public/codecs
72+
ydb/library/breakpad
73+
ydb/public/sdk/cpp/client/ydb_persqueue_public/codecs
7374
)
7475

7576
YQL_LAST_ABI_VERSION()

ydb/deploy/docker/Dockerfile

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,20 @@ COPY --chmod=0644 /liblibaio-dynamic.so /lib/liblibaio-dynamic.so
2424
###
2525
# Base image with google brekpad assets
2626
###
27-
FROM ${BREAKPAD_INIT_IMAGE}:${BREAKPAD_INIT_IMAGE_TAG} AS breakpad_init
28-
29-
30-
FROM base AS breakpad-setuid
31-
COPY --from=breakpad_init /usr/lib/libbreakpad_init.so /usr/lib/libbreakpad_init.so
32-
# workaround for old docker versions
33-
# https://github.com/moby/buildkit/issues/3920
34-
RUN /usr/bin/chmod 4644 /usr/lib/libbreakpad_init.so
3527

28+
FROM ${BREAKPAD_INIT_IMAGE}:${BREAKPAD_INIT_IMAGE_TAG} AS breakpad_init
3629
FROM base AS base-breakpad
3730
RUN \
3831
apt-get -yqq update && \
3932
apt-get -yqq install --no-install-recommends binutils gdb strace linux-tools-generic && \
4033
apt-get clean && rm -rf /var/lib/apt/lists/*
41-
ENV LD_PRELOAD=libbreakpad_init.so
4234
ENV BREAKPAD_MINIDUMPS_PATH=/opt/ydb/volumes/coredumps
4335
ENV BREAKPAD_MINIDUMPS_SCRIPT=/opt/ydb/bin/minidump_script.py
4436
# breakpad binaries
4537
COPY --chmod=0755 --from=breakpad_init /usr/bin/minidump_stackwalk /usr/bin/minidump_stackwalk
4638
COPY --chmod=0755 --from=breakpad_init /usr/bin/minidump-2-core /usr/bin/minidump-2-core
4739
# minidump callback script
4840
COPY --chmod=0755 --chown=ydb /minidump_script.py /opt/ydb/bin/minidump_script.py
49-
# minidump init library
50-
COPY --link --from=breakpad-setuid /usr/lib/libbreakpad_init.so /usr/lib/libbreakpad_init.so
5141

5242
FROM base AS ydbd-setcap
5343
COPY --chmod=0755 --chown=ydb /ydbd /opt/ydb/bin/ydbd

ydb/library/breakpad/minidumps.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <util/generic/ptr.h>
2+
#include <contrib/libs/breakpad/src/client/linux/handler/exception_handler.h>
3+
#include <unistd.h>
4+
#include <sys/wait.h>
5+
6+
7+
class TMinidumper {
8+
public:
9+
TMinidumper() {
10+
if(const char* path = getenv("BREAKPAD_MINIDUMPS_PATH")) {
11+
using namespace google_breakpad;
12+
Handler = MakeHolder<ExceptionHandler>(MinidumpDescriptor(path), nullptr, DumpCallback, nullptr, true, -1, true);
13+
}
14+
}
15+
16+
private:
17+
static bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded) {
18+
if (char* script = getenv("BREAKPAD_MINIDUMPS_SCRIPT")) {
19+
if (auto pid = fork()) {
20+
waitpid(pid, 0, 0);
21+
} else {
22+
char* dumpSucceded = succeeded ? (char *)"true" : (char *)"false";
23+
char* descriptorPath = succeeded ? (char *)descriptor.path() : (char *)"\0";
24+
char* cmd[] = {script, dumpSucceded, descriptorPath, NULL};
25+
if (execve(cmd[0], &cmd[0], NULL)) {
26+
fprintf(stderr, "Error while process BREAKPAD MINIDUMPS SCRIPT: execve(%s '%s' '%s' '%s'): %s\n", cmd[0], cmd[1], cmd[2], strerror(errno));
27+
}
28+
}
29+
}
30+
return succeeded;
31+
}
32+
33+
THolder<google_breakpad::ExceptionHandler> Handler;
34+
};
35+
36+
TMinidumper Minidumper;

ydb/library/breakpad/ya.make

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
LIBRARY()
2+
3+
IF (OS_LINUX)
4+
PEERDIR(
5+
contrib/libs/breakpad/src
6+
contrib/libs/breakpad/src/client/linux
7+
)
8+
9+
SRCS(
10+
GLOBAL minidumps.cpp
11+
)
12+
ENDIF()
13+
14+
END()

ydb/library/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ RECURSE(
77
arrow_parquet
88
backup
99
benchmarks
10+
breakpad
1011
chunks_limiter
1112
folder_service
1213
formats
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import yatest.common
2+
import os
3+
from ydb.tests.library.harness.kikimr_runner import KiKiMR
4+
5+
6+
def test_create_minidump():
7+
dump_path = os.path.join(yatest.common.tempfile.gettempdir(), 'dumps1')
8+
os.makedirs(dump_path, exist_ok=True)
9+
os.environ['BREAKPAD_MINIDUMPS_PATH'] = dump_path
10+
cluster = KiKiMR()
11+
cluster.start()
12+
for node in cluster.nodes.values():
13+
node.send_signal(6)
14+
try:
15+
cluster.stop()
16+
except RuntimeError:
17+
pass
18+
assert len(os.listdir(dump_path)) == len(cluster.nodes)
19+
20+
21+
def test_minidump_script():
22+
temp_dir = yatest.common.tempfile.gettempdir()
23+
dump_path = os.path.join(temp_dir, 'dumps2')
24+
script_path = os.path.join(temp_dir, 'minidump_script.sh')
25+
os.makedirs(dump_path, exist_ok=True)
26+
with open(script_path, 'w') as f:
27+
f.write(
28+
'#!/usr/bin/bash\n'
29+
'SUCCESS=$1\n'
30+
'PATH=$2\n'
31+
'echo $SUCCESS >${PATH}.success\n'
32+
)
33+
os.chmod(script_path, 0o777)
34+
os.environ['BREAKPAD_MINIDUMPS_SCRIPT'] = script_path
35+
os.environ['BREAKPAD_MINIDUMPS_PATH'] = dump_path
36+
cluster = KiKiMR()
37+
cluster.start()
38+
for node in cluster.nodes.values():
39+
node.send_signal(6)
40+
try:
41+
cluster.stop()
42+
except RuntimeError:
43+
pass
44+
files = os.listdir(dump_path)
45+
dmps = list(filter(lambda x: x.endswith('.dmp'), files))
46+
successes = list(filter(lambda x: x.endswith('.dmp.success'), files))
47+
assert len(dmps) == len(cluster.nodes)
48+
assert len(successes) == len(cluster.nodes)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
IF (OS_LINUX)
2+
3+
PY3TEST()
4+
5+
TEST_SRCS(
6+
test_break.py
7+
)
8+
9+
SIZE(MEDIUM)
10+
11+
ENV(YDB_DRIVER_BINARY="ydb/apps/ydbd/ydbd")
12+
13+
PEERDIR(
14+
ydb/tests/library
15+
)
16+
17+
DEPENDS(
18+
ydb/apps/ydbd
19+
)
20+
21+
22+
END()
23+
24+
ENDIF()

ydb/tests/functional/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ RECURSE(
1515
kqp
1616
large_serializable
1717
limits
18+
minidumps
1819
postgresql
1920
query_cache
2021
rename

0 commit comments

Comments
 (0)