Hi David,

Yes, sending an empty batch before stream finishing helped us, thanks! Will 
wait for a proper fix.

btw, changing the problematic line to:

RETURN_NOT_OK(stream_->Finish(Status::OK()));
return nullptr;

fixes the issue.

Regards,
Igor

On 2022/11/14 14:55:46 David Li wrote:
> Hi Igor, 
> 
> A workaround might be to send a single empty batch in the case of an empty 
> stream. 
> 
> I tried reproducing with PyArrow 10 but couldn't get it to crash. I filed 
> ARROW-18320 [1] to look deeper.
> 
> [1]: https://issues.apache.org/jira/browse/ARROW-18320
> 
> Thanks,
> David
> 
> On Mon, Nov 14, 2022, at 07:18, Igor Seliverstov wrote:
> > Hi!
> > 
> > I have an issue on my project, we have a query execution engine that 
> > returns result data as a flight stream and c++ client that receives the 
> > stream. In case a query has no results but the result schema implies 
> > dictionary encoded fields in results we have client app crushed.
> > 
> > The cause is in cpp/src/arrow/flight/client.cc:461:
> > 
> > ::arrow::Result<std::unique_ptr<ipc::Message>> ReadNextMessage() override {
> > if (stream_finished_) {
> > return nullptr;
> > }
> > internal::FlightData* data;
> > {
> > auto guard = read_mutex_ ? std::unique_lock<std::mutex>(*read_mutex_)
> > : std::unique_lock<std::mutex>();
> > peekable_reader_->Next(&data);
> > }
> > if (!data) {
> > stream_finished_ = true;
> > return stream_->Finish(Status::OK()); // Here the issue
> > }
> > // Validate IPC message
> > auto result = data->OpenMessage();
> > if (!result.ok()) {
> > return stream_->Finish(std::move(result).status());
> > }
> > *app_metadata_ = std::move(data->app_metadata);
> > return result;
> > }
> > 
> > The method returns Result object while stream_Finish(..) returns a Status. 
> > So there is an implicit conversion from Status to Result that causes 
> > Result(Status) constructor to be called, but the constructor expects only 
> > error statuses which in turn causes the app to be failed:
> > 
> > /// Constructs a Result object with the given non-OK Status object. All
> > /// calls to ValueOrDie() on this object will abort. The given `status` must
> > /// not be an OK status, otherwise this constructor will abort.
> > ///
> > /// This constructor is not declared explicit so that a function with a 
> > return
> > /// type of `Result<T>` can return a Status object, and the status will be
> > /// implicitly converted to the appropriate return type as a matter of
> > /// convenience.
> > ///
> > /// \param status The non-OK Status object to initialize to.
> > Result(const Status& status) noexcept // NOLINT(runtime/explicit)
> > : status_(status) {
> > if (ARROW_PREDICT_FALSE(status.ok())) {
> > internal::DieWithMessage(std::string("Constructed with a non-error status: 
> > ") +
> > status.ToString());
> > }
> > }
> > 
> > Is there a way to workaround or fix it? We use Arrow 6.0.0, but it seems 
> > that the issue exists in all future versions.
> > 
> > Regards,
> > Igor
> 

Reply via email to