|
| 1 | +#!/usr/bin/env bash |
| 2 | +# This test reproduces a segfault that occurs when send_profile_events is enabled |
| 3 | +# via SQL SETTINGS clause after being disabled at the connection level. |
| 4 | +# |
| 5 | +# The bug: profile_queue is only created if send_profile_events was true during |
| 6 | +# connection setup. If it was false but then enabled via SQL SETTINGS, the queue |
| 7 | +# is null and getProfileEvents() crashes when trying to lock the mutex. |
| 8 | +# |
| 9 | +# The crash happens at ProfileEventsExt.cpp:169 when calling profile_queue->tryPop() |
| 10 | +# with a null profile_queue pointer. |
| 11 | +# |
| 12 | +# NOTE: This bug is TCP protocol specific. HTTP doesn't send profile events. |
| 13 | +# NOTE: clickhouse-client cannot reproduce this because it parses the query |
| 14 | +# client-side and merges SQL SETTINGS into protocol settings before sending |
| 15 | +# (see ClientBase.cpp:2337 - InterpreterSetQuery::applySettingsFromQuery). |
| 16 | +# We use Python clickhouse-driver which sends settings and query separately. |
| 17 | + |
| 18 | +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) |
| 19 | +# shellcheck source=../shell_config.sh |
| 20 | +. "$CURDIR"/../shell_config.sh |
| 21 | + |
| 22 | +# Check if clickhouse-driver is available |
| 23 | +if ! python3 -c "import clickhouse_driver" 2>/dev/null; then |
| 24 | + echo "1" |
| 25 | + echo "OK" |
| 26 | + exit 0 |
| 27 | +fi |
| 28 | + |
| 29 | +# Connect with send_profile_events disabled at the connection level, |
| 30 | +# but enable it via SQL SETTINGS clause in the query. |
| 31 | +# Before the fix: server crashes with SIGSEGV |
| 32 | +# After the fix: query executes successfully |
| 33 | +python3 << EOF |
| 34 | +from clickhouse_driver import Client |
| 35 | +
|
| 36 | +client = Client( |
| 37 | + host='${CLICKHOUSE_HOST:-localhost}', |
| 38 | + port=${CLICKHOUSE_PORT_TCP:-9000}, |
| 39 | + settings={'send_profile_events': False}, |
| 40 | + send_receive_timeout=5 |
| 41 | +) |
| 42 | +
|
| 43 | +# This query would crash unpatched servers |
| 44 | +result = client.execute('SELECT 1 SETTINGS send_profile_events = 1') |
| 45 | +print(result[0][0]) |
| 46 | +
|
| 47 | +print("OK") |
| 48 | +EOF |
0 commit comments