Skip to content

Commit 2d9b1a6

Browse files
elifaslan1Paul Hohensee
authored andcommitted
8303942: os::write should write completely
8316468: os::write incorrectly handles partial write 8183227: read/write APIs in class os shall return ssize_t Reviewed-by: phh, shade Backport-of: bddf48380e658df630fecad5eda40106a24b6e1c
1 parent 17d65fe commit 2d9b1a6

File tree

12 files changed

+85
-71
lines changed

12 files changed

+85
-71
lines changed

src/hotspot/os/linux/attachListener_linux.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -384,7 +384,7 @@ LinuxAttachOperation* LinuxAttachListener::dequeue() {
384384
// write the given buffer to the socket
385385
int LinuxAttachListener::write_fully(int s, char* buf, int len) {
386386
do {
387-
int n = ::write(s, buf, len);
387+
ssize_t n = ::write(s, buf, len);
388388
if (n == -1) {
389389
if (errno != EINTR) return -1;
390390
} else {

src/hotspot/os/posix/os_posix.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -739,9 +739,9 @@ FILE* os::open(int fd, const char* mode) {
739739
return ::fdopen(fd, mode);
740740
}
741741

742-
size_t os::write(int fd, const void *buf, unsigned int nBytes) {
743-
size_t res;
744-
RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
742+
ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
743+
ssize_t res;
744+
RESTARTABLE(::write(fd, buf, nBytes), res);
745745
return res;
746746
}
747747

src/hotspot/os/posix/perfMemory_posix.cpp

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -89,38 +89,25 @@ static void save_memory_to_file(char* addr, size_t size) {
8989
const char* destfile = PerfMemory::get_perfdata_file_path();
9090
assert(destfile[0] != '\0', "invalid PerfData file path");
9191

92-
int result;
92+
int fd;
9393

94-
RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR),
95-
result);
96-
if (result == OS_ERR) {
97-
if (PrintMiscellaneous && Verbose) {
98-
warning("Could not create Perfdata save file: %s: %s\n",
99-
destfile, os::strerror(errno));
100-
}
94+
RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR), fd);
95+
if (fd == OS_ERR) {
96+
warning("Could not create Perfdata save file: %s: %s\n",
97+
destfile, os::strerror(errno));
10198
} else {
102-
int fd = result;
99+
ssize_t result;
103100

104-
for (size_t remaining = size; remaining > 0;) {
105-
106-
RESTARTABLE(::write(fd, addr, remaining), result);
107-
if (result == OS_ERR) {
108-
if (PrintMiscellaneous && Verbose) {
109-
warning("Could not write Perfdata save file: %s: %s\n",
110-
destfile, os::strerror(errno));
111-
}
112-
break;
113-
}
114-
115-
remaining -= (size_t)result;
116-
addr += result;
101+
bool successful_write = os::write(fd, addr, size);
102+
if (!successful_write) {
103+
warning("Could not write Perfdata save file: %s: %s\n",
104+
destfile, os::strerror(errno));
117105
}
118106

107+
119108
result = ::close(fd);
120-
if (PrintMiscellaneous && Verbose) {
121-
if (result == OS_ERR) {
122-
warning("Could not close %s: %s\n", destfile, os::strerror(errno));
123-
}
109+
if (result == OS_ERR) {
110+
warning("Could not close %s: %s\n", destfile, os::strerror(errno));
124111
}
125112
}
126113
FREE_C_HEAP_ARRAY(char, destfile);
@@ -880,9 +867,9 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
880867
// Open the filename in the current directory.
881868
// Cannot use O_TRUNC here; truncation of an existing file has to happen
882869
// after the is_file_secure() check below.
883-
int result;
884-
RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), result);
885-
if (result == OS_ERR) {
870+
int fd;
871+
RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), fd);
872+
if (fd == OS_ERR) {
886873
if (PrintMiscellaneous && Verbose) {
887874
if (errno == ELOOP) {
888875
warning("file %s is a symlink and is not secure\n", filename);
@@ -898,9 +885,6 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
898885
// close the directory and reset the current working directory
899886
close_directory_secure_cwd(dirp, saved_cwd_fd);
900887

901-
// save the file descriptor
902-
int fd = result;
903-
904888
// check to see if the file is secure
905889
if (!is_file_secure(fd, filename)) {
906890
::close(fd);
@@ -933,6 +917,8 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
933917
}
934918
#endif
935919

920+
ssize_t result;
921+
936922
// truncate the file to get rid of any existing data
937923
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
938924
if (result == OS_ERR) {
@@ -959,19 +945,19 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
959945
int zero_int = 0;
960946
result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
961947
if (result == -1 ) break;
962-
RESTARTABLE(::write(fd, &zero_int, 1), result);
963-
if (result != 1) {
948+
if (!os::write(fd, &zero_int, 1)) {
964949
if (errno == ENOSPC) {
965950
warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
966951
}
952+
result = OS_ERR;
967953
break;
968954
}
969955
}
970956

971957
if (result != -1) {
972958
return fd;
973959
} else {
974-
::close(fd);
960+
os::close(fd);
975961
return -1;
976962
}
977963
}

src/hotspot/os/windows/os_windows.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -4842,8 +4842,19 @@ FILE* os::open(int fd, const char* mode) {
48424842
return ::_fdopen(fd, mode);
48434843
}
48444844

4845-
size_t os::write(int fd, const void *buf, unsigned int nBytes) {
4846-
return ::write(fd, buf, nBytes);
4845+
ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
4846+
ssize_t original_len = (ssize_t)nBytes;
4847+
while (nBytes > 0) {
4848+
unsigned int len = nBytes > INT_MAX ? INT_MAX : (unsigned int)nBytes;
4849+
// On Windows, ::write takes 'unsigned int' no of bytes, so nBytes should be split if larger.
4850+
ssize_t written_bytes = ::write(fd, buf, len);
4851+
if (written_bytes < 0) {
4852+
return OS_ERR;
4853+
}
4854+
nBytes -= written_bytes;
4855+
buf = (char *)buf + written_bytes;
4856+
}
4857+
return original_len;
48474858
}
48484859

48494860
int os::close(int fd) {

src/hotspot/share/cds/filemap.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,8 +1420,7 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_me
14201420

14211421
void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
14221422
assert(_file_open, "must be");
1423-
size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
1424-
if (n != nbytes) {
1423+
if (!os::write(_fd, buffer, nbytes)) {
14251424
// If the shared archive is corrupted, close it and remove it.
14261425
close();
14271426
remove(_full_path);

src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,17 @@ static void write_repository_files(const RepositoryIterator& iterator, char* con
350350
const ssize_t read_result = os::read_at(current_fd, copy_block, (int)block_size, bytes_read);
351351
if (-1 == read_result) {
352352
log_info(jfr)( // For user, should not be "jfr, system"
353-
"Unable to recover JFR data");
353+
"Unable to recover JFR data, read failed.");
354354
break;
355355
}
356356
bytes_read += (int64_t)read_result;
357357
assert(bytes_read - bytes_written <= (int64_t)block_size, "invariant");
358-
bytes_written += (int64_t)os::write(emergency_fd, copy_block, bytes_read - bytes_written);
359-
assert(bytes_read == bytes_written, "invariant");
358+
if (!os::write(emergency_fd, copy_block, bytes_read - bytes_written)) {
359+
log_info(jfr)( // For user, should not be "jfr, system"
360+
"Unable to recover JFR data, write failed.");
361+
break;
362+
}
363+
bytes_written = bytes_read;
360364
}
361365
os::close(current_fd);
362366
}

src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -76,14 +76,14 @@ inline void StreamWriterHost<Adapter, AP>::write_bytes(const u1* buf, intptr_t l
7676
assert(len >= 0, "invariant");
7777
while (len > 0) {
7878
const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len;
79-
const ssize_t num_written = (ssize_t)os::write(_fd, buf, nBytes);
80-
if (errno == ENOSPC) {
79+
const bool successful_write = os::write(_fd, buf, nBytes);
80+
if (!successful_write && errno == ENOSPC) {
8181
JfrJavaSupport::abort("Failed to write to jfr stream because no space left on device", false);
8282
}
83-
guarantee(num_written > 0, "Nothing got written, or os::write() failed");
84-
_stream_pos += num_written;
85-
len -= num_written;
86-
buf += num_written;
83+
guarantee(successful_write, "Not all the bytes got written, or os::write() failed");
84+
_stream_pos += nBytes;
85+
len -= nBytes;
86+
buf += nBytes;
8787
}
8888
}
8989

src/hotspot/share/prims/jvm.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -2823,7 +2823,7 @@ void jio_print(const char* s, size_t len) {
28232823
jio_fprintf(defaultStream::output_stream(), "%.*s", (int)len, s);
28242824
} else {
28252825
// Make an unused local variable to avoid warning from gcc compiler.
2826-
size_t count = ::write(defaultStream::output_fd(), s, (int)len);
2826+
bool dummy = os::write(defaultStream::output_fd(), s, len);
28272827
}
28282828
}
28292829

src/hotspot/share/runtime/os.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,22 @@ bool os::file_exists(const char* filename) {
13561356
return os::stat(filename, &statbuf) == 0;
13571357
}
13581358

1359+
bool os::write(int fd, const void *buf, size_t nBytes) {
1360+
ssize_t res;
1361+
1362+
while (nBytes > 0) {
1363+
res = pd_write(fd, buf, nBytes);
1364+
if (res == OS_ERR) {
1365+
return false;
1366+
}
1367+
buf = (void *)((char *)buf + res);
1368+
nBytes -= res;
1369+
}
1370+
1371+
return true;
1372+
}
1373+
1374+
13591375
// Splits a path, based on its separator, the number of
13601376
// elements is returned back in "elements".
13611377
// file_name_length is used as a modifier for each path's

src/hotspot/share/runtime/os.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -169,6 +169,8 @@ class os: AllStatic {
169169
// Get summary strings for system information in buffer provided
170170
static void get_summary_cpu_info(char* buf, size_t buflen);
171171
static void get_summary_os_info(char* buf, size_t buflen);
172+
// Returns number of bytes written on success, OS_ERR on failure.
173+
static ssize_t pd_write(int fd, const void *buf, size_t nBytes);
172174

173175
static void initialize_initial_active_processor_count();
174176

@@ -580,7 +582,8 @@ class os: AllStatic {
580582

581583
static ssize_t read(int fd, void *buf, unsigned int nBytes);
582584
static ssize_t read_at(int fd, void *buf, unsigned int nBytes, jlong offset);
583-
static size_t write(int fd, const void *buf, unsigned int nBytes);
585+
// Writes the bytes completely. Returns true on success, false otherwise.
586+
static bool write(int fd, const void *buf, size_t nBytes);
584587

585588
// Reading directories.
586589
static DIR* opendir(const char* dirname);

0 commit comments

Comments
 (0)