# Unix.write exiting the program without throwing an exception

**URL:** <https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866>\
**Category:** Learning\
**Created:** [May 29, 2020, 11:22am UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866 "2020-05-29T11:22:08Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cjen1](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cjen1/32/1731_2.png) [@Cjen1](https://discuss.ocaml.org/u/Cjen1)\
**Post date:** [May 29, 2020, 11:22am UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/1 "2020-05-29T11:22:08Z")

</div>

When I call:

```auto
try
  Unix.write fd buf offset len
with e ->
  Log.debug (fun m -> m "Failed to send %a" Fmt.exn e); 0

```

My program exits. My mental model says that this should either succeed or throw an error. Is there a case that would cause it to just simply exit without throwing the exception?

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [May 29, 2020, 11:34am UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/2 "2020-05-29T11:34:26Z")

</div>

It may be that the output channels are not being flushed before exiting (this should not normally happen, but…). Did you try flushing them explicitly (either `Format` or `Printf`, not sure what you are using).

Best wishes,  
Nicolás

---

<div class="post-metadata">

**Author:** ![Cjen1](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cjen1/32/1731_2.png) [@Cjen1](https://discuss.ocaml.org/u/Cjen1)\
**Post date:** [May 29, 2020, 11:47am UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/3 "2020-05-29T11:47:10Z")

</div>

Figured out the root cause, it happened when attempting to write to a bound and listening socket, and not the client socket returned by `accept`…

Still I would have thought that this should not have happened…

Btw strace’s output was:

```auto
write(6, "\0\0\0\0\4\0\0\0\0\0\0\0\1\0\1\0\6\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0"..., 40) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=31015, si_uid=4068} ---
+++ killed by SIGPIPE +++

```

---

<div class="post-metadata">

**Author:** ![cvine](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@cvine](https://discuss.ocaml.org/u/cvine)\
**Post date:** [May 29, 2020, 12:31pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/4 "2020-05-29T12:31:38Z")

</div>

> [@Cjen1](#):
>
> Still I would have thought that this should not have happened…
> 
> Btw strace’s output was:
> 
> ```auto
> write(6, "\0\0\0\0\4\0\0\0\0\0\0\0\1\0\1\0\6\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0"..., 40) = -1 EPIPE (Broken pipe)
> --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=31015, si_uid=4068} ---
> +++ killed by SIGPIPE +++
> 
> ```

In a C/POSIX program using sockets you almost always want to set an ignore (SIG\_IGN) signal handler for SIGPIPE, so that unix write will set an EPIPE error instead of generating a SIGPIPE interrupt which will terminate the program, upon attempting to write to a socket that is not open for reading.

Presumably the same is true if you want an EPIPE exception in ocaml instead of SIGPIPE. So I suggest you do the necessary with Sys.signal.

---

<div class="post-metadata">

**Author:** ![fweimer](https://avatars.discourse-cdn.com/v4/letter/f/d2c977/32.png) [@fweimer](https://discuss.ocaml.org/u/fweimer)\
**Post date:** [May 31, 2020, 2:04pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/5 "2020-05-31T14:04:59Z")

</div>

The ideal way to avoid the signal is not use `write`, but `send` with `MSG_NOSIGNAL`, so that you do not have to install a signal handler. Unfortunately, the `Unix` module does not expose `MSG_NOSIGNAL` (although it is part of POSIX nowadays).

---

<div class="post-metadata">

**Author:** ![cvine](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@cvine](https://discuss.ocaml.org/u/cvine)\
**Post date:** [May 31, 2020, 4:02pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/6 "2020-05-31T16:02:11Z")

</div>

> [@fweimer](#):
>
> The ideal way to avoid the signal is not use `write` , but `send` with `MSG_NOSIGNAL` , so that you do not have to install a signal handler. Unfortunately, the `Unix` module does not expose `SIGPIPE` (although it is part of POSIX nowadays).

`SIGPIPE` is not in the Unix module, it’s in the Sys module (`Sys.sigpipe`). As far as I can see `MSG_NOSIGNAL` is not included in `Unix.msg_flag`. The documentation only lists `MSG_OOB`, `MSG_DONTROUTE` and `MSG_PEEK`

---

<div class="post-metadata">

**Author:** ![fweimer](https://avatars.discourse-cdn.com/v4/letter/f/d2c977/32.png) [@fweimer](https://discuss.ocaml.org/u/fweimer)\
**Post date:** [May 31, 2020, 4:18pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/7 "2020-05-31T16:18:39Z")

</div>

Yes, sorry, I meant to write `MSG_NOSIGNAL`, not `SIGPIPE`.

---

<div class="post-metadata">

**Author:** ![cvine](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@cvine](https://discuss.ocaml.org/u/cvine)\
**Post date:** [May 31, 2020, 5:41pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/8 "2020-05-31T17:41:34Z")

</div>

> [@fweimer](#):
>
> Yes, sorry, I meant to write `MSG_NOSIGNAL` , not `SIGPIPE` .

Ah OK.

As it happens I don’t usually bother with the `MSG_NOSIGNAL` flag for sending to sockets when writing C code: I usually just ignore `SIGPIPE` and have done with it. SIGPIPE is only really useful for small programs intended to have their stdin and stdout piped at the unix shell, which is unlikely to involve opening and writing to sockets or opening other pipes/fifos. If I have a program which uses sockets or explicit pipes/fifos I normally ignore `SIGPIPE` at the outset and have done with it. `EPIPE` is what you need for those. So the fact that `MSG_NOSIGNAL` is not wrapped by ocaml doesn’t worry me.

---

<div class="post-metadata">

**Author:** ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)\
**Post date:** [May 31, 2020, 5:44pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/9 "2020-05-31T17:44:45Z")

</div>

> [@cvine](#):
>
> I usually just ignore `SIGPIPE`

In my experience programming in distributed systems (not in Ocaml – but in many other languages), every systems-hacker has that experience where they learn about reset sockets, SIGPIPE, ignoring the signal, EPIPE, and the necessity of checking return-codes from write (and other syscalls) … in that order _grin_. For many of us, it’s drilled into us by some vary gruesome screwup. Almost a rite of passage to forget some part of that checklist, and learn the hard way never to do it again.

---

<div class="post-metadata">

**Author:** ![cvine](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@cvine](https://discuss.ocaml.org/u/cvine)\
**Post date:** [May 31, 2020, 6:54pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/10 "2020-05-31T18:54:28Z")

</div>

> [@Chet\_Murthy](#):
>
> Almost a rite of passage to forget some part of that checklist, and learn the hard way never to do it again.

Yes, sockets seem to abound in such things, where basically the defaults are wrong: `SIGPIPE`, `SO_REUSEADDR`, `FD_CLOEXEC`: and for some reason the tutorials don’t seem to draw attention to them.

---

<div class="post-metadata">

**Author:** ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)\
**Post date:** [May 31, 2020, 7:50pm UTC](https://discuss.ocaml.org/t/unix-write-exiting-the-program-without-throwing-an-exception/5866/11 "2020-05-31T19:50:07Z")

</div>

And the different-for-every-OS ones: close\_wait, fin\_wait timers, max socket counts, etc. Yeah, TCP kinda sucks.
