ocaml / ocaml

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

Installation sur Linux #2386

Closed vicuna closed 24 years ago

vicuna commented 24 years ago

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

Bug description

Bonjour,

j'ai installé sans problèmes plusieurs versions d'OCaml sur différentes plates-formes sans jamais rencontrer aucun problème. Bizarrement, je n'arrive pas à compiler (version 2.04 et 2.99) sur certaines machines Linux (les nouvelles machines élèves Linux de l'ENS; pas de problèmes sur d'autres Linux).

make world se bloque sur: ../boot/ocamlrun ../ocamlc -g -nopervasives -c pervasives.mli à cause d'une exception "End_of_file" non rattrapée par le compilateur.

Il s'avère que si on lance cette ligne manuellement, on obtient une fois sur deux un succès et une fois sur deux un échec (avec une vraie periodicité de periode 2).

strace montre que l'echec est provoqué par un read de 4096 octets sur pervasives.cmi, après la fin du fichier. Voici la fin de la sortie de strace lors d'un echec:

open("pervasives.cmi", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 brk(0x808f000) = 0x808f000 brk(0x806d000) = 0x806d000 write(3, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 write(3, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 write(3, "\341\0\1\0031\2\5\365\341\0\1\003"..., 3297) = 3297 open("pervasives.cmi", O_RDONLY) = 4 lseek(4, 0, SEEK_END) = 11540 lseek(4, 0, SEEK_SET) = 0 read(4, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 read(4, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 read(4, "\341\0\1\0031\2\5\365\341\0\1\003"..., 4096) = 3297 read(4, "", 4096) = 0 write(2, "Uncaught exception: End_of_file\n"..., 32Uncaught exception: End_of_file ) = 32 _exit(2) = ?

et lors d'un succès:

open("pervasives.cmi", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 brk(0x808f000) = 0x808f000 brk(0x806d000) = 0x806d000 write(3, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 write(3, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 write(3, "\341\0\1\0031\2\5\365\341\0\1\003"..., 3297) = 3297 open("pervasives.cmi", O_RDONLY) = 4 lseek(4, 0, SEEK_END) = 11489 lseek(4, 0, SEEK_SET) = 0 read(4, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 read(4, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 read(4, "\341\0\1\0031\2\5\365\341\0\1\003"..., 4096) = 3297 close(4) = 0 brk(0x8071000) = 0x8071000 write(3, "\204\225\246\276\0\0\0\37\0\0\0\4"..., 51) = 51 close(3) = 0 _exit(0) = ?

Je précise que l'on travaille en NFS (le serveur NFS est un Sun sous Solaris).

Avez-vous une idée d'où cela peut venir ?

Merci de votre aide

-- Alain Frisch

vicuna commented 24 years ago

Comment author: administrator

Bonjour,

j'ai installé sans problèmes plusieurs versions d'OCaml sur différentes plates-formes sans jamais rencontrer aucun problème. Bizarrement, je n'arrive pas à compiler (version 2.04 et 2.99) sur certaines machines Linux (les nouvelles machines élèves Linux de l'ENS; pas de problèmes sur d'autres Linux).

Merci pour le strace, qui m'a permis (je crois) de localiser le probleme. Mon impression est que c'est un bug... dans Linux!

Explication: l'erreur se produit lorsque OCaml ecrit un fichier d'interface compilee, en l'occurrence pervasives.cmi. L'algorithme pour ecrire ces fichiers est le suivant:

Sur le strace, dans le cas qui reussit, on voit bien ces etapes:

open("pervasives.cmi", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 creation du fichier en ecriture write(3, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 write(3, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 write(3, "\341\0\1\0031\2\5\365\341\0\1\003"..., 3297) = 3297 ecriture de 4096+4096+3297=11489 octets open("pervasives.cmi", O_RDONLY) = 4 reouverture en lecture lseek(4, 0, SEEK_END) = 11489 lseek(4, 0, SEEK_SET) = 0 determination de la taille courante du fichier = 11489 read(4, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 read(4, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 read(4, "\341\0\1\0031\2\5\365\341\0\1\003"..., 4096) = 3297 calcul du MD5 close(4) = 0 write(3, "\204\225\246\276\0\0\0\37\0\0\0\4"..., 51) = 51 ecriture du MD5 et d'autres infos close(3) = 0

Sur le strace du cas d'echec, il se produit quelque chose de tres bizarre:

open("pervasives.cmi", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 write(3, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 write(3, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 write(3, "\341\0\1\0031\2\5\365\341\0\1\003"..., 3297) = 3297 ecriture de 4096+4096+3297=11489 octets, c'est normal open("pervasives.cmi", O_RDONLY) = 4 lseek(4, 0, SEEK_END) = 11540 mais ici la taille courante du fichier est 11540, et non 11489!!! lseek(4, 0, SEEK_SET) = 0 read(4, "Caml1999I005\204\225\246\276\0\0"..., 4096) = 4096 read(4, "\365\341\0\1\1\256\260\262\4\367"..., 4096) = 4096 read(4, "\341\0\1\0031\2\5\365\341\0\1\003"..., 4096) = 3297 read(4, "", 4096) = 0 on essaye de lire 11540 octets, et bien sur ca echoue car il n'y en a que 11489

Je précise que l'on travaille en NFS (le serveur NFS est un Sun sous Solaris). Avez-vous une idée d'où cela peut venir ?

Je pense qu'il s'agit d'un probleme de NFS entre Linux et Solaris. J'ai vaguement entendu parler de problemes de cet ordre, certains pouvant etre corriges en appliquant un patch de Sun sur la machine Solaris, mais je ne me souviens pas des details. Peut-etre que les archives de la liste linux-kernel ou du newsgroup comp.os.linux.development.kernel contiennent plus d'infos la-dessus.

vicuna commented 24 years ago

Comment author: administrator

Looks like an NFS incompatibility between Linux and Solaris

vicuna commented 24 years ago

Comment author: administrator

Bonjour,

je vous avais signalé un problème que nous rencontrons pour compiler OCaml sur les Linux du réseau de l'ENS. Apparemment, il s'agit d'un problème de NFS, lié à l'algorithme d'écriture des sommes de controle dans les fichiers signature (le meme fichier est ouvert en ecriture et en lecture dans 2 fd différents; je ne sais pas si NFS est censé gérer cela).

J'ai patché env/typing.ml pour fermer le fichier avant de calculer la somme MD5 et l'ouvrir de nouveau en mode append. J'ai vérifié, cela fonctionne et permet effectivement de compiler sur les Linux connectés à un serveur NFS Solaris (avant, nous compilions sur un Linux standalone).

Voici la version modifiée de la fonction concernée:

let save_signature sg modname filename = Btype.cleanup_abbrev (); let comps = components_of_module empty Subst.identity (Pident(Ident.create_persistent modname)) (Tmty_signature sg) in let oc = open_out_bin filename in output_string oc cmi_magic_number; output_value oc (modname, sg); flush oc; close_out oc; let crc = Digest.file filename in let crcs = (modname, crc) :: imported_units() in let oc = open_out_gen [Open_wronly; Open_append; Open_binary] 0o666 filename in output_value oc crcs; close_out oc; ( Enter signature in persistent table so that imported_unit() will also return its crc ) let ps = { ps_name = modname; ps_sig = sg; ps_comps = comps; ps_crcs = crcs } in Hashtbl.add persistent_structures modname ps

Et le diff avec la version 2.99: 765a766

close_out oc; 767a769,770 let oc = open_out_gen [Open_wronly; Open_append; Open_binary] 0o666 filename in

(je vois à l'instant, dans le CVS que la fonction a été modifiée depuis la 2.99)

Bien cordialement,

Alain Frisch

vicuna commented 24 years ago

Comment author: administrator

je vous avais signalé un problème que nous rencontrons pour compiler OCaml sur les Linux du réseau de l'ENS. Apparemment, il s'agit d'un problème de NFS, lié à l'algorithme d'écriture des sommes de controle dans les fichiers signature (le meme fichier est ouvert en ecriture et en lecture dans 2 fd différents; je ne sais pas si NFS est censé gérer cela).

Mais si, mais si, NFS n'est pas MSDOS :-)

Le problème en question semble être un bug connu de Solaris, un patch est disponible chez Sun:

We had the same problem with Linux<-->Solaris. It was fixed by a patch fom Sun. The problem would occur when Linux padded the NFS packet. Solaris used the size of the packet, not the size field of the packet to determine the amount of data in the packet. Most Linux NFS requests are block-sized request so this error rarely appears.

J'ai patché env/typing.ml pour fermer le fichier avant de calculer la somme MD5 et l'ouvrir de nouveau en mode append. J'ai vérifié, cela fonctionne et permet effectivement de compiler sur les Linux connectés à un serveur NFS Solaris (avant, nous compilions sur un Linux standalone).

Plutôt que de contourner le bug de Solaris dans Caml, je vous encourage à patcher votre serveur Solaris. D'autres applications que Caml peuvent être affectées. Autrement dit, quand on a 40 de fièvre, il vaut mieux soigner la fièvre que casser le thermomètre :-)