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