1

で遊んでい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たとえば、 or 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}]}]}}

erlang がエラー理由を認識しないかデコードできないようで、 を送信しますunknownstartでは、コールバックの何が問題なのですか?

4

1 に答える 1

2

これは、ドキュメントまたはコードのバグのようです。ドライバーstart関数を呼び出すコードが、関数が を返すことを検出した場合ERL_DRV_ERROR_ERRNOエラー番号は から取得されますがerrnoerl_errno (これは otp マスター コミット 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: この問題は、Erlang 18.0のdriver_entryドキュメントで修正されています。

于 2015-06-18T02:02:44.873 に答える