Erlang драйвер erl_errno проблема
Я играю с erl_driver
, Пуск обратного вызова моего драйвера ниже:
ErlDrvData drv_start(ErlDrvPort port, char* command) {
char* file_name = command + sizeof(drv_name);
GenTtyData* port_data = (GenTtyData*)driver_alloc(sizeof(GenTtyData));
erl_errno = gt_open(file_name, &port_data->file);
if (erl_errno != 0) {
// Assertion there is just to show you my intention
assert(erl_errno == ENOENT);
driver_free(port_data);
return ERL_DRV_ERROR_ERRNO;
}
return port_data;
}
ErlDrvData (запуск)(порт ErlDrvPort, команда char)
This is called when the driver is instantiated, when open_port/2 is called. The driver should return a number >= 0 or a pointer, or if the driver can't be started, one of three error codes should be returned:
ERL_DRV_ERROR_GENERAL - general error, no error code
ERL_DRV_ERROR_ERRNO - error with error code in erl_errno
ERL_DRV_ERROR_BADARG - error, badarg
If an error code is returned, the port isn't started.
Так что я ожидаю, что erlang:open_port/2
отправит сигнал выхода с описанием ошибки (eacces
например, или enotty
). Тем не менее, в тесте у меня есть
{'EXIT',
{unknown,
[{erlang,open_port,[{spawn,"gen_tty_drv non_existent.tty"},[]],[]},
{gen_tty,open,1,
[{file,
"/home/vkovalev/workspace/gen_tty_drv/_build/test/lib/gen_tty/src/gen_tty.erl"},
{line,48}]},
{gen_tty_drv_SUITE,open_non_existent_file,1,
[{file,
"/home/vkovalev/workspace/gen_tty_drv/test/gen_tty_drv_SUITE.erl"},
{line,29}]},
{test_server,ts_tc,3,[{file,"test_server.erl"},{line,1450}]},
{test_server,run_test_case_eval1,6,
[{file,"test_server.erl"},{line,1026}]},
{test_server,run_test_case_eval,9,
[{file,"test_server.erl"},{line,968}]}]}}
Кажется, Эрланг не видит или не может декодировать причину ошибки и отправляет unknown
, Так что не так с моим start
Перезвоните?
1 ответ
Это похоже на ошибку в документации или в коде. Если код, который вызывает драйвер start
функция находит, что функция возвращает ERL_DRV_ERROR_ERRNO
, он принимает номер ошибки от errno
не erl_errno
(в любом случае это верно для otp master commit dc35ae6c, что примерно соответствует Erlang версии 18.0-rc2; в более поздних версиях это может отличаться).
Чтобы доказать это, я написал драйвер start
функция, которая устанавливает errno
в явном виде:
static ErlDrvData
my_driver_start(ErlDrvPort port, char *command)
{
errno = ETXTBSY;
return ERL_DRV_ERROR_ERRNO;
}
и с этим подходом я получил результат, который вы ищете:
1> my_driver:start().
** exception error: etxtbsy
in function open_port/2
called as open_port({spawn,my_driver},[binary])
in call from my_driver:start/0 (my_driver.erl, line 10)
настройка erl_errno
таким же образом, однако, не дал этого результата. Если я явно установить errno
к значению мусора, а затем установить erl_errno
на действительный номер ошибки, например:
static ErlDrvData
my_driver_start(ErlDrvPort port, char *command)
{
errno = 3245690989;
erl_errno = ETXTBSY;
return ERL_DRV_ERROR_ERRNO;
}
тогда я получаю то же самое unknown
результат как вы:
1> my_driver:start().
** exception error: unknown
in function open_port/2
called as open_port({spawn,my_driver},[binary])
in call from my_driver:start/0 (my_driver.erl, line 10)
Обновление: я связался с членом команды OTP по этому поводу, и они ответили по электронной почте, что это ошибка документации, что означает использование errno
скорее, чем erl_errno
это правильное решение. Они сказали, что эта часть кода драйвера всегда использовалась errno
,
Обновление 2: эта проблема была исправлена в driver_entry
документация по Erlang 18.0.