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 >
