私はhttp://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.phpのガイドに基づいてCZMQ用のOCamlバインディングを作成しましたが、これはかなりうまくいくようです。例えば、ここにzstr_sendです:シグナルハンドラからOCamlでラップされたZeroMQコードを呼び出す
CAMLprim value
caml_zstr_send(value socket_val, value string_val)
{
CAMLparam2 (socket_val, string_val);
void *sock = CAML_CZMQ_zsocket_val(socket_val);
char *string = String_val(string_val);
int rc = zstr_send(sock, string);
CAMLreturn (Val_int(rc));
}
は、私は自分のコードのほとんどにこれらのバインディングを使用してうまくメッセージを送受信することができます。しかし、私は、シグナルハンドラの内部で送受信を行い、他のコードのバックグラウンドでメッセージを受け渡しするというシナリオを持っています。この簡単な例ください:トップレベルから
open ZMQ
exception SocketBindFailure
let bg_ctx = zctx_new();;
let pub_sock = zsocket_new bg_ctx ZMQ_PUB;;
let handler _ =
print_endline "enter handler";
print_endline (string_of_int (zstr_send pub_sock "hello"));
print_endline "end handler";
;;
let() =
(try (
(* bind pub socket *)
let rc = zsocket_bind pub_sock "tcp://*:5556" in
if (rc < 0) then (raise SocketBindFailure);
Sys.set_signal
Sys.sigalrm
(Sys.Signal_handle handler);
ignore
(Unix.setitimer
Unix.ITIMER_REAL
{ Unix.it_interval = 0.01 ; Unix.it_value = 0.01 });
(* do some work *)
)
with
| SocketBindFailure -> raise SocketBindFailure)
;;
を、これは出力で失敗します。OCamlのと似
enter handler
0
end handler
Fatal error: exception Sys_blocked_io
Cコードは、上記だけで正常に動作します。 OCamlはこの例外の原因となっている式に何を追加していますか?
一般に、シグナルハンドラ内からルーチンを呼び出すのは、コードを監査しているときは赤いフラグです。理由はさまざまですが、その要点はルーチンが非同期で安全であることを100%確実にしなければならないということです。 [詳細はこちら](https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers) –
Iあなたが例外を持った理由を教えてもらえませんが、ハンドラ内でI/Oを試みることで、CやOCamlのように危険な状態になっていると言うことはできません。上記のリンクは、シグナルハンドラの呼び出しを安全に記録するためのレシピを提供します。 –
情報ありがとう、Dave。私は別のアプローチをとっていきます。 – user1494672