仕事の著作権のために実際のコードを投稿することはできないので、簡単なサンプル コードで問題を示してみます。
簡略化されたバージョンが次のような 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 のように)。また、ファイルへの書き込みは発生しません。ただし、単純化されたテストコードでそれを行うと、期待どおりに文字列「成功」が返され、書き込みは実際に完了します。
この関数が書き込みを実行せず、false を返す状況を知っている人はいますか? rb_raise の 1 つをスローしていた場合に備えて、すでにその周りにレスキューを配置しようとしましたが、そうではないようです。
私と私のチームの他の 3 人のメンバーは、午後中ずっとこれを見てきましたが、答えは見つかりませんでした。