Problem with porting ei program to MS Windows
erlang@REDACTED
erlang@REDACTED
Wed Apr 14 18:31:15 CEST 2004
Hi,
I have a port program using the ei library running under Sparc Solaris.
I have attemted porting it to Windows, but have come across the
following problem. Most messages from my C program to Erlang cannot
be correctly transformed with binary_to_term/1.
I have reduced my program to something nice and small and have added
debug output, and that shows identical streams of bytes being written.
I am running R9C-0 on both Solaris and Windows XP.
Any insights on this are happily received.
Here is the run on Sparc Solaris:
Eshell V5.3 (abort with ^G)
1> crashtest:start().
<0.30.0>
2> {ok,[{section,name,[],[],[locked,expanded],user,0,unknown},
{section,name,[],["one"],[],admin,1,bool},
{section,name,[],["one","two"],[locked],internal,2,integer},
{section,name,[],["one","two","three"],[expanded],deprecated,3,real},
{section,name,[],["one","two","three","four"],[locked],user,4,string},
{section,name,[],[],[],admin,5,enum},
{section,name,[],["one"],[locked,expanded],internal,6,pathname},
{section,name,[],["one","two"],[],deprecated,7,unknown},
{section,name,[],["one","two","three"],[locked],user,8,bool},
{section,name,[],["one","two","three","four"],[expanded],admin,9,integer},
{section,name,[],[],[locked],internal,10,real},
{section,name,[],["one"],[],deprecated,11,string},
{section,name,[],["one","two"],[locked,expanded],user,12,enum},
{section,name,[],["one","two","three"],[],admin,13,pathname}]}
2> ** exited: {port_terminated,{exit_status,0}} **
But on Windows XP I get:
Eshell V5.3 (abort with ^G)
1> crashtest:start().
<0.30.0>
2>
=ERROR REPORT==== 14-Apr-2004::17:18:33 ===
Error in process <0.30.0> with exit value: {badarg,[{erlang,binary_to_term,[<<1145 bytes>>]},{crashtest,loop,1}]}
2> ** exited: {badarg,[{erlang,binary_to_term,
[<<131,104,2,100,0,2,111,107,108,0,0,0,1,104,8,100,0,7,115,101,99,...>>]},
{crashtest,loop,1}]} **
2>
Here is crashtest.erl:
-module(crashtest).
-export([start/0, stop/0,init/1]).
start() ->
spawn_link(?MODULE, init, ["./crashtest"]).
stop() ->
myserver ! stop.
init(Cmd) ->
register(myserver, self()),
process_flag(trap_exit, true),
Port = open_port({spawn, Cmd}, [binary, {packet, 4}, exit_status]),
loop(Port).
loop(Port) ->
receive
{Port, {data, Data}} ->
io:fwrite("~p~n", [binary_to_term(Data)]),
loop(Port);
stop ->
port_close(Port),
exit(normal);
{Port, {exit_status, Status}} ->
exit({port_terminated, {exit_status, Status}});
{'EXIT', Port, Reason} ->
exit({port_terminated, Reason})
end.
And here is crashtest.c:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#if defined(_WINDOWS)
# include <io.h>
# include <winsock2.h>
#else
# include <unistd.h>
# include <sys/types.h>
# include <netinet/in.h>
# include <inttypes.h>
#endif
#include "ei.h"
/*support functions */
static int safe_write(char* buf, int len);
static int send_msg(ei_x_buff *x);
static void build_message(ei_x_buff *x);
FILE *logfile;
int
main(int argc, char **argv)
{
ei_x_buff x;
logfile = fopen("LOGFILE", "w");
fprintf(logfile, "Started.\n");
ei_x_new(&x);
build_message(&x);
if (send_msg(&x) < 0)
fprintf(logfile, "No port to Erlang!\n");
ei_x_free(&x);
return 0;
}
static int
safe_write(char* buf, int len)
{
int tot = 0;
int r;
while (len > 0) {
if ((r = write(1, buf, len)) <= 0)
return r;
tot += r;
buf += r;
len -= r;
}
return tot;
}
static void
logbuff(char *b, int len, char *title)
{
int i;
fprintf(logfile, "%s\n", title);
for (i = 0; i < len; i++)
{
unsigned char c = b[i];
fprintf(logfile, " %03u (%c)\n", c, isprint(c) ? c : ' ');
}
fprintf(logfile, "\n");
}
static int
send_msg(ei_x_buff *x)
{
int host_len = x->index;
int net_len = htonl(host_len);
fprintf(logfile, "Sending %d bytes.\n", host_len);
if (safe_write((char *) &net_len, 4) != 4)
return -1;
if (safe_write(x->buff, host_len) != host_len)
return -1;
logbuff(x->buff, host_len, "Sent:");
return host_len;
}
static void
encode_string_list(ei_x_buff *x, int n, char **strings)
{
int i;
for (i = 0; i < n; i++) {
ei_x_encode_list_header(x, 1);
ei_x_encode_string(x, strings[i]);
}
ei_x_encode_empty_list(x);
}
static void
build_message(ei_x_buff *x)
{
int i;
int n = 14;
static void build_elem(ei_x_buff *x, int i);
/* {ok, [Elem]} */
ei_x_encode_version(x);
ei_x_encode_tuple_header(x, 2);
ei_x_encode_atom(x, "ok");
for (i = 0; i < n; i++) {
ei_x_encode_list_header(x, 1);
build_elem(x, i);
}
ei_x_encode_empty_list(x);
}
static void
build_elem(ei_x_buff *x, int i)
{
/* {"section", "name", [sysvalues], [uservalues], [locked|expanded], Access,
sig_count, Sig_type, [sig_enumerations]}
where
Access = user | admin | internal | deprecated
Sig_type = unknown | bool | integer | real | string | enum | pathname
*/
char *some_strings[] = { "one", "two", "three", "four", "five" };
char *sig_access2str[] = { "user", "admin", "internal", "deprecated" };
char *sig_type2str[] = { "unknown", "bool", "integer", "real", "string", "enum", "pathname" };
ei_x_encode_tuple_header(x, 8);
ei_x_encode_atom(x, "section"); /* 1 */
ei_x_encode_atom(x, "name"); /* 2 */
encode_string_list(x, 0, NULL); /* 3 */
encode_string_list(x, i % 5, some_strings); /* 4 */
if (i % 2 == 0) { /* 5 */
ei_x_encode_list_header(x, 1);
ei_x_encode_atom(x, "locked");
}
if (i % 3 == 0) {
ei_x_encode_list_header(x, 1);
ei_x_encode_atom(x, "expanded");
}
ei_x_encode_empty_list(x);
ei_x_encode_atom(x, sig_access2str[i % 4]); /* 6 */
ei_x_encode_long(x, i); /* 7 */
ei_x_encode_atom(x, sig_type2str[i % 7]); /* 8 */
}
Thank you for any help,
Robby
More information about the erlang-questions
mailing list