[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