由于作品版权,我无法发布我的实际代码,所以我将尝试用简单的示例代码来展示我的问题。
我有一个 C 扩展,其简化版本如下所示:
#include <ruby.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
VALUE test(VALUE self, VALUE string);
void Init_module_name() {
module_name = rb_define_module("Modulename");
c_modulename = rb_define_class_under(modulename, "Class", rb_cObject);
rb_define_method(c_modulename, "test", test, 1);
e_ModuleNameError = rb_define_class_under(modulename, "Error", rb_eStandardError);
}
VALUE test(VALUE self, VALUE string) {
char *c_string = StringValueCStr(string);
int fd = open(c_string, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd == -1) {
rb_raise(e_ModuleNameError, "Failed to open file");
}
if (!isatty(fd)) {
rb_raise(e_ModuleNameError, "File is not a tty");
}
struct termios config;
int termios_ret = init_termios(config, fd)
if (termios_ret != OK) { // OK defined by enum in modulename's header
close(fd);
rb_raise(e_ModuleNameError, "Termios init failed.");
}
int success = write(fd, "I'm a string", str_length);
if (success < str_length) {
close(fd);
rb_raise(e_ModuleNameError, "Failed to write to file.");
}
close(fd);
return rb_str_new2("Success");
}
然后,需要这个的 ruby 代码如下所示:
require 'modulename'
class ModuleName
attr_acessor :file
def initialize(file)
@file = file
@object = Modulename::Class.new
end
def test
@object.test @file
end
end
然后在我的生产项目中调用它,例如:
require "modulename_ruby_file"
x = ModuleName "/dev/pts/1"
x.test
这是有趣的事情。当我在生产环境中运行此代码时,上面 x.test 的返回值为 false(字面意义上的值为 false,而不是字符串)。此外,对文件的写入永远不会发生。但是,如果我在一些简化的测试代码中执行此操作,它会像预期的那样返回字符串“Success”,并且确实完成了写入。
有谁知道会导致此函数不执行写入并返回 false 的任何情况?我已经尝试在它周围进行救援,以防它抛出一个 rb_raises,但它似乎没有。
我和我团队的其他 3 名成员整个下午都在看这个问题,但没有找到答案。