Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error code 141 / "unknown C primitive `unix_dup'" when flushing to unopened pipe #5289

Closed
vicuna opened this issue Jun 15, 2011 · 4 comments
Closed
Labels

Comments

@vicuna
Copy link

vicuna commented Jun 15, 2011

Original bug ID: 5289
Reporter: cvp
Status: closed (set by @xavierleroy on 2013-08-31T10:43:57Z)
Resolution: not a bug
Priority: normal
Severity: crash
Platform: GNU/Linux (x86_64)
OS: Fedora Core (x86_64)
OS Version: 15
Version: 3.12.0
Category: ~DO NOT USE (was: OCaml general)

Bug description

When piping to programs that don't use stdin, the toplevel and the bytecode interpreter straight-up crash, when you would expect that an exception be thrown instead or something.

Steps to reproduce

Toplevel:
$ ocaml

#load "unix.cma" ;;

let p_out = Unix.open_process_out "true" ;;

val p_out : out_channel =

output_string p_out "foo" ;;

  • : unit = ()

flush p_out ;; (* crashes *)

$ echo $?
141
$

(Also crashes in toplevel without dynamic loading, made with:
$ ocamlmktop -custom -cclib -lunix unix.cma -o unix-top
)

Bytecode:
$ cat > fail.ml
let p_out = Unix.open_process_out "true" in
output_string p_out "foo";
flush p_out;
close_out p_out;
Unix.close_process_out p_out ;;
print_endline "executed successfully" ;;
^D
$ ocamlc -custom -cclib -lunix unix.cma fail.ml -o fail
$ ./fail # works
executed successfully
$ ocamlrun fail # doesn't
Fatal error: unknown C primitive `unix_dup'
$

Compiling to native machine code produces no errors (i.e. "executed successfully").

Additional information

$ uname -a
Linux icarus 2.6.38.7-30.fc15.x86_64 #1 SMP Fri May 27 05:15:53 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

$ ocaml -version
The Objective Caml toplevel, version 3.12.0

$ grep '$Id' $(ocamlc -where)/unix.mli
(* $Id: unix.mli 10450 2010-05-21 12:00:49Z doligez $ *)

@vicuna
Copy link
Author

vicuna commented Jun 15, 2011

Comment author: cvp

Er... click the "View Advanced" link to see Steps to Reproduce.

@vicuna
Copy link
Author

vicuna commented Jun 16, 2011

Comment author: @ygrek

It doesn't crash, but exits on SIGPIPE because true exits before output channel is flushed. Try yes > /dev/null' instead and see. Bytecode compiled works because channel happens to be flushed before trueis launched (race condition).unix_dup` is not found in last example because you shouldn't use ocamlrun to run executables with custom runtime.

@vicuna
Copy link
Author

vicuna commented Jun 16, 2011

Comment author: cvp

In that case, shouldn't the interactive toplevel handle a SIGPIPE a little more gracefully? Because all the user sees is a sudden termination without an explanation.

@vicuna
Copy link
Author

vicuna commented Aug 3, 2011

Comment author: @damiendoligez

You have your explanation right here:

flush p_out ;; (* crashes *)

$ echo $?
141

The termination code is 128 + 13. The 128 is a flag telling you that the process was killed by a signal, and the 13 is the signal number (SIGPIPE). Maybe the shell should report exit codes more explicitely ?

Should we try to catch all signals? And what do we do when we get one?

@vicuna vicuna closed this as completed Aug 31, 2013
@vicuna vicuna added the bug label Mar 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant