forked from OSchip/llvm-project
[ORC] Use native Errors rather than converted std::error_codes for ORC RPC.
llvm-svn: 300155
This commit is contained in:
parent
b3f5742551
commit
22bc7b9648
|
@ -27,26 +27,15 @@ enum class OrcErrorCode : int {
|
|||
RemoteMProtectAddrUnrecognized,
|
||||
RemoteIndirectStubsOwnerDoesNotExist,
|
||||
RemoteIndirectStubsOwnerIdAlreadyInUse,
|
||||
RPCConnectionClosed,
|
||||
RPCCouldNotNegotiateFunction,
|
||||
RPCResponseAbandoned,
|
||||
UnexpectedRPCCall,
|
||||
UnexpectedRPCResponse,
|
||||
UnknownRPCFunction
|
||||
};
|
||||
|
||||
std::error_code orcError(OrcErrorCode ErrCode);
|
||||
|
||||
class RPCFunctionNotSupported : public ErrorInfo<RPCFunctionNotSupported> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
RPCFunctionNotSupported(std::string RPCFunctionSignature);
|
||||
std::error_code convertToErrorCode() const override;
|
||||
void log(raw_ostream &OS) const override;
|
||||
const std::string &getFunctionSignature() const;
|
||||
private:
|
||||
std::string RPCFunctionSignature;
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
||||
|
|
|
@ -32,6 +32,109 @@ namespace llvm {
|
|||
namespace orc {
|
||||
namespace rpc {
|
||||
|
||||
/// Base class of all fatal RPC errors (those that necessarily result in the
|
||||
/// termination of the RPC session).
|
||||
class RPCFatalError : public ErrorInfo<RPCFatalError> {
|
||||
public:
|
||||
static char ID;
|
||||
};
|
||||
|
||||
/// RPCConnectionClosed is returned from RPC operations if the RPC connection
|
||||
/// has already been closed due to either an error or graceful disconnection.
|
||||
class ConnectionClosed : public ErrorInfo<ConnectionClosed> {
|
||||
public:
|
||||
static char ID;
|
||||
std::error_code convertToErrorCode() const override;
|
||||
void log(raw_ostream &OS) const override;
|
||||
};
|
||||
|
||||
/// BadFunctionCall is returned from handleOne when the remote makes a call with
|
||||
/// an unrecognized function id.
|
||||
///
|
||||
/// This error is fatal because Orc RPC needs to know how to parse a function
|
||||
/// call to know where the next call starts, and if it doesn't recognize the
|
||||
/// function id it cannot parse the call.
|
||||
template <typename FnIdT, typename SeqNoT>
|
||||
class BadFunctionCall
|
||||
: public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BadFunctionCall(FnIdT FnId, SeqNoT SeqNo)
|
||||
: FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {}
|
||||
|
||||
std::error_code convertToErrorCode() const override {
|
||||
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||
}
|
||||
|
||||
void log(raw_ostream &OS) const override {
|
||||
OS << "Call to invalid RPC function id '" << FnId << "' with "
|
||||
"sequence number " << SeqNo;
|
||||
}
|
||||
|
||||
private:
|
||||
FnIdT FnId;
|
||||
SeqNoT SeqNo;
|
||||
};
|
||||
|
||||
template <typename FnIdT, typename SeqNoT>
|
||||
char BadFunctionCall<FnIdT, SeqNoT>::ID = 0;
|
||||
|
||||
/// InvalidSequenceNumberForResponse is returned from handleOne when a response
|
||||
/// call arrives with a sequence number that doesn't correspond to any in-flight
|
||||
/// function call.
|
||||
///
|
||||
/// This error is fatal because Orc RPC needs to know how to parse the rest of
|
||||
/// the response call to know where the next call starts, and if it doesn't have
|
||||
/// a result parser for this sequence number it can't do that.
|
||||
template <typename SeqNoT>
|
||||
class InvalidSequenceNumberForResponse
|
||||
: public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
InvalidSequenceNumberForResponse(SeqNoT SeqNo)
|
||||
: SeqNo(std::move(SeqNo)) {}
|
||||
|
||||
std::error_code convertToErrorCode() const override {
|
||||
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||
};
|
||||
|
||||
void log(raw_ostream &OS) const override {
|
||||
OS << "Response has unknown sequence number " << SeqNo;
|
||||
}
|
||||
private:
|
||||
SeqNoT SeqNo;
|
||||
};
|
||||
|
||||
template <typename SeqNoT>
|
||||
char InvalidSequenceNumberForResponse<SeqNoT>::ID = 0;
|
||||
|
||||
/// This non-fatal error will be passed to asynchronous result handlers in place
|
||||
/// of a result if the connection goes down before a result returns, or if the
|
||||
/// function to be called cannot be negotiated with the remote.
|
||||
class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
std::error_code convertToErrorCode() const override;
|
||||
void log(raw_ostream &OS) const override;
|
||||
};
|
||||
|
||||
/// This error is returned if the remote does not have a handler installed for
|
||||
/// the given RPC function.
|
||||
class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
CouldNotNegotiate(std::string Signature);
|
||||
std::error_code convertToErrorCode() const override;
|
||||
void log(raw_ostream &OS) const override;
|
||||
const std::string &getSignature() const { return Signature; }
|
||||
private:
|
||||
std::string Signature;
|
||||
};
|
||||
|
||||
template <typename DerivedFunc, typename FnT> class Function;
|
||||
|
||||
// RPC Function class.
|
||||
|
@ -500,7 +603,7 @@ public:
|
|||
|
||||
// Create an error instance representing an abandoned response.
|
||||
static Error createAbandonedResponseError() {
|
||||
return errorCodeToError(orcError(OrcErrorCode::RPCResponseAbandoned));
|
||||
return make_error<ResponseAbandoned>();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -814,12 +917,9 @@ public:
|
|||
if (auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation, false))
|
||||
FnId = *FnIdOrErr;
|
||||
else {
|
||||
// This isn't a channel error so we don't want to abandon other pending
|
||||
// responses, but we still need to run the user handler with an error to
|
||||
// let them know the call failed.
|
||||
if (auto Err = Handler(errorCodeToError(
|
||||
orcError(OrcErrorCode::UnknownRPCFunction))))
|
||||
report_fatal_error(std::move(Err));
|
||||
// Negotiation failed. Notify the handler then return the negotiate-failed
|
||||
// error.
|
||||
cantFail(Handler(make_error<ResponseAbandoned>()));
|
||||
return FnIdOrErr.takeError();
|
||||
}
|
||||
|
||||
|
@ -885,7 +985,8 @@ public:
|
|||
return I->second(C, SeqNo);
|
||||
|
||||
// else: No handler found. Report error to client?
|
||||
return errorCodeToError(orcError(OrcErrorCode::UnexpectedRPCCall));
|
||||
return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId,
|
||||
SeqNo);
|
||||
}
|
||||
|
||||
/// Helper for handling setter procedures - this method returns a functor that
|
||||
|
@ -995,7 +1096,8 @@ protected:
|
|||
// Unlock the pending results map to prevent recursive lock.
|
||||
Lock.unlock();
|
||||
abandonPendingResponses();
|
||||
return errorCodeToError(orcError(OrcErrorCode::UnexpectedRPCResponse));
|
||||
return make_error<
|
||||
InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1041,7 +1143,7 @@ protected:
|
|||
Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
|
||||
RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
|
||||
if (*RemoteIdOrErr == getInvalidFunctionId())
|
||||
return make_error<RPCFunctionNotSupported>(Func::getPrototype());
|
||||
return make_error<CouldNotNegotiate>(Func::getPrototype());
|
||||
return *RemoteIdOrErr;
|
||||
} else
|
||||
return RemoteIdOrErr.takeError();
|
||||
|
@ -1049,7 +1151,7 @@ protected:
|
|||
|
||||
// No key was available in the map and we weren't allowed to try to
|
||||
// negotiate one, so return an unknown function error.
|
||||
return make_error<RPCFunctionNotSupported>(Func::getPrototype());
|
||||
return make_error<CouldNotNegotiate>(Func::getPrototype());
|
||||
}
|
||||
|
||||
using WrappedHandlerFn = std::function<Error(ChannelT &, SequenceNumberT)>;
|
||||
|
|
|
@ -64,6 +64,12 @@ public:
|
|||
/// using std::error_code. It will be removed in the future.
|
||||
virtual std::error_code convertToErrorCode() const = 0;
|
||||
|
||||
// Returns the class ID for this type.
|
||||
static const void *classID() { return &ID; }
|
||||
|
||||
// Returns the class ID for the dynamic type of this ErrorInfoBase instance.
|
||||
virtual const void *dynamicClassID() const = 0;
|
||||
|
||||
// Check whether this instance is a subclass of the class identified by
|
||||
// ClassID.
|
||||
virtual bool isA(const void *const ClassID) const {
|
||||
|
@ -75,9 +81,6 @@ public:
|
|||
return isA(ErrorInfoT::classID());
|
||||
}
|
||||
|
||||
// Returns the class ID for this type.
|
||||
static const void *classID() { return &ID; }
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
|
||||
|
@ -316,11 +319,14 @@ template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
|
|||
template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
|
||||
class ErrorInfo : public ParentErrT {
|
||||
public:
|
||||
|
||||
static const void *classID() { return &ThisErrT::ID; }
|
||||
|
||||
const void *dynamicClassID() const override { return &ThisErrT::ID; }
|
||||
|
||||
bool isA(const void *const ClassID) const override {
|
||||
return ClassID == classID() || ParentErrT::isA(ClassID);
|
||||
}
|
||||
|
||||
static const void *classID() { return &ThisErrT::ID; }
|
||||
};
|
||||
|
||||
/// Special ErrorInfo subclass representing a list of ErrorInfos.
|
||||
|
@ -926,6 +932,8 @@ public:
|
|||
void log(raw_ostream &OS) const override;
|
||||
std::error_code convertToErrorCode() const override;
|
||||
|
||||
const std::string &getMessage() const { return Msg; }
|
||||
|
||||
private:
|
||||
std::string Msg;
|
||||
std::error_code EC;
|
||||
|
|
|
@ -6,6 +6,7 @@ add_llvm_library(LLVMOrcJIT
|
|||
OrcCBindings.cpp
|
||||
OrcError.cpp
|
||||
OrcMCJITReplacement.cpp
|
||||
RPCUtils.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
|
||||
|
|
|
@ -39,14 +39,16 @@ public:
|
|||
return "Remote indirect stubs owner does not exist";
|
||||
case OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse:
|
||||
return "Remote indirect stubs owner Id already in use";
|
||||
case OrcErrorCode::RPCConnectionClosed:
|
||||
return "RPC connection closed";
|
||||
case OrcErrorCode::RPCCouldNotNegotiateFunction:
|
||||
return "Could not negotiate RPC function";
|
||||
case OrcErrorCode::RPCResponseAbandoned:
|
||||
return "RPC response abandoned";
|
||||
case OrcErrorCode::UnexpectedRPCCall:
|
||||
return "Unexpected RPC call";
|
||||
case OrcErrorCode::UnexpectedRPCResponse:
|
||||
return "Unexpected RPC response";
|
||||
case OrcErrorCode::UnknownRPCFunction:
|
||||
return "Unknown RPC function";
|
||||
}
|
||||
llvm_unreachable("Unhandled error code");
|
||||
}
|
||||
|
@ -58,27 +60,10 @@ static ManagedStatic<OrcErrorCategory> OrcErrCat;
|
|||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
char RPCFunctionNotSupported::ID = 0;
|
||||
|
||||
std::error_code orcError(OrcErrorCode ErrCode) {
|
||||
typedef std::underlying_type<OrcErrorCode>::type UT;
|
||||
return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
|
||||
}
|
||||
|
||||
RPCFunctionNotSupported::RPCFunctionNotSupported(std::string RPCFunctionSignature)
|
||||
: RPCFunctionSignature(std::move(RPCFunctionSignature)) {}
|
||||
|
||||
std::error_code RPCFunctionNotSupported::convertToErrorCode() const {
|
||||
return orcError(OrcErrorCode::UnknownRPCFunction);
|
||||
}
|
||||
|
||||
void RPCFunctionNotSupported::log(raw_ostream &OS) const {
|
||||
OS << "Could not negotiate RPC function '" << RPCFunctionSignature << "'";
|
||||
}
|
||||
|
||||
const std::string &RPCFunctionNotSupported::getFunctionSignature() const {
|
||||
return RPCFunctionSignature;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -604,10 +604,10 @@ TEST(DummyRPC, TestAPICalls) {
|
|||
|
||||
{
|
||||
auto Err = DummyCallsAll::negotiate(Client);
|
||||
EXPECT_EQ(errorToErrorCode(std::move(Err)).value(),
|
||||
static_cast<int>(OrcErrorCode::UnknownRPCFunction))
|
||||
<< "Expected 'UnknownRPCFunction' error for attempted negotiate of "
|
||||
EXPECT_TRUE(Err.isA<CouldNotNegotiate>())
|
||||
<< "Expected CouldNotNegotiate error for attempted negotiate of "
|
||||
"unsupported function";
|
||||
consumeError(std::move(Err));
|
||||
}
|
||||
|
||||
ServerThread.join();
|
||||
|
|
Loading…
Reference in New Issue