blob: a3e6ebf6aa88d83f0b25415a77108c39f0724640 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <array>
#include <memory>
#include <queue>
#include "lib/fxl/files/unique_fd.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/strings/string_view.h"
#include "lib/fsl/tasks/message_loop.h"
#include "exception_port.h"
#include "io_loop.h"
#include "process.h"
#include "thread.h"
namespace debugserver {
// Server implements the main loop and handles commands.
//
// NOTE: This class is generally not thread safe. Care must be taken when
// calling methods such as set_current_process() and SetCurrentThread()
// which modify its internal state.
class Server : public IOLoop::Delegate, public Process::Delegate {
public:
// Starts the main loop, and returns when the main loop exits.
// Returns true if the main loop exits cleanly, or false in the case of an
// error.
// TODO(armansito): More clearly define the error scenario.
// TODO(dje): This mightn't need to be virtual, but it provides consistency
// among the uses.
virtual bool Run() = 0;
// Returns a raw pointer to the current inferior. The instance pointed to by
// the returned pointer is owned by this Server instance and should not be
// deleted.
Process* current_process() const { return current_process_.get(); }
// Sets the current process. This cleans up the current process (if any) and
// takes ownership of |process|.
void set_current_process(Process* process) {
current_process_.reset(process);
}
// Returns a raw pointer to the current thread.
Thread* current_thread() const { return current_thread_.get(); }
// Assigns the current thread.
void SetCurrentThread(Thread* thread);
// Returns a mutable reference to the main message loop. The returned instance
// is owned by this Server instance and should not be deleted.
fsl::MessageLoop* message_loop() { return &message_loop_; }
// Returns a mutable reference to the exception port. The returned instance is
// owned by this Server instance and should not be deleted.
ExceptionPort* exception_port() { return &exception_port_; }
// Call this to schedule termination of gdbserver.
// Any outstanding messages will be sent first.
// N.B. The Server will exit its main loop asynchronously so any
// subsequently posted tasks will be dropped.
void PostQuitMessageLoop(bool status);
protected:
Server();
virtual ~Server();
// Sets the run status and quits the main message loop.
void QuitMessageLoop(bool status);
// The current thread under debug. We only keep a weak pointer here, since the
// instance itself is owned by a Process and may get removed.
fxl::WeakPtr<Thread> current_thread_;
// The main loop.
fsl::MessageLoop message_loop_;
// The IOLoop used for blocking I/O operations over |client_sock_|.
// |message_loop_| and |client_sock_| both MUST outlive |io_loop_|. We take
// care to clean it up in the destructor.
std::unique_ptr<IOLoop> io_loop_;
// File descriptor for the socket (or terminal) used for communication.
// TODO(dje): Rename from *sock* after things are working.
fxl::UniqueFD client_sock_;
// The ExceptionPort used by inferiors to receive exceptions.
// (This is declared after |message_loop_| since that needs to have been
// created before this can be initialized).
ExceptionPort exception_port_;
// Strong pointer to the current inferior process that is being debugged.
// NOTE: This must be declared after |exception_port_| above, since the
// process may do work in its destructor to detach itself from
// |exception_port_|.
std::unique_ptr<Process> current_process_;
// Stores the global error state. This is used to determine the return value
// for "Run()" when |message_loop_| exits.
bool run_status_;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(Server);
};
} // namespace debugserver