Skip to content

Commit d687ab2

Browse files
authored
Merge pull request ClickHouse#89347 from ClickHouse/backport/25.8/89174
Backport ClickHouse#89174 to 25.8: Avoid possible data-races due to mutable exceptions while parsing Parquet
2 parents 75ef622 + 0c272ae commit d687ab2

File tree

8 files changed

+55
-2
lines changed

8 files changed

+55
-2
lines changed

base/poco/Foundation/include/Poco/Exception.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class Foundation_API Exception : public std::exception
8484
/// The copy can later be thrown again by
8585
/// invoking rethrow() on it.
8686

87-
virtual void rethrow() const;
87+
[[noreturn]] virtual void rethrow() const;
8888
/// (Re)Throws the exception.
8989
///
9090
/// This is useful for temporarily storing a

src/Access/Authentication.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ struct Authentication
3838
explicit Require(const String & realm_);
3939
const String & getRealm() const;
4040

41+
Require * clone() const override { return new Require(*this); }
42+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
43+
4144
private:
4245
const String realm;
4346
};

src/Client/ClientBase.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@ class LocalFormatError : public Exception
339339
{
340340
public:
341341
using Exception::Exception;
342+
343+
LocalFormatError * clone() const override { return new LocalFormatError(*this); }
344+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
342345
};
343346

344347

src/Common/Exception.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,4 +779,27 @@ ExecutionStatus ExecutionStatus::fromText(const std::string & data)
779779
return status;
780780
}
781781

782+
std::exception_ptr copyMutableException(std::exception_ptr ptr)
783+
{
784+
try
785+
{
786+
std::rethrow_exception(ptr);
787+
}
788+
catch (Poco::Exception & e)
789+
{
790+
try
791+
{
792+
e.rethrow();
793+
}
794+
catch (...)
795+
{
796+
return std::current_exception();
797+
}
798+
}
799+
catch (...)
800+
{
801+
return std::current_exception();
802+
}
803+
}
804+
782805
}

src/Common/Exception.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,4 +376,8 @@ T current_exception_cast()
376376
}
377377
}
378378

379+
/// Return copy of a current exception if it is a Poco::Exception (DB::Exception), since this exception is mutable, and returning reference is unsafe.
380+
/// And a reference otherwise.
381+
std::exception_ptr copyMutableException(std::exception_ptr ptr);
382+
379383
}

src/Common/mysqlxx/mysqlxx/Exception.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ struct Exception : public Poco::Exception
1414
int errnum() const { return code(); }
1515
const char * name() const noexcept override { return "mysqlxx::Exception"; }
1616
const char * className() const noexcept override { return "mysqlxx::Exception"; }
17+
18+
Exception * clone() const override { return new Exception(*this); }
19+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
1720
};
1821

1922

@@ -23,6 +26,9 @@ struct ConnectionFailed : public Exception
2326
explicit ConnectionFailed(const std::string & msg, int code = 0) : Exception(msg, code) {}
2427
const char * name() const noexcept override { return "mysqlxx::ConnectionFailed"; }
2528
const char * className() const noexcept override { return "mysqlxx::ConnectionFailed"; }
29+
30+
ConnectionFailed * clone() const override { return new ConnectionFailed(*this); }
31+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
2632
};
2733

2834

@@ -32,6 +38,9 @@ struct ConnectionLost : public Exception
3238
explicit ConnectionLost(const std::string & msg, int code = 0) : Exception(msg, code) {}
3339
const char * name() const noexcept override { return "mysqlxx::ConnectionLost"; }
3440
const char * className() const noexcept override { return "mysqlxx::ConnectionLost"; }
41+
42+
ConnectionLost * clone() const override { return new ConnectionLost(*this); }
43+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
3544
};
3645

3746

@@ -41,6 +50,9 @@ struct BadQuery : public Exception
4150
explicit BadQuery(const std::string & msg, int code = 0) : Exception(msg, code) {}
4251
const char * name() const noexcept override { return "mysqlxx::BadQuery"; }
4352
const char * className() const noexcept override { return "mysqlxx::BadQuery"; }
53+
54+
BadQuery * clone() const override { return new BadQuery(*this); }
55+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
4456
};
4557

4658

@@ -50,6 +62,9 @@ struct CannotParseValue : public Exception
5062
explicit CannotParseValue(const std::string & msg, int code = 0) : Exception(msg, code) {}
5163
const char * name() const noexcept override { return "mysqlxx::CannotParseValue"; }
5264
const char * className() const noexcept override { return "mysqlxx::CannotParseValue"; }
65+
66+
CannotParseValue * clone() const override { return new CannotParseValue(*this); }
67+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
5368
};
5469

5570

src/IO/S3Common.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class S3Exception : public Exception
4747

4848
bool isRetryableError() const;
4949

50+
S3Exception * clone() const override { return new S3Exception(*this); }
51+
void rethrow() const override { throw *this; } /// NOLINT(cert-err60-cpp)
52+
5053
private:
5154
Aws::S3::S3Errors code;
5255
};

src/Processors/Formats/Impl/ParquetBlockInputFormat.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1169,7 +1169,9 @@ Chunk ParquetBlockInputFormat::read()
11691169
if (background_exception)
11701170
{
11711171
is_stopped = true;
1172-
std::rethrow_exception(background_exception);
1172+
/// This exception can be mutated (addMessage()) in IInputFormat::generate(),
1173+
/// so we need to copy it (copyMutableException()) to avoid sharing mutable exception between multiple threads
1174+
std::rethrow_exception(copyMutableException(background_exception));
11731175
}
11741176
if (is_stopped)
11751177
return {};

0 commit comments

Comments
 (0)