Problem with porting ei program to MS Windows

pan+eq <>
Wed Apr 14 18:59:06 CEST 2004


Hi,

Rule of thumb, never use VC++ "unix/posix emulation thingie". 
ReadFile and WriteFile are the Win32 calls for reading and witing to file
handles.
This makes the program work though (context diff):

*** crashtest.c.orig    Wed Apr 14 18:52:41 2004
--- crashtest.c Wed Apr 14 18:53:48 2004
***************
*** 6,11 ****
--- 6,12 ----
  
  #if defined(_WINDOWS)
  #     include <io.h>
+ #     include <fcntl.h>
  #     include <winsock2.h>
  #else
  #     include <unistd.h>
***************
*** 28,33 ****
--- 29,37 ----
  {
        ei_x_buff x;
  
+ #if defined(_WINDOWS)
+       _setmode(1,_O_BINARY);
+ #endif
        logfile = fopen("LOGFILE", "w");
        fprintf(logfile, "Started.\n");

Cheers,
/Patrik
On Wed, 14 Apr 2004  wrote:

> 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