ocaml / ocaml

The core OCaml system: compilers, runtime system, base libraries
https://ocaml.org
Other
5.18k stars 1.06k forks source link

Re: error in marshalling #2537

Closed vicuna closed 23 years ago

vicuna commented 23 years ago

Original bug ID: 168 Reporter: administrator Status: closed Resolution: not a bug Priority: normal Severity: minor Category: ~DO NOT USE (was: OCaml general)

Bug description

Hi,

Thank you for your message to the Caml mailing list.

However your message seems to be a bug report; hence I send it to the relevant mailing list

caml-bugs@inria.fr

Thank again for your interest in Caml.

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/

Hi,

I'm currently programming a distributed application implementing Hewitt's and Agha's Actors.

At some time, I try to send a 'behavior', that's to say a special function. Therefore, I first marshal it, then I send it. But it fails and an exception Invalid_argument is raised. I know the functions of module Marshal don't work with bytecode-threads, so I use a trick given by X. Leroy.

Here is what happens:

type address = { ( 4 fields, similar to IP ) mutable cluster : int; mutable machine : int; mutable process : int; mutable actor : int; }

and actor = { box : mailbox; ego : address; mutable self : behavior; }

and behavior = actor -> unit

and mailbox = { mb_new_ones : packet Queue.t; mutable mb_new_max_size : int option; mb_old_ones : packet Mutable_queue.t; ( resizable array by M.Mottl ) mutable mb_old_max_size : int option; mutable mb_look_old_ones : bool; mutable mb_accept_msg : packet -> bool; mb_mutex : Mutex.t; mb_cond : Condition.t; }

and packet = packet_type * packet_arg

and packet_type = | NOTIFY_SUICIDE ( ego -> NS ) ... many constructors ... | PERFORM_RUN ( PS -> PS ) | MESSAGE of string

and packet_arg = | PA_unit ... many constructors ... | PA_addr_beh of address * behavior | PA_msg_arg of argument

and argument ( abstract )

The rewritten marshalling function :

let to_channel oc v = Pervasives.output_string oc (Marshal.to_string v [Marshal.Closures])

The sending function:

let send_on cout from dest (pcktype, data) =
  Mutex.lock cout.mto_mutex;
  send_dest cout dest;
  send_pcktype cout pcktype;
  send_from cout from;
  send_data cout data;    (* the exception will be raise here *)
  Mutex.unlock cout.mto_mutex

The send_data function :

let send_data chan data =
  Marshalling.to_channel chan.mto_chan data;
  flush chan.mto_chan

Then when the program is executed, it encounters this instruction:

send_on cout ps_addr (upper_address addr) (PERFORM_RUN, PA_addr_beh (addr, beh))

Here is what happens then: Fatal error: uncaught exception Invalid_argument("output_value: object value")

I tried to look at the C code in byterun/extern.c in the OCaml 3.00 distribution, but I didn't understand very much. I saw that the system finds an Object_tag which I wonder where the system finds it :-)

Any comment or idea will be strongly appreciated ;-)

dc

-- David Chemouil [mailto:chemouil@enseeiht.fr] [mobile: 06 84 16 26 65]

Laboratoire d'informatique et de mathématiques appliquées (IRIT-INPT)

vicuna commented 23 years ago

Comment author: administrator

At some time, I try to send a 'behavior', that's to say a special function. Therefore, I first marshal it, then I send it. But it fails and an exception Invalid_argument is raised. I know the functions of module Marshal don't work with bytecode-threads, so I use a trick given by X. Leroy.

Right. The Marshall module will be thread-safe in future releases.

Here is what happens: Fatal error: uncaught exception Invalid_argument("output_value: object value") I tried to look at the C code in byterun/extern.c in the OCaml 3.00 distribution, but I didn't understand very much. I saw that the system finds an Object_tag which I wonder where the system finds it :-)

Well, it means that the data structure you gave to the marshaller contains an object somewhere (including in the closures of the functions that you're marshalling). Maybe in the Mutable_queue.t type? Also, it seems that your data may contain mutexes and conditions, which you cannot marshal reliably.

Generally speaking, the OCaml marshaller works only for pure, passive data structures: no functions, no objects, no stateful things like file descriptors and mutexes. The Marshal.Closures flag allows functions to be marshaled under some circumstances, but it's really a hack that works only for very simple SPMD programming.

I agree this makes the marshaller insufficient for advanced distributed programming -- the Join Calculus / JoeCaml people also have problems with this. But there is no ideal solution known currently.

vicuna commented 23 years ago

Comment author: administrator

Inherent limitations of the marshaler.