-
Notifications
You must be signed in to change notification settings - Fork 411
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
fix(rpc): ignore sigpipe on linux #7319
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
dune_util | ||
csexp | ||
fiber | ||
threads.posix | ||
(re_export unix)) | ||
(foreign_stubs | ||
(language c) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
open Stdune | ||
|
||
type t = | ||
{ mutable bytes : Bytes.t (* underlying bytes *) | ||
; (* the position we can start reading from (until [pos_w]) *) | ||
mutable pos_r : int | ||
; (* the position we can start writing to (until [Bytes.length bytes - 1]) *) | ||
mutable pos_w : int | ||
; (* total number of bytes written to this buffer. 2^63 bytes should be | ||
enough for anybody *) | ||
mutable total_written : int | ||
} | ||
|
||
type flush_token = int | ||
|
||
(* We can't use [Out_channel] for writes on Linux because we want to disable | ||
sigpipes. Eventually we'll move to event based IO and ditch the threads, | ||
so we'll need this anyway *) | ||
|
||
let create ~size = | ||
{ bytes = Bytes.create size; pos_r = 0; pos_w = 0; total_written = 0 } | ||
|
||
let length t = t.pos_w - t.pos_r | ||
|
||
let max_buffer_size = 65536 | ||
|
||
let maybe_resize_to_fit t write_size = | ||
let buf_len = Bytes.length t.bytes in | ||
let capacity = buf_len - t.pos_w in | ||
if capacity < write_size then ( | ||
rgrinberg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let bytes = | ||
let new_size = | ||
let needed = buf_len + write_size - capacity in | ||
max (min max_buffer_size (buf_len * 2)) needed | ||
in | ||
Bytes.create new_size | ||
in | ||
let len = length t in | ||
Bytes.blit ~src:t.bytes ~src_pos:t.pos_r ~dst:bytes ~dst_pos:0 ~len; | ||
t.bytes <- bytes; | ||
t.pos_w <- len; | ||
t.pos_r <- 0) | ||
|
||
let write_char_exn t c = | ||
assert (t.pos_w < Bytes.length t.bytes); | ||
Bytes.set t.bytes t.pos_w c; | ||
rgrinberg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
t.pos_w <- t.pos_w + 1 | ||
|
||
let write_string_exn t src = | ||
assert (t.pos_w < Bytes.length t.bytes); | ||
let len = String.length src in | ||
rgrinberg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Bytes.blit_string ~src ~src_pos:0 ~dst:t.bytes ~dst_pos:t.pos_w ~len; | ||
t.pos_w <- t.pos_w + len | ||
|
||
let read t len = | ||
let pos_r = t.pos_r + len in | ||
if pos_r > t.pos_w then | ||
Code_error.raise "not enough bytes in buffer" | ||
[ ("len", Dyn.int len); ("length", Dyn.int (length t)) ]; | ||
t.pos_r <- pos_r; | ||
t.total_written <- t.total_written + len | ||
|
||
let flush_token t = t.total_written + length t | ||
|
||
let flushed t token = t.total_written >= token | ||
|
||
let write_csexps = | ||
let rec loop t (csexp : Csexp.t) = | ||
match csexp with | ||
| Atom str -> | ||
write_string_exn t (string_of_int (String.length str)); | ||
write_char_exn t ':'; | ||
write_string_exn t str | ||
| List e -> | ||
write_char_exn t '('; | ||
List.iter ~f:(loop t) e; | ||
write_char_exn t ')' | ||
in | ||
fun t csexps -> | ||
let length = | ||
List.fold_left csexps ~init:0 ~f:(fun acc csexp -> | ||
acc + Csexp.serialised_length csexp) | ||
in | ||
maybe_resize_to_fit t length; | ||
List.iter ~f:(loop t) csexps | ||
|
||
let pos t = t.pos_r | ||
|
||
let bytes t = t.bytes | ||
|
||
let to_dyn ({ bytes; pos_r; pos_w; total_written } as t) = | ||
let open Dyn in | ||
record | ||
[ ("total_written", int total_written) | ||
; ("contents", string (Bytes.sub_string bytes ~pos:pos_r ~len:(length t))) | ||
; ("pos_w", int pos_w) | ||
; ("pos_r", int pos_r) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
(** A resizable IO buffer *) | ||
|
||
type t | ||
|
||
val to_dyn : t -> Dyn.t | ||
|
||
(** create a new io buffer *) | ||
val create : size:int -> t | ||
|
||
(** [read t n] reads [n] bytes *) | ||
val read : t -> int -> unit | ||
|
||
(** [write t csexps] write [csexps] to [t] while resizing [t] as necessary *) | ||
val write_csexps : t -> Csexp.t list -> unit | ||
|
||
(** a flush token is used to determine when a write has been completely flushed *) | ||
type flush_token | ||
|
||
(** [flush_token t] will be flushed whenever everything in [t] will be written *) | ||
val flush_token : t -> flush_token | ||
|
||
(** [flushed t token] will return [true] once all the data that was present in | ||
[t] when [token] was created will be written *) | ||
val flushed : t -> flush_token -> bool | ||
|
||
(** underlying raw buffer *) | ||
val bytes : t -> Bytes.t | ||
|
||
(** [pos t] in [bytes t] to read *) | ||
val pos : t -> int | ||
|
||
(** [length t] the number of bytes to read [bytes t] *) | ||
val length : t -> int |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A second question is that we repeatedly lock/unlock the mutex on each iteration of the write loop; is this better than holding on to the mutex until the writing is done? (eg by using a local function)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better because it's allowing callers to refill the write buffer on every send. Less write calls and more mutex locks sounds like a better trade off. Anyway, the mutex will be gone soon so I suggest we don't dwell on it.