2525#include <caml/bigarray.h>
2626#include <caml/socketaddr.h>
2727#include <caml/custom.h>
28+ #include <caml/fail.h>
2829
2930#include "fork_action.h"
3031
@@ -66,9 +67,16 @@ CAMLprim value caml_eio_posix_getrandom(value v_ba, value v_off, value v_len) {
6667 CAMLreturn (Val_long (ret ));
6768}
6869
69- /* Fill [iov] with pointers to the cstructs in the array [v_bufs]. */
70- static void fill_iov (struct iovec * iov , value v_bufs ) {
70+ /* Allocates an array of C iovecs using the cstructs in the array [v_bufs]. */
71+ static struct iovec * alloc_iov (value v_bufs ) {
72+ struct iovec * iov ;
7173 int n_bufs = Wosize_val (v_bufs );
74+
75+ if (n_bufs == 0 ) return NULL ;
76+ iov = caml_stat_calloc_noexc (n_bufs , sizeof (struct iovec ));
77+ if (iov == NULL )
78+ caml_raise_out_of_memory ();
79+
7280 for (int i = 0 ; i < n_bufs ; i ++ ) {
7381 value v_cs = Field (v_bufs , i );
7482 value v_ba = Field (v_cs , 0 );
@@ -77,17 +85,18 @@ static void fill_iov(struct iovec *iov, value v_bufs) {
7785 iov [i ].iov_base = (uint8_t * )Caml_ba_data_val (v_ba ) + Long_val (v_off );
7886 iov [i ].iov_len = Long_val (v_len );
7987 }
88+ return iov ;
8089}
8190
8291CAMLprim value caml_eio_posix_readv (value v_fd , value v_bufs ) {
8392 CAMLparam1 (v_bufs );
8493 ssize_t r ;
8594 int n_bufs = Wosize_val (v_bufs );
86- struct iovec iov [n_bufs ];
87-
88- fill_iov (iov , v_bufs );
95+ struct iovec * iov ;
8996
97+ iov = alloc_iov (v_bufs );
9098 r = readv (Int_val (v_fd ), iov , n_bufs );
99+ caml_stat_free_preserving_errno (iov );
91100 if (r < 0 ) uerror ("readv" , Nothing );
92101
93102 CAMLreturn (Val_long (r ));
@@ -97,11 +106,11 @@ CAMLprim value caml_eio_posix_writev(value v_fd, value v_bufs) {
97106 CAMLparam1 (v_bufs );
98107 ssize_t r ;
99108 int n_bufs = Wosize_val (v_bufs );
100- struct iovec iov [n_bufs ];
101-
102- fill_iov (iov , v_bufs );
109+ struct iovec * iov ;
103110
111+ iov = alloc_iov (v_bufs );
104112 r = writev (Int_val (v_fd ), iov , n_bufs );
113+ caml_stat_free_preserving_errno (iov );
105114 if (r < 0 ) uerror ("writev" , Nothing );
106115
107116 CAMLreturn (Val_long (r ));
@@ -111,11 +120,11 @@ CAMLprim value caml_eio_posix_preadv(value v_fd, value v_bufs, value v_offset) {
111120 CAMLparam2 (v_bufs , v_offset );
112121 ssize_t r ;
113122 int n_bufs = Wosize_val (v_bufs );
114- struct iovec iov [n_bufs ];
115-
116- fill_iov (iov , v_bufs );
123+ struct iovec * iov ;
117124
125+ iov = alloc_iov (v_bufs );
118126 r = preadv (Int_val (v_fd ), iov , n_bufs , Int63_val (v_offset ));
127+ caml_stat_free_preserving_errno (iov );
119128 if (r < 0 ) uerror ("preadv" , Nothing );
120129
121130 CAMLreturn (Val_long (r ));
@@ -125,11 +134,11 @@ CAMLprim value caml_eio_posix_pwritev(value v_fd, value v_bufs, value v_offset)
125134 CAMLparam2 (v_bufs , v_offset );
126135 ssize_t r ;
127136 int n_bufs = Wosize_val (v_bufs );
128- struct iovec iov [n_bufs ];
129-
130- fill_iov (iov , v_bufs );
137+ struct iovec * iov ;
131138
139+ iov = alloc_iov (v_bufs );
132140 r = pwritev (Int_val (v_fd ), iov , n_bufs , Int63_val (v_offset ));
141+ caml_stat_free_preserving_errno (iov );
133142 if (r < 0 ) uerror ("pwritev" , Nothing );
134143
135144 CAMLreturn (Val_long (r ));
@@ -402,12 +411,11 @@ CAMLprim value caml_eio_posix_send_msg(value v_fd, value v_n_fds, value v_fds, v
402411 CAMLparam3 (v_fds , v_dst_opt , v_bufs );
403412 int n_bufs = Wosize_val (v_bufs );
404413 int n_fds = Int_val (v_n_fds );
405- struct iovec iov [n_bufs ];
406414 union sock_addr_union dst_addr ;
415+ struct iovec * iov ;
407416 int controllen = n_fds > 0 ? CMSG_SPACE (sizeof (int ) * n_fds ) : 0 ;
408417 char cmsg [controllen ];
409418 struct msghdr msg = {
410- .msg_iov = iov ,
411419 .msg_iovlen = n_bufs ,
412420 .msg_control = n_fds > 0 ? cmsg : NULL ,
413421 .msg_controllen = controllen ,
@@ -421,12 +429,14 @@ CAMLprim value caml_eio_posix_send_msg(value v_fd, value v_n_fds, value v_fds, v
421429 msg .msg_name = & dst_addr ;
422430 }
423431
424- fill_iov (iov , v_bufs );
432+ iov = alloc_iov (v_bufs );
433+ msg .msg_iov = iov ;
425434 fill_fds (& msg , n_fds , v_fds );
426435
427436 caml_enter_blocking_section ();
428437 r = sendmsg (Int_val (v_fd ), & msg , 0 );
429438 caml_leave_blocking_section ();
439+ caml_stat_free_preserving_errno (iov );
430440 if (r < 0 ) uerror ("send_msg" , Nothing );
431441
432442 CAMLreturn (Val_long (r ));
@@ -474,14 +484,13 @@ CAMLprim value caml_eio_posix_recv_msg(value v_fd, value v_max_fds, value v_bufs
474484 CAMLlocal2 (v_result , v_addr );
475485 int max_fds = Int_val (v_max_fds );
476486 int n_bufs = Wosize_val (v_bufs );
477- struct iovec iov [ n_bufs ] ;
487+ struct iovec * iov ;
478488 union sock_addr_union source_addr ;
479489 int controllen = max_fds > 0 ? CMSG_SPACE (sizeof (int ) * max_fds ) : 0 ;
480490 char cmsg [controllen ];
481491 struct msghdr msg = {
482492 .msg_name = & source_addr ,
483493 .msg_namelen = sizeof (source_addr ),
484- .msg_iov = iov ,
485494 .msg_iovlen = n_bufs ,
486495 .msg_control = max_fds > 0 ? cmsg : NULL ,
487496 .msg_controllen = controllen ,
@@ -490,11 +499,13 @@ CAMLprim value caml_eio_posix_recv_msg(value v_fd, value v_max_fds, value v_bufs
490499
491500 memset (cmsg , 0 , controllen );
492501
493- fill_iov (iov , v_bufs );
502+ iov = alloc_iov (v_bufs );
503+ msg .msg_iov = iov ;
494504
495505 caml_enter_blocking_section ();
496506 r = recvmsg (Int_val (v_fd ), & msg , 0 );
497507 caml_leave_blocking_section ();
508+ caml_stat_free_preserving_errno (iov );
498509 if (r < 0 ) uerror ("recv_msg" , Nothing );
499510
500511 v_addr = safe_caml_unix_alloc_sockaddr (& source_addr , msg .msg_namelen , -1 );
0 commit comments