[erlang-questions] Half word emulators and NIFs

Sverker Eriksson <>
Thu Jun 30 11:59:51 CEST 2011


Paul Davis wrote:
> On Mon, Jun 27, 2011 at 6:03 AM, Sverker Eriksson
> <> wrote:
>   
>> Have you tested with a debug built emulator. That may catch faulty NIF
>> behaviors earlier. Otherwise if a NIF builds broken terms on the process
>> heap it might not be discovered until later when those terms are matched or
>> maybe garbage collected.
>>
>> There is no difference to make NIF's for the halfword emulator. Just use the
>> NIF API as intended and don't cheat (make assumptions about
>> sizeof(ERL_NIF_TERM) for example).
>>
>> /Sverker, Erlang/OTP
>>
>>     
>
> I've reduced this to a failing test case in the NIF API [1].
>
> In the end it boils down to these two functions (notice one is int64,
> the other not):
>
> ERL_NIF_TERM
> run_test1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
> {
>     return enif_make_int64(env, 1);
> }
>
> ERL_NIF_TERM
> run_test2(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
> {
>     return enif_make_int(env, 1);
> }
>
> Test 1 returns a Value V where (V =:= 1) is false, but (V == 1) is
> true. The second function returns a value where both comparisons are
> true.
>
> Paolo also found that amusingly this bug disappears at 2^27 as shown by:
>
> ERL_NIF_TERM
> run_test3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
> {
>     return enif_make_int64(env, 134217727);
> }
>
> ERL_NIF_TERM
> run_test4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
> {
>     return enif_make_int64(env, 134217728);
> }
>
> run_test3 returns a value that can't be pattern matched against
> 134217727 but test 4 returns a value that can be matched against
> 134217728.
>
> Also, I built R14B03 on Ubuntu 10.04 with this configure:
>
> ./configure --enable-smp --enable-threads --enable-m64-build
> --without-javac --enable-halfword-emulator
>
> The processors are a pair of dual core Xeon's if that's important at all.
>
> [1] https://github.com/davisp/halfwordtest
>
>   
Very nice trouble shooting. Thank you Paul.

It's a halfword-bug affecting:
enif_make_int64
enif_make_long
enif_make_uint64
enif_make_ulong

for integer values that can fit into 28 bits.

What happens is that it makes a bignum even though the value could have
fit into a small integer. Small bignums like that are not allowed internally
and that's the reason why it behaves so strangely when comparing.

I'll be back with a source patch.

/Sverker, Erlang/OTP







More information about the erlang-questions mailing list