我创建了一个模块,它以完全不同的方式透明地处理某些文件,作为 Erlangfile:open/2
和它返回的 IoDevice/文件描述符的替代品。在许多情况下,它只是简单地返回 Erlang 的结果file:open/2
,而在其他情况下,它返回一个通过 HTTP API(CloudFiles 或 AWS S3)读写的自定义 IoDevice。
最近这是一个普通的模块,但我一直在尝试将其转换gen_server
为更好地处理异步 HTTP 调用(以及其他原因)。这些自定义位运行良好,但我无法简单地file:open/2
从 a调用gen_server:handle_call/3
并返回生成的 IoDevice。问题是在我gen_server
打开文件以使用 IoDevice 回复后,gen_server:handle_info/2
我的gen_server
.
...
handle_call({open, Path, Flags}, _From, State) ->
Reply = case handle_external_file(Path) of
false -> file:open(Path, Flags);
true -> external_file:open(Path)
end,
%%
%% Reply is {ok,{file_descriptor,prim_file,{#Port<0.1896>,14}}}
%%
{reply, Reply, State};
...
handle_info(Message, State) ->
%%
%% Message is {#Port<0.1896>,{data,[3,0,0,0,0,0,0,0,0]}}
%%
io:format("UNEXPECTED MESSAGE: ~p~n", [Message]),
{noreply, State}
...
我认为这与文档中的以下内容有关:
IoDevice 实际上是处理文件的进程的 pid。此进程链接到最初打开文件的进程。如果与 IoDevice 链接的任何进程终止,则文件将被关闭并且进程本身将被终止。从此调用返回的 IoDevice 可用作 IO 函数的参数(请参阅 io(3))。
有没有办法从 a 打开文件gen_server
,将其 IoDevice 交给另一个进程?