1818#include " arrow/flight/server.h"
1919#include " arrow/flight/protocol-internal.h"
2020
21+ #include < signal.h>
22+ #include < atomic>
2123#include < cstdint>
2224#include < memory>
2325#include < string>
@@ -294,30 +296,101 @@ class FlightServiceImpl : public FlightService::Service {
294296 FlightServerBase* server_;
295297};
296298
297- struct FlightServerBase ::FlightServerBaseImpl {
298- std::unique_ptr<grpc::Server> server;
299+ #if (ATOMIC_INT_LOCK_FREE != 2 || ATOMIC_POINTER_LOCK_FREE != 2)
300+ #error "atomic ints and atomic pointers not always lock-free!"
301+ #endif
302+
303+ struct FlightServerBase ::Impl {
304+ std::string address_;
305+ std::unique_ptr<FlightServiceImpl> service_;
306+ std::unique_ptr<grpc::Server> server_;
307+
308+ // Signal handling
309+ std::vector<int > signals_;
310+ std::vector<struct sigaction > old_signal_handlers_;
311+ std::atomic<int > got_signal_;
312+ static thread_local std::atomic<Impl*> running_instance_;
313+
314+ static void HandleSignal (int signum);
315+
316+ void DoHandleSignal (int signum) {
317+ got_signal_ = signum;
318+ server_->Shutdown ();
319+ }
299320};
300321
301- FlightServerBase::FlightServerBase () { impl_.reset (new FlightServerBaseImpl); }
322+ thread_local std::atomic<FlightServerBase::Impl*>
323+ FlightServerBase::Impl::running_instance_;
324+
325+ void FlightServerBase::Impl::HandleSignal (int signum) {
326+ auto instance = running_instance_.load ();
327+ if (instance != nullptr ) {
328+ instance->DoHandleSignal (signum);
329+ }
330+ }
331+
332+ FlightServerBase::FlightServerBase () { impl_.reset (new Impl); }
302333
303334FlightServerBase::~FlightServerBase () {}
304335
305- void FlightServerBase::Run (int port) {
306- std::string address = " localhost:" + std::to_string (port);
336+ Status FlightServerBase::Init (int port) {
337+ impl_->address_ = " localhost:" + std::to_string (port);
338+ impl_->service_ .reset (new FlightServiceImpl (this ));
307339
308- FlightServiceImpl service (this );
309340 grpc::ServerBuilder builder;
310- builder.AddListeningPort (address, grpc::InsecureServerCredentials ());
311- builder.RegisterService (&service);
341+ builder.AddListeningPort (impl_->address_ , grpc::InsecureServerCredentials ());
342+ builder.RegisterService (impl_->service_ .get ());
343+
344+ impl_->server_ = builder.BuildAndStart ();
345+ return Status::OK ();
346+ }
312347
313- impl_->server = builder.BuildAndStart ();
314- std::cout << " Server listening on " << address << std::endl;
315- impl_->server ->Wait ();
348+ Status FlightServerBase::SetShutdownOnSignals (const std::vector<int > sigs) {
349+ impl_->signals_ = sigs;
350+ impl_->old_signal_handlers_ .clear ();
351+ return Status::OK ();
316352}
317353
354+ Status FlightServerBase::Serve () {
355+ impl_->got_signal_ = 0 ;
356+ impl_->running_instance_ = impl_.get ();
357+
358+ // Setup signal handlers
359+ impl_->old_signal_handlers_ .clear ();
360+ for (size_t i = 0 ; i < impl_->signals_ .size (); ++i) {
361+ int signum = impl_->signals_ [i];
362+ // Override with our own handler so as to stop the server.
363+ struct sigaction sa, old_handler;
364+ sa.sa_handler = &Impl::HandleSignal;
365+ sa.sa_flags = 0 ;
366+ sigemptyset (&sa.sa_mask );
367+ int ret = sigaction (signum, &sa, &old_handler);
368+ if (ret != 0 ) {
369+ return Status::IOError (" sigaction call failed" );
370+ }
371+ impl_->old_signal_handlers_ .push_back (old_handler);
372+ }
373+
374+ // TODO(wesm): How can we tell if the server failed to start for some reason?
375+ impl_->server_ ->Wait ();
376+ impl_->running_instance_ = nullptr ;
377+
378+ // Restore signal handlers
379+ for (size_t i = 0 ; i < impl_->signals_ .size (); ++i) {
380+ int ret = sigaction (impl_->signals_ [i], &impl_->old_signal_handlers_ [i], nullptr );
381+ if (ret != 0 ) {
382+ return Status::IOError (" sigaction call failed" );
383+ }
384+ }
385+
386+ return Status::OK ();
387+ }
388+
389+ int FlightServerBase::GotSignal () const { return impl_->got_signal_ ; }
390+
318391void FlightServerBase::Shutdown () {
319- DCHECK (impl_->server );
320- impl_->server ->Shutdown ();
392+ DCHECK (impl_->server_ );
393+ impl_->server_ ->Shutdown ();
321394}
322395
323396Status FlightServerBase::ListFlights (const Criteria* criteria,
@@ -327,7 +400,6 @@ Status FlightServerBase::ListFlights(const Criteria* criteria,
327400
328401Status FlightServerBase::GetFlightInfo (const FlightDescriptor& request,
329402 std::unique_ptr<FlightInfo>* info) {
330- std::cout << " GetFlightInfo" << std::endl;
331403 return Status::NotImplemented (" NYI" );
332404}
333405
0 commit comments