[erlang-questions] C interface, NaN and infinity
Björn-Egil Dahlberg
egil@REDACTED
Fri Dec 5 18:45:07 CET 2014
Ok, so you are talking about distribution and erl_interface.
If I'm understanding you correctly: You have a C-Node using legacy
erl_interface, encoding a NaN double and sending it to the beam? It has
nothing to do with beam?
Did you actually manage to get a NaN to the beam or does beam always
close the connection?
Regarding erl_interface, i think neither erl_mk_float (old) or
ei_encode_double (new) checks if it is a valid double. The easiest
solution is probably to check the double yourself with isfinite() before
encoding. Regardless, beam should drop the connection (the distribution
channel) if it finds bad data on the wire. As it does in your example.
// Björn-Egil
On 2014-12-05 18:07, David Welton wrote:
> Hi,
>
>> Explain more please. How did you send a NaN to the beam?
> Here's an example - it may have a problem or two because my C is rusty.
>
> For it to work, you have to have a registered process:
>
> erlang:register(someregisteredprocess, self()) from the shell, for instance.
>
> I get:
>
> 'erlangnode@REDACTED' got a corrupted external term from
> 'nukenode@REDACTED' on distribution channel 13686
> <<...,131,99,45,110,97,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
> ATOM_CACHE_REF translations: none
>
>
>> NaN are not allowed as a float in erlang terms.
> As far as I can see, the C code in OTP does not disallow it, either. Should it?
>
> ----
> #include <stdio.h>
> #include <stdlib.h>
>
> #include <sys/stat.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <unistd.h>
> #include <errno.h>
> #include <time.h>
> #include "erl_interface.h"
> #include "ei.h"
>
> int main(int argc, char **argv) {
> int fd; /* fd to Erlang node */
>
> int loop = 1; /* Loop flag */
> int got; /* Result of receive */
> erlang_msg emsg; /* Incoming message */
>
> ETERM *tosend;
> int res;
> ei_x_buff recvbuf;
>
> int sendonce = 0;
> int nodenum = 0;
>
> ei_cnode ec;
>
> srand(time(NULL) + getpid());
>
> erl_init(NULL, 0);
>
> nodenum = rand() % 100;
>
> fprintf(stderr, "nodenum %d\n", nodenum);
> if (ei_connect_init(&ec, "nukenode", "somecookie", nodenum) == -1) {
> erl_err_quit("erl_connect_init");
> }
>
> if ((fd = ei_connect(&ec, "erlangnode@REDACTED")) < 0) {
> erl_err_quit("erl_connect");
> }
>
> ei_x_new(&recvbuf);
> while (loop) {
>
> ei_receive_msg(fd, &emsg, &recvbuf);
> if (got == ERL_TICK) {
> /* ignore */
> } else if (got == ERL_ERROR) {
> loop = 0;
> }
>
> if (sendonce == 0) {
> ETERM *tosend;
> tosend = erl_mk_float(0.0/0.0);
> erl_print_term(stderr, tosend);
> {
> ETERM *msg;
> ei_x_buff x;
> int r = 0;
>
> msg = tosend;
> ei_x_new_with_version(&x);
> if (ei_x_encode_term(&x, msg) < 0) {
> r = 0;
> } else {
> r = ei_reg_send(&ec, fd, "someregisteredprocess",
> x.buff, x.index - 10);
> }
> ei_x_free(&x);
> }
>
> erl_free_term(tosend);
>
> sendonce = 1;
> exit(0);
> }
> }
> }
>
>
>
More information about the erlang-questions
mailing list