我在我的一个Thrift函数定义中使用oneway
修饰符:
...
oneway void secret_function(1: string x, 2: string y),
...
通过Thrift生成相应的Erlang代码时,将其转换为:
...
function_info('secret_function', reply_type) ->
oneway_void;
function_info('secret_function', exceptions) ->
{struct, []};
...
请注意那里的oneway_void
原子。
执行secret_function
函数时,出现以下错误:
=ERROR REPORT==== 2-Sep-2010::18:17:08 ===
oneway void secret_function threw error which must be ignored: {error,
function_clause,
[{thrift_protocol,
term_to_typeid,
[oneway_void]},
{thrift_protocol,
struct_write_loop,
3},
{thrift_protocol,
write,2},
{thrift_processor,
send_reply,
4},
{thrift_processor,
handle_function,
2},
{thrift_processor,
loop,1}]}
独立于用户代码中包含的可能错误,这里使用thrift_protocol:term_to_typeid/1
原子作为参数调用oneway_void
函数,这会导致函数子句。实际上,从代码中读取(thrift_protocol.erl):
...
term_to_typeid(void) -> ?tType_VOID;
term_to_typeid(bool) -> ?tType_BOOL;
term_to_typeid(byte) -> ?tType_BYTE;
term_to_typeid(double) -> ?tType_DOUBLE;
term_to_typeid(i16) -> ?tType_I16;
term_to_typeid(i32) -> ?tType_I32;
term_to_typeid(i64) -> ?tType_I64;
term_to_typeid(string) -> ?tType_STRING;
term_to_typeid({struct, _}) -> ?tType_STRUCT;
term_to_typeid({map, _, _}) -> ?tType_MAP;
term_to_typeid({set, _}) -> ?tType_SET;
term_to_typeid({list, _}) -> ?tType_LIST.
...
一个错误?还有其他解释吗?为什么oneway_void
被传递给该函数?
答案 0 :(得分:0)
我想我知道幕后发生了什么。
我的Erlang代码(secret_function/2
)正在返回{ok,pid()}而不是简单的确定。
即使这在概念上是错误的,因为我宣布了函数oneway_void
,我花了一段时间来确定问题的原因。
也许我们可以调整Thrift中的handle_succes
函数,使其行为与h andle_function_catch
已经完成的行为相同。
这就是handle_function_catch
目前的样子:
...
case {ErrType, ErrData} of
_ when IsOneway ->
Stack = erlang:get_stacktrace(),
error_logger:warning_msg(
"oneway void ~p threw error which must be ignored: ~p",
[Function, {ErrType, ErrData, Stack}]),
{State, ok};
...
即使该函数声明为oneway_void
,当引发异常时,也会报告该问题。根据相同的推理,潜在的新handle_success函数可能如下所示:
handle_success(State = #thrift_processor{service = Service},
Function,
Result) ->
ReplyType = Service:function_info(Function, reply_type),
StructName = atom_to_list(Function) ++ "_result",
case Result of
{reply, ReplyData} when ReplyType =:= oneway_void ->
Stack = erlang:get_stacktrace(),
error_logger:warning_msg(
"oneway void ~p sent reply which must be ignored: ~p",
[Function, {ReplyData, Stack}]),
{State, ok};
{reply, ReplyData} ->
Reply = {{struct, [{0, ReplyType}]}, {StructName, ReplyData}},
send_reply(State, Function, ?tMessageType_REPLY, Reply);
ok when ReplyType == {struct, []} ->
send_reply(State, Function, ?tMessageType_REPLY, {ReplyType, {StructName}});
ok when ReplyType == oneway_void ->
%% no reply for oneway void
{State, ok}
end.
这里我只是检查函数是否定义为oneway_void
并且如果这是真的并且我仍然收到不同于原子ok
的返回值,我报告事故,仍然忽略返回值。
这是开发人员使用更新的handle_success
函数看到的内容:
=ERROR REPORT==== 7-Sep-2010::11:06:43 ===
oneway void secret_function sent reply which must be ignored: {{ok,
<0.262.0>},
[]}
这可以挽救你的生命至少一次(cit。)。