[erlang-questions] C interface, NaN and infinity

Björn-Egil Dahlberg <>
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:
>
> '' got a corrupted external term from
> '' 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, "")) < 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