From 66156f508565dc0bc4d243ed49995d4db291d027 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Wed, 4 Feb 2015 08:05:17 +0300 Subject: [PATCH] dbms: fixed segfault when query was cancelled while merging aggregate states in calculation of TOTALS [#METR-14654]. --- .../DB/DataStreams/IProfilingBlockInputStream.h | 3 +++ dbms/src/Server/TCPHandler.cpp | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dbms/include/DB/DataStreams/IProfilingBlockInputStream.h b/dbms/include/DB/DataStreams/IProfilingBlockInputStream.h index f90e756034c..b8308083d0a 100644 --- a/dbms/include/DB/DataStreams/IProfilingBlockInputStream.h +++ b/dbms/include/DB/DataStreams/IProfilingBlockInputStream.h @@ -39,6 +39,9 @@ public: * Реализация по-умолчанию берёт их из себя или из первого дочернего источника, в котором они есть. * Переопределённый метод может провести некоторые вычисления. Например, применить выражение к totals дочернего источника. * Тотальных значений может не быть - тогда возвращается пустой блок. + * + * Вызывайте этот метод только после получения всех данных с помощью read, + * иначе будут проблемы, если какие-то данные в это же время вычисляются в другом потоке. */ virtual const Block & getTotals(); diff --git a/dbms/src/Server/TCPHandler.cpp b/dbms/src/Server/TCPHandler.cpp index 377c694c695..d9920be1bba 100644 --- a/dbms/src/Server/TCPHandler.cpp +++ b/dbms/src/Server/TCPHandler.cpp @@ -301,10 +301,14 @@ void TCPHandler::processOrdinaryQuery() } } - /// Если закончились данные, то отправим данные профайлинга и тотальные значения до - /// последнего нулевого блока, чтобы иметь возможность использовать - /// эту информацию в выводе суффикса output stream'а - if (!block) + /** Если закончились данные, то отправим данные профайлинга и тотальные значения до + * последнего нулевого блока, чтобы иметь возможность использовать + * эту информацию в выводе суффикса output stream'а. + * Если запрос был прерван, то вызывать методы sendTotals и другие нельзя, + * потому что мы прочитали ещё не все данные, и в это время могут производиться какие-то + * вычисления в других потоках. + */ + if (!block && !isQueryCancelled()) { sendTotals(); sendExtremes();