[erlang-questions] Adding a NIF to prim_file
Andre Nathan
andre@REDACTED
Mon Apr 29 15:23:31 CEST 2019
That worked, thanks!
On 4/29/19 3:40 AM, John Högberg wrote:
> Hi,
>
> `prim_file` is a prebuilt module that's statically embedded into the
> emulator, and the emulator crashes if there are any problems
> initializing it. In this case you've added a function to the NIF but
> haven't yet rebuilt the module, so it crashes when trying to inject the
> non-existent `my_truncate_nif/1`.
>
> To update these prebuilt modules, you need to run:
>
> ./otp_build update_preloaded --no-commit
>
> Try doing this on a clean build without changes to the NIF (C code),
> and then rebuild the emulator with the changes applied. Note that you
> will need to rebuild the emulator every time you update the preloaded
> modules for the changes to take effect.
>
> Hope that helps!
>
> Regards,
> John Högberg
>
> On Sun, 2019-04-28 at 17:59 -0300, Andre Nathan wrote:
>> Hi
>>
>> I'm trying to figure out how to add a NIF to the prim_file module.
>> To
>> try to get it working, I'm just trying to add an existing function
>> under
>> a different name:
>>
>> In prim_file_nif.c I added the lines below:
>>
>> WRAP_FILE_HANDLE_EXPORT(my_truncate_nif)
>>
>> static ErlNifFunc nif_funcs[] = {
>> ...
>> {"my_truncate_nif", 1, my_truncate_nif,
>> ERL_NIF_DIRTY_JOB_IO_BOUND},
>> ...
>> };
>>
>> Then I copied truncate_nif_impl and renamed the copy to
>> my_truncate_nif_impl.
>>
>>
>> In prim_file.erl I copied the truncate function, renamed the copy to
>> my_truncate and changed it to call my_truncate_nif instead of
>> truncate_nif. Then I added
>>
>> my_truncate_nif(_FileRef) ->
>> erlang:nif_error(undef).
>>
>> However, when I try to build OTP, I get this error:
>>
>> (no logger present) unexpected logger message: {log,error,"Error in
>> process ~p with exit
>> value:~n~p~n",[<0.0.0>,{{badmatch,{error,{bad_lib,"Function not
>> found
>> prim_file:my_truncate_nif/1"}}},[{prim_file,on_load,0,[]},{erl_init,s
>> tart,2,[]}]}],#{error_logger=>#{emulator=>true,tag=>error},gl=><0.0.0
>>> ,pid=><0.0.0>,time=>1556484838271817}}
>>
>> Is there anything else I have to do to allow the new function to be
>> detected? I couldn't find any other references to truncate_nif that
>> I
>> could replicate.
>>
>> The full diff is pasted below.
>>
>> Thanks,
>> Andre
>>
>>
>> diff --git a/erts/emulator/nifs/common/prim_file_nif.c
>> b/erts/emulator/nifs/common/prim_file_nif.c
>> index 3df04e42e2..61a9b70679 100644
>> --- a/erts/emulator/nifs/common/prim_file_nif.c
>> +++ b/erts/emulator/nifs/common/prim_file_nif.c
>> @@ -162,6 +162,7 @@ WRAP_FILE_HANDLE_EXPORT(allocate_nif)
>> WRAP_FILE_HANDLE_EXPORT(advise_nif)
>> WRAP_FILE_HANDLE_EXPORT(get_handle_nif)
>> WRAP_FILE_HANDLE_EXPORT(ipread_s32bu_p32bu_nif)
>> +WRAP_FILE_HANDLE_EXPORT(my_truncate_nif)
>>
>> static ErlNifFunc nif_funcs[] = {
>> /* File handle ops */
>> @@ -174,6 +175,7 @@ static ErlNifFunc nif_funcs[] = {
>> {"seek_nif", 3, seek_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
>> {"sync_nif", 2, sync_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
>> {"truncate_nif", 1, truncate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
>> + {"my_truncate_nif", 1, my_truncate_nif,
>> ERL_NIF_DIRTY_JOB_IO_BOUND},
>> {"allocate_nif", 3, allocate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
>> {"advise_nif", 4, advise_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
>>
>> @@ -721,6 +723,16 @@ static ERL_NIF_TERM sync_nif_impl(efile_data_t
>> *d,
>> ErlNifEnv *env, int argc, con
>> return am_ok;
>> }
>>
>> +static ERL_NIF_TERM my_truncate_nif_impl(efile_data_t *d, ErlNifEnv
>> *env, int argc, const ERL_NIF_TERM argv[]) {
>> + ASSERT(argc == 0);
>> +
>> + if(!efile_truncate(d)) {
>> + return posix_error_to_tuple(env, d->posix_errno);
>> + }
>> +
>> + return am_ok;
>> +}
>> +
>> static ERL_NIF_TERM truncate_nif_impl(efile_data_t *d, ErlNifEnv
>> *env,
>> int argc, const ERL_NIF_TERM argv[]) {
>> ASSERT(argc == 0);
>>
>> diff --git a/erts/preloaded/src/prim_file.erl
>> b/erts/preloaded/src/prim_file.erl
>> index 1aa5d85c64..e350cd9a19 100644
>> --- a/erts/preloaded/src/prim_file.erl
>> +++ b/erts/preloaded/src/prim_file.erl
>> @@ -22,7 +22,7 @@
>> -export([on_load/0]).
>>
>> -export([open/2, close/1,
>> - sync/1, datasync/1, truncate/1, advise/4, allocate/3,
>> + sync/1, datasync/1, truncate/1, my_truncate/1, advise/4,
>> allocate/3,
>> read_line/1, read/2, write/2, position/2,
>> pread/2, pread/3, pwrite/2, pwrite/3]).
>>
>>
>> @@ -242,6 +242,15 @@ truncate(Fd) ->
>> error:badarg -> {error, badarg}
>> end.
>>
>> +my_truncate(Fd) ->
>> + try
>> + #{ handle := FRef } = get_fd_data(Fd),
>> + reset_write_position(Fd),
>> + my_truncate_nif(FRef)
>> + catch
>> + error:badarg -> {error, badarg}
>> + end.
>> +
>> advise(Fd, Offset, Length, Advise) ->
>> try
>> #{ handle := FRef } = get_fd_data(Fd),
>> @@ -493,6 +502,8 @@ allocate_nif(_FileRef, _Offset, _Length) ->
>> erlang:nif_error(undef).
>> truncate_nif(_FileRef) ->
>> erlang:nif_error(undef).
>> +my_truncate_nif(_FileRef) ->
>> + erlang:nif_error(undef).
>> get_handle_nif(_FileRef) ->
>> erlang:nif_error(undef).
>> delayed_close_nif(_FileRef) ->
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
More information about the erlang-questions
mailing list