The unpac monorepo manager self-hosting as a monorepo using unpac

eio_windows: fix blocking bug and pipe error

* fix blocking issue on Windows : issue #793.
Adding await_readable before reading fd

* fix broken pipe exception : issue #792.
Use Unix.read_bigarray instead of Unix_cstruct.read

* replace eio_windows_cstruct_stubs.c by Unix functions.
Since OCaml 5.2, Unix.read_bigarray and Unix.write_bigarray can be used.

authored by

bdodrem and committed by
Thomas Leonard
d3cb04a6 c78db1a7

+21 -158
+2 -2
.github/workflows/main.yml
··· 12 12 os: 13 13 - macos-latest 14 14 ocaml-compiler: 15 - - 5.1.x 15 + - 5.2.x 16 16 local-packages: 17 17 - eio eio_posix eio_main 18 18 ··· 44 44 with: 45 45 opam-pin: false 46 46 opam-depext: false 47 - ocaml-compiler: ocaml.5.1.0,ocaml-option-mingw 47 + ocaml-compiler: ocaml.5.2.0,ocaml-option-mingw 48 48 opam-repositories: | 49 49 dra27: https://github.com/dra27/opam-repository.git#windows-5.0 50 50 normal: https://github.com/ocaml/opam-repository.git
+1 -1
dune-project
··· 14 14 (description "An effect-based IO API for multicore OCaml with fibers.") 15 15 (conflicts (seq (< 0.3))) 16 16 (depends 17 - (ocaml (>= 5.1.0)) 17 + (ocaml (>= 5.2.0)) 18 18 (bigstringaf (>= 0.9.0)) 19 19 (cstruct (>= 6.0.1)) 20 20 lwt-dllist
+1 -1
eio.opam
··· 10 10 bug-reports: "https://github.com/ocaml-multicore/eio/issues" 11 11 depends: [ 12 12 "dune" {>= "3.9"} 13 - "ocaml" {>= "5.1.0"} 13 + "ocaml" {>= "5.2.0"} 14 14 "bigstringaf" {>= "0.9.0"} 15 15 "cstruct" {>= "6.0.1"} 16 16 "lwt-dllist"
+1 -1
lib_eio_windows/dune
··· 6 6 (foreign_stubs 7 7 (language c) 8 8 (include_dirs ../lib_eio/unix/include) 9 - (names eio_windows_stubs eio_windows_cstruct_stubs)) 9 + (names eio_windows_stubs)) 10 10 (c_library_flags :standard -lbcrypt -lntdll) 11 11 (libraries eio eio.unix eio.utils fmt)) 12 12
-149
lib_eio_windows/eio_windows_cstruct_stubs.c
··· 1 - /* From mirage/ocaml-cstruct 2 - Copyright (c) 2012 Anil Madhavapeddy <anil@recoil.org> 3 - Copyright (c) 2012 Pierre Chambart 4 - Copyright (c) Christiano F. Haesbaert <haesbaert@haesbaert.org> 5 - Copyright (c) Citrix Inc 6 - Copyright (c) David Sheets <sheets@alum.mit.edu> 7 - Copyright (c) Drup <drupyog@zoho.com> 8 - Copyright (c) Hannes Mehnert <hannes@mehnert.org> 9 - Copyright (c) Jeremy Yallop <yallop@gmail.com> 10 - Copyright (c) Mindy Preston <meetup@yomimono.org> 11 - Copyright (c) Nicolas Ojeda Bar <n.oje.bar@gmail.com> 12 - Copyright (c) Richard Mortier <mort@cantab.net> 13 - Copyright (c) Rudi Grinberg <rudi.grinberg@gmail.com> 14 - Copyright (c) Thomas Gazagnaire <thomas@gazagnaire.com> 15 - Copyright (c) Thomas Leonard <talex5@gmail.com> 16 - Copyright (c) Vincent Bernardoff <vb@luminar.eu.org> 17 - Copyright (c) pqwy <david@numm.org> 18 - 19 - Permission to use, copy, modify, and distribute this software for any 20 - purpose with or without fee is hereby granted, provided that the above 21 - copyright notice and this permission notice appear in all copies. 22 - 23 - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 24 - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 25 - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 26 - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27 - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28 - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 29 - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 30 - #include <caml/mlvalues.h> 31 - #include <caml/memory.h> 32 - #include <caml/custom.h> 33 - #include <caml/callback.h> 34 - #include <caml/alloc.h> 35 - #include <caml/unixsupport.h> 36 - #include <caml/bigarray.h> 37 - #include <caml/threads.h> 38 - #include <caml/fail.h> 39 - 40 - #include <stdio.h> 41 - #include <errno.h> 42 - 43 - CAMLprim value eio_windows_cstruct_read(value val_fd, value val_c) 44 - { 45 - CAMLparam2(val_fd, val_c); 46 - CAMLlocal3(val_buf, val_ofs, val_len); 47 - uint8_t *buf; 48 - size_t len; 49 - ssize_t n = 0; 50 - int win32err = 0; 51 - SOCKET s; 52 - HANDLE h; 53 - DWORD numread; 54 - int ok; 55 - 56 - val_buf = Field(val_c, 0); 57 - val_ofs = Field(val_c, 1); 58 - val_len = Field(val_c, 2); 59 - 60 - buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); 61 - len = (size_t)Long_val(val_len); 62 - 63 - switch (Descr_kind_val(val_fd)) 64 - { 65 - case KIND_SOCKET: 66 - s = Socket_val(val_fd); 67 - 68 - caml_release_runtime_system(); 69 - n = recv(s, buf, len, 0); 70 - win32err = WSAGetLastError(); 71 - caml_acquire_runtime_system(); 72 - 73 - if (n == SOCKET_ERROR) 74 - { 75 - win32_maperr(win32err); 76 - uerror("stub_cstruct_read", Nothing); 77 - } 78 - break; 79 - case KIND_HANDLE: 80 - h = Handle_val(val_fd); 81 - caml_release_runtime_system(); 82 - ok = ReadFile(h, buf, len, &numread, NULL); 83 - win32err = GetLastError(); 84 - n = numread; 85 - caml_acquire_runtime_system(); 86 - 87 - if (!ok) 88 - { 89 - win32_maperr(win32err); 90 - uerror("stub_cstruct_read", Nothing); 91 - } 92 - break; 93 - default: 94 - caml_failwith("unknown Descr_kind_val"); 95 - } 96 - 97 - CAMLreturn(Val_int(n)); 98 - } 99 - 100 - CAMLprim value eio_windows_cstruct_write(value val_fd, value val_c) 101 - { 102 - CAMLparam2(val_fd, val_c); 103 - CAMLlocal3(val_buf, val_ofs, val_len); 104 - val_buf = Field(val_c, 0); 105 - val_ofs = Field(val_c, 1); 106 - val_len = Field(val_c, 2); 107 - void *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); 108 - size_t len = Long_val(val_len); 109 - ssize_t n = 0; 110 - 111 - int win32err = 0; 112 - switch (Descr_kind_val(val_fd)) 113 - { 114 - case KIND_SOCKET: 115 - SOCKET s = Socket_val(val_fd); 116 - 117 - caml_release_runtime_system(); 118 - n = send(s, buf, len, 0); 119 - win32err = WSAGetLastError(); 120 - caml_acquire_runtime_system(); 121 - 122 - if (n == SOCKET_ERROR) 123 - { 124 - win32_maperr(win32err); 125 - unix_error(errno, "stub_cstruct_write", Nothing); 126 - } 127 - break; 128 - case KIND_HANDLE: 129 - HANDLE h = Handle_val(val_fd); 130 - DWORD numwritten; 131 - caml_release_runtime_system(); 132 - int ok = WriteFile(h, buf, len, &numwritten, NULL); 133 - win32err = GetLastError(); 134 - 135 - n = numwritten; 136 - caml_acquire_runtime_system(); 137 - 138 - if (!ok) 139 - { 140 - win32_maperr(win32err); 141 - uerror("stub_cstruct_write", Nothing); 142 - } 143 - break; 144 - default: 145 - caml_failwith("unknown Descr_kind_val"); 146 - } 147 - 148 - CAMLreturn(Val_int(n)); 149 - }
+15 -4
lib_eio_windows/low_level.ml
··· 39 39 do_nonblocking ty fn fd 40 40 41 41 let read fd buf start len = 42 + await_readable fd; 42 43 Fd.use_exn "read" fd @@ fun fd -> 43 44 do_nonblocking Read (fun fd -> Unix.read fd buf start len) fd 44 45 45 - let read_cstruct fd buf = 46 + let read_cstruct fd (buf:Cstruct.t) = 47 + await_readable fd; 46 48 Fd.use_exn "read_cstruct" fd @@ fun fd -> 47 - do_nonblocking Read (fun fd -> Unix_cstruct.read fd buf) fd 49 + do_nonblocking Read (fun fd -> Unix.read_bigarray fd buf.buffer buf.off buf.len) fd 48 50 49 51 let write fd buf start len = 52 + await_writable fd; 50 53 Fd.use_exn "write" fd @@ fun fd -> 51 54 do_nonblocking Write (fun fd -> Unix.write fd buf start len) fd 55 + 56 + let write_cstruct fd (buf:Cstruct.t) = 57 + await_writable fd; 58 + Fd.use_exn "write_cstruct" fd @@ fun fd -> 59 + do_nonblocking Write (fun fd -> Unix.write_bigarray fd buf.buffer buf.off buf.len) fd 52 60 53 61 let sleep_until time = 54 62 Sched.enter @@ fun t k -> ··· 148 156 do_nonblocking Read (fun fd -> eio_readv fd bufs) fd 149 157 150 158 let writev fd bufs = 151 - Fd.use_exn "writev" fd @@ fun fd -> 152 - do_nonblocking Write (fun fd -> Unix_cstruct.writev fd bufs) fd 159 + let rec loop buf = if Cstruct.length buf > 0 then begin 160 + let n = write_cstruct fd buf in 161 + loop @@ Cstruct.shift buf n 162 + end in 163 + List.iter loop bufs 153 164 154 165 let preadv ~file_offset fd bufs = 155 166 Fd.use_exn "preadv" fd @@ fun fd ->
+1
lib_eio_windows/low_level.mli
··· 22 22 val read : fd -> bytes -> int -> int -> int 23 23 val read_cstruct : fd -> Cstruct.t -> int 24 24 val write : fd -> bytes -> int -> int -> int 25 + val write_cstruct : fd -> Cstruct.t -> int 25 26 26 27 val socket : sw:Switch.t -> Unix.socket_domain -> Unix.socket_type -> int -> fd 27 28 val connect : fd -> Unix.sockaddr -> unit