Skip to content

Commit

Permalink
8303942: os::write should write completely
Browse files Browse the repository at this point in the history
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
  • Loading branch information
elifaslan1 authored and Paul Hohensee committed Jun 7, 2024
1 parent 17d65fe commit 2d9b1a6
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/hotspot/os/linux/attachListener_linux.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -384,7 +384,7 @@ LinuxAttachOperation* LinuxAttachListener::dequeue() {
// write the given buffer to the socket
int LinuxAttachListener::write_fully(int s, char* buf, int len) {
do {
int n = ::write(s, buf, len);
ssize_t n = ::write(s, buf, len);
if (n == -1) {
if (errno != EINTR) return -1;
} else {
Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/os/posix/os_posix.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -739,9 +739,9 @@ FILE* os::open(int fd, const char* mode) {
return ::fdopen(fd, mode);
}

size_t os::write(int fd, const void *buf, unsigned int nBytes) {
size_t res;
RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
ssize_t res;
RESTARTABLE(::write(fd, buf, nBytes), res);
return res;
}

Expand Down
58 changes: 22 additions & 36 deletions src/hotspot/os/posix/perfMemory_posix.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -89,38 +89,25 @@ static void save_memory_to_file(char* addr, size_t size) {
const char* destfile = PerfMemory::get_perfdata_file_path();
assert(destfile[0] != '\0', "invalid PerfData file path");

int result;
int fd;

RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR),
result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("Could not create Perfdata save file: %s: %s\n",
destfile, os::strerror(errno));
}
RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR), fd);
if (fd == OS_ERR) {
warning("Could not create Perfdata save file: %s: %s\n",
destfile, os::strerror(errno));
} else {
int fd = result;
ssize_t result;

for (size_t remaining = size; remaining > 0;) {

RESTARTABLE(::write(fd, addr, remaining), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("Could not write Perfdata save file: %s: %s\n",
destfile, os::strerror(errno));
}
break;
}

remaining -= (size_t)result;
addr += result;
bool successful_write = os::write(fd, addr, size);
if (!successful_write) {
warning("Could not write Perfdata save file: %s: %s\n",
destfile, os::strerror(errno));
}


result = ::close(fd);
if (PrintMiscellaneous && Verbose) {
if (result == OS_ERR) {
warning("Could not close %s: %s\n", destfile, os::strerror(errno));
}
if (result == OS_ERR) {
warning("Could not close %s: %s\n", destfile, os::strerror(errno));
}
}
FREE_C_HEAP_ARRAY(char, destfile);
Expand Down Expand Up @@ -880,9 +867,9 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
// Open the filename in the current directory.
// Cannot use O_TRUNC here; truncation of an existing file has to happen
// after the is_file_secure() check below.
int result;
RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), result);
if (result == OS_ERR) {
int fd;
RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), fd);
if (fd == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("file %s is a symlink and is not secure\n", filename);
Expand All @@ -898,9 +885,6 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);

// save the file descriptor
int fd = result;

// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
Expand Down Expand Up @@ -933,6 +917,8 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
}
#endif

ssize_t result;

// truncate the file to get rid of any existing data
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
if (result == OS_ERR) {
Expand All @@ -959,19 +945,19 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
int zero_int = 0;
result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
if (result == -1 ) break;
RESTARTABLE(::write(fd, &zero_int, 1), result);
if (result != 1) {
if (!os::write(fd, &zero_int, 1)) {
if (errno == ENOSPC) {
warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
}
result = OS_ERR;
break;
}
}

if (result != -1) {
return fd;
} else {
::close(fd);
os::close(fd);
return -1;
}
}
Expand Down
17 changes: 14 additions & 3 deletions src/hotspot/os/windows/os_windows.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -4842,8 +4842,19 @@ FILE* os::open(int fd, const char* mode) {
return ::_fdopen(fd, mode);
}

size_t os::write(int fd, const void *buf, unsigned int nBytes) {
return ::write(fd, buf, nBytes);
ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
ssize_t original_len = (ssize_t)nBytes;
while (nBytes > 0) {
unsigned int len = nBytes > INT_MAX ? INT_MAX : (unsigned int)nBytes;
// On Windows, ::write takes 'unsigned int' no of bytes, so nBytes should be split if larger.
ssize_t written_bytes = ::write(fd, buf, len);
if (written_bytes < 0) {
return OS_ERR;
}
nBytes -= written_bytes;
buf = (char *)buf + written_bytes;
}
return original_len;
}

int os::close(int fd) {
Expand Down
3 changes: 1 addition & 2 deletions src/hotspot/share/cds/filemap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1420,8 +1420,7 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_me

void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
assert(_file_open, "must be");
size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
if (n != nbytes) {
if (!os::write(_fd, buffer, nbytes)) {
// If the shared archive is corrupted, close it and remove it.
close();
remove(_full_path);
Expand Down
10 changes: 7 additions & 3 deletions src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,17 @@ static void write_repository_files(const RepositoryIterator& iterator, char* con
const ssize_t read_result = os::read_at(current_fd, copy_block, (int)block_size, bytes_read);
if (-1 == read_result) {
log_info(jfr)( // For user, should not be "jfr, system"
"Unable to recover JFR data");
"Unable to recover JFR data, read failed.");
break;
}
bytes_read += (int64_t)read_result;
assert(bytes_read - bytes_written <= (int64_t)block_size, "invariant");
bytes_written += (int64_t)os::write(emergency_fd, copy_block, bytes_read - bytes_written);
assert(bytes_read == bytes_written, "invariant");
if (!os::write(emergency_fd, copy_block, bytes_read - bytes_written)) {
log_info(jfr)( // For user, should not be "jfr, system"
"Unable to recover JFR data, write failed.");
break;
}
bytes_written = bytes_read;
}
os::close(current_fd);
}
Expand Down
14 changes: 7 additions & 7 deletions src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -76,14 +76,14 @@ inline void StreamWriterHost<Adapter, AP>::write_bytes(const u1* buf, intptr_t l
assert(len >= 0, "invariant");
while (len > 0) {
const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len;
const ssize_t num_written = (ssize_t)os::write(_fd, buf, nBytes);
if (errno == ENOSPC) {
const bool successful_write = os::write(_fd, buf, nBytes);
if (!successful_write && errno == ENOSPC) {
JfrJavaSupport::abort("Failed to write to jfr stream because no space left on device", false);
}
guarantee(num_written > 0, "Nothing got written, or os::write() failed");
_stream_pos += num_written;
len -= num_written;
buf += num_written;
guarantee(successful_write, "Not all the bytes got written, or os::write() failed");
_stream_pos += nBytes;
len -= nBytes;
buf += nBytes;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/prims/jvm.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -2823,7 +2823,7 @@ void jio_print(const char* s, size_t len) {
jio_fprintf(defaultStream::output_stream(), "%.*s", (int)len, s);
} else {
// Make an unused local variable to avoid warning from gcc compiler.
size_t count = ::write(defaultStream::output_fd(), s, (int)len);
bool dummy = os::write(defaultStream::output_fd(), s, len);
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/hotspot/share/runtime/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,22 @@ bool os::file_exists(const char* filename) {
return os::stat(filename, &statbuf) == 0;
}

bool os::write(int fd, const void *buf, size_t nBytes) {
ssize_t res;

while (nBytes > 0) {
res = pd_write(fd, buf, nBytes);
if (res == OS_ERR) {
return false;
}
buf = (void *)((char *)buf + res);
nBytes -= res;
}

return true;
}


// Splits a path, based on its separator, the number of
// elements is returned back in "elements".
// file_name_length is used as a modifier for each path's
Expand Down
7 changes: 5 additions & 2 deletions src/hotspot/share/runtime/os.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -169,6 +169,8 @@ class os: AllStatic {
// Get summary strings for system information in buffer provided
static void get_summary_cpu_info(char* buf, size_t buflen);
static void get_summary_os_info(char* buf, size_t buflen);
// Returns number of bytes written on success, OS_ERR on failure.
static ssize_t pd_write(int fd, const void *buf, size_t nBytes);

static void initialize_initial_active_processor_count();

Expand Down Expand Up @@ -580,7 +582,8 @@ class os: AllStatic {

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

// Reading directories.
static DIR* opendir(const char* dirname);
Expand Down
11 changes: 3 additions & 8 deletions src/hotspot/share/services/heapDumperCompression.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -54,14 +55,8 @@ char const* FileWriter::write_buf(char* buf, ssize_t size) {
assert(_fd >= 0, "Must be open");
assert(size > 0, "Must write at least one byte");

while (size > 0) {
ssize_t n = os::write(_fd, buf, (uint) size);
if (n <= 0) {
return os::strerror(errno);
}

buf += n;
size -= n;
if (!os::write(_fd, buf, (size_t)size)) {
return os::strerror(errno);
}

return NULL;
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/utilities/ostream.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -614,7 +614,7 @@ void fileStream::flush() {
void fdStream::write(const char* s, size_t len) {
if (_fd != -1) {
// Make an unused local variable to avoid warning from gcc compiler.
size_t count = ::write(_fd, s, (int)len);
ssize_t count = ::write(_fd, s, (int)len);
update_position(s, len);
}
}
Expand Down

1 comment on commit 2d9b1a6

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.