- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经根据 http://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php 上的指南为 CZMQ 编写了一些 OCaml 绑定(bind),这似乎工作得很好。例如这里的 zstr_send:
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));
}
我可以在我的大部分代码中使用这些绑定(bind)发送和接收消息。但是,我有一个场景,我想在信号处理程序内部进行发送和接收,最后在其他代码的后台进行消息传递。以这个简化的例子为例:
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)
;;
从顶层开始,输出失败:
enter handler
0
end handler
Fatal error: exception Sys_blocked_io
类似于上面的 OCaml 的 C 代码工作得很好。 OCaml 添加到导致此异常的等式中的是什么?
最佳答案
有两个潜在的问题:
在信号处理程序中,您只能调用异步信号安全 函数。大多数函数都不是异步信号安全的。
限制的原因是一个函数可以在同一个函数的执行过程中被调用。因此,内部状态可能会被破坏。很少有函数是异步信号安全的,任何动态分配内存的函数都不是。在 OCaml 中,许多分配发生在“幕后”,因此您的代码很可能不是异步信号安全的。
在您的例子中,您正在调用一个写入标准输出的函数。在 C 中,这是 从不 异步信号安全的,只有一个异常(exception):原始 write()
函数。这是原始系统调用(对文件描述符进行操作)并且是异步信号安全的,原因很简单,因为内核本身并不关心您是否在信号处理程序中,并且在将控制权返回给您之前已经完全清理干净。
从信号处理程序调用不安全函数,当信号是异步的(这里的情况)并且它本身被中断时,不安全函数在 C 中是未定义的行为。这意味着任何事情都可能发生——包括您的程序正常工作,但也包括段错误或其他错误,以及允许攻击者执行任意代码。这通常与 C 等低级语言相关联,并且通常不会出现在 OCaml 中。
OCaml 使用了一个巧妙的技巧:当接收到已在 OCaml 中设置了处理程序的信号时,它会推迟执行处理程序,直到安全点。结果是在处理程序中将未装箱 数量设置到ref
变量中是安全的。但是,print
等其他函数可能不可重入,因为它们可能具有内部状态。通常,在信号处理程序中,您应该尽量避免做比设置标志并迅速返回更多的事情。在 OCaml 中,标志应该是 31 位或 63 位整数,或者 bool 值,因为它们是未装箱的。在 C 中,标志必须是 volatile sig_atomic_t
或(我不确定)C11 原子类型。
@TheCodeArtist 给出了错误的其他可能原因。
关于从信号处理程序调用 OCaml 包装的 ZeroMQ 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16653153/
我正在尝试以更命令的方式表达一组链式调用。例如,图像我们有一个函数,它接受一个列表和一个元素,并将该元素附加到列表的末尾: let insert l e = l @ [e] 我想一次插入几个元素。
是否有一个完整的列表(或详尽的规则)可以给 OCaml 中的自定义中缀运算符提供可能的名称? 最佳答案 如 OCaml manual 中所述, 中缀运算符必须匹配正则表达式 [-=<>@^|&+*/$
我想开始使用 OCaml 编程。由于我是 Windows 用户,我知道最好使用 Netbeans 的 OCaml 插件。 我已经从以下链接下载了上述插件:http://ocamlplugin.loki
能够做到这一点以获得最大速度不是很重要吗? 编辑: 例如,Clojure 有 map ,它使用多个核心。 Harrop 博士写道(2011 年 1 月 9 日): 语言中添加的新功能,例如一流 OCa
我在 x86 机器上用字节码编译 OCaml 程序,然后将字节码传输到 ppc64 机器。假设 ppc64 机器有 ocamlrun(为 ppc64 编译),我能在 ppc64 架构上执行我的程序吗?
我创建了一个新模块,它只是名称很长的模块的较短别名: module M = ModuleWithLongName 我处于最终可执行文件的大小很重要的情况。上面的构造是由编译器合理处理的吗(即 M 实际
我在使用 ocaml 时遇到了麻烦。 我想创建一个函数,每次调用它时都会增加我的计数器,并将我的 vargen 字符串与计数器编号连接起来,然后返回这个新字符串。 我没有成功的做法是: let (co
我正在学习 OCaml,我对变量的不变性有点困惑。根据我正在阅读的书,变量是不可变的。到目前为止一切顺利,但为什么我可以这样做: let foo = 42 let foo = 4242 我错过了什么?
非尾递归组合函数可以这样写: let rec combinations l k = if k List.length l then [] else if k = 1 then List.ma
我有一段包含camlp4引用的代码。 let f_name = "my_func" > 运行此程序后 camlp4of ,它产生这个: Ast.StExp (_loc, (Ast.ExAp
如何在 OCaml 中模拟这个 Python 习语? if __name__=="__main__": main() 见 RosettaCode其他编程语言中的示例。 最佳答案 Ocaml 中没
我开始学习 Ocaml,使用 hickey book ,我被困在练习 3.4,第 9 部分 让 x x = x + 1 在 x 2 运算结果为3 ,但我不明白为什么? 最佳答案 当你写 let x x
Rust具有线性系统。有什么(好的)方法可以在 OCaml 中模拟这个吗?例如,当使用 ocaml-lua 时,我想确保仅当 Lua 处于特定状态(堆栈顶部的表等)时才调用某些函数。 编辑 :这是最近
在 OCaml?我知道非常酷的Bitstring图书馆,但是 虽然这将是在某些协议(protocol)中解析二进制数据的好方法, 它不支持异或或移位等按位运算。 我相信该库使用的底层数据结构是 只是
我们可以像这样构造一个无限列表: let rec endless = 1::endless 我认为它会吃掉所有的内存,但是当我在 utop 中尝试时,好像不是这样。 utop显示列表已构建: val
是否可以通过合并列表的元素而不是创建列表的列表来创建列表? 例子: List.combine ["A";"B"] ["C";"D"];; 我得到: [("A", "C"); ("B", "D")] 有
我想在 OCaml 中创建一个查找表。该表将有 7000 多个条目,在查找时(通过 int)返回一个字符串。用于此任务的适当数据结构是什么?表是否应该从基本代码中外部化,如果是这样,如何“包括”查找表
我正在评估 Ocaml 顶层中的一段非常简单的代码: let p5 () = print_int 5;; p5 ();; print_string "*************************
记录和元组之间是否有任何区别而不仅仅是句法差异? 有性能差异吗? 元组和记录的实现是否相同? 您是否有可以使用元组完成但不能使用记录完成的事情的示例(和 反之)? 最佳答案 模数语法它们几乎相同。主要
OCaml 中的 ` 运算符有什么作用? let int_of_meth = function | `GET -> 0 | `POST -> 1 | `PUT ->
我是一名优秀的程序员,十分优秀!