File 1672-erts-Fix-large-read-writes-on-macOS.patch of Package erlang
From 434c97f4596bb9df4d132f7f3bf51aac6376de6d Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Fri, 26 Aug 2022 09:37:43 +0200
Subject: [PATCH 1/2] erts: Fix large read/writes on macOS
On macOS there is an (as far as I can tell) undocumented limitation
for read and write that the size is not allowed to be greater than
2GB. So if we get an EINVAL from read/write and the size is > 2GB
we try again with a smaller size.
Closes #6242
---
erts/emulator/nifs/unix/unix_prim_file.c | 12 ++++++++++++
lib/kernel/test/file_SUITE.erl | 15 +++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/erts/emulator/nifs/unix/unix_prim_file.c b/erts/emulator/nifs/unix/unix_prim_file.c
index d110ead1e5..ff47d08ec4 100644
--- a/erts/emulator/nifs/unix/unix_prim_file.c
+++ b/erts/emulator/nifs/unix/unix_prim_file.c
@@ -42,6 +42,8 @@
#include <utime.h>
+#define FALLBACK_RW_LENGTH ((1ull << 31) - 1)
+
/* Macros for testing file types. */
#ifdef NO_UMASK
#define FILE_MODE 0644
@@ -284,6 +286,11 @@ Sint64 efile_readv(efile_data_t *d, SysIOVec *iov, int iovlen) {
if(use_fallback) {
result = read(u->fd, iov->iov_base, iov->iov_len);
+
+ /* Some OSs (e.g. macOS) does not allow reads greater than 2 GB,
+ so if we get EINVAL in the fallback, we try with a smaller length */
+ if (result < 0 && errno == EINVAL && iov->iov_len > FALLBACK_RW_LENGTH)
+ result = read(u->fd, iov->iov_base, FALLBACK_RW_LENGTH);
}
if(result > 0) {
@@ -329,6 +336,11 @@ Sint64 efile_writev(efile_data_t *d, SysIOVec *iov, int iovlen) {
if(use_fallback) {
result = write(u->fd, iov->iov_base, iov->iov_len);
+
+ /* Some OSs (e.g. macOS) does not allow writes greater than 2 GB,
+ so if we get EINVAL in the fallback, we try with a smaller length */
+ if (result < 0 && errno == EINVAL && iov->iov_len > FALLBACK_RW_LENGTH)
+ result = write(u->fd, iov->iov_base, FALLBACK_RW_LENGTH);
}
if(result > 0) {
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 52ef711008..dc9d0ebb2c 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -4088,6 +4088,21 @@ do_large_file(Name) ->
{ok,R} = ?FILE_MODULE:read(F1, L+1),
ok = ?FILE_MODULE:close(F1),
+ %% Reopen the file try to read all of it; used to fail on macOS
+ %% We open with binary in order to not get a memory explosion.
+ {ok, F2} = ?FILE_MODULE:open(Name, [raw,read,binary]),
+ IsWindows = element(1,os:type()) =:= win32,
+ case {?FILE_MODULE:read(F2, P), erlang:system_info(wordsize)} of
+ {{ok, B}, 8} ->
+ P = byte_size(B);
+ {eof, 8} when IsWindows ->
+ ok;
+ {eof, 4} ->
+ %% Cannot read such large files on 32-bit
+ ok
+ end,
+ ok = ?FILE_MODULE:close(F2),
+
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--
2.35.3