You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bn...@apache.org on 2021/07/15 21:06:06 UTC
[trafficserver] branch master updated: Log meta file: ensure the
entire contents are written (#8062)
This is an automated email from the ASF dual-hosted git repository.
bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 870bbdb Log meta file: ensure the entire contents are written (#8062)
870bbdb is described below
commit 870bbdb18eb267e4fd0ebebf3d667ac0dd1d5479
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Thu Jul 15 16:05:21 2021 -0500
Log meta file: ensure the entire contents are written (#8062)
Updating the write of the meta file content for log rotation to ensure
that the entire line is written. If not, then the file will be
ill-formed which will lead eventually to an assertion when we try to
read from it later.
---
include/tscore/ink_sock.h | 32 ++++++++++++++++++++++++++++++++
src/tscore/BaseLogFile.cc | 21 ++++++++++++---------
src/tscore/ink_sock.cc | 43 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+), 9 deletions(-)
diff --git a/include/tscore/ink_sock.h b/include/tscore/ink_sock.h
index 3ea127e..6fff029 100644
--- a/include/tscore/ink_sock.h
+++ b/include/tscore/ink_sock.h
@@ -41,6 +41,18 @@ int safe_listen(int s, int backlog);
int safe_getsockname(int s, struct sockaddr *name, int *namelen);
int safe_getpeername(int s, struct sockaddr *name, int *namelen);
+/** Repeat write calls to fd until all len bytes are written.
+ *
+ * @param[in] fd The file descriptor to write to.
+ * @param[in] buffer The buffer of bytes to write into fd.
+ * @param[in] len The number of bytes in buffer to write into fd.
+ *
+ * @return The number of bytes written or -1 if there was an error writing to
+ * the file descriptor. If -1 is returned, errno should indicate why the
+ * write failed.
+ */
+int safe_write(int fd, const char *buffer, int len);
+
int safe_fcntl(int fd, int cmd, int arg);
int safe_ioctl(int fd, int request, char *arg);
@@ -50,8 +62,28 @@ int safe_clr_fl(int fd, int arg);
int safe_blocking(int fd);
int safe_nonblocking(int fd);
+/** Poll on fd until it is ready for reading.
+ *
+ * @param[in] fd The file descriptor to poll on.
+ * @param[in] timeout_msec How many milliseconds to poll on the socket before
+ * giving up.
+ *
+ * @return 1 if the socket is ready for reading, -1 if there was an error, and
+ * 0 for timeout.
+ */
int read_ready(int fd, int timeout_msec = 0);
+/** Poll on fd until it is ready for writing.
+ *
+ * @param[in] fd The file descriptor to poll on.
+ * @param[in] timeout_msec How many milliseconds to poll on the socket before
+ * giving up.
+ *
+ * @return 1 if the socket is ready for writing, -1 if there was an error, and
+ * 0 for timeout.
+ */
+int write_ready(int fd, int timeout_msec = 0);
+
char fd_read_char(int fd);
int fd_read_line(int fd, char *s, int len);
diff --git a/src/tscore/BaseLogFile.cc b/src/tscore/BaseLogFile.cc
index 280ad17..1c42f20 100644
--- a/src/tscore/BaseLogFile.cc
+++ b/src/tscore/BaseLogFile.cc
@@ -22,6 +22,7 @@
*/
#include "tscore/BaseLogFile.h"
+#include "tscore/ink_sock.h"
/*
* This constructor creates a BaseLogFile based on a given name.
@@ -532,24 +533,23 @@ BaseMetaInfo::_write_to_file()
}
log_log_trace("Successfully opened metafile=%s\n", _filename);
- int n;
if (_flags & VALID_CREATION_TIME) {
log_log_trace("Writing creation time to %s\n", _filename);
- n = snprintf(_buffer, BUF_SIZE, "creation_time = %lu\n", static_cast<unsigned long>(_creation_time));
+ int const num_to_write = snprintf(_buffer, BUF_SIZE, "creation_time = %lu\n", static_cast<unsigned long>(_creation_time));
// TODO modify this runtime check so that it is not an assertion
- ink_release_assert(n <= BUF_SIZE);
- if (write(fd, _buffer, n) == -1) {
- log_log_trace("Could not write creation_time");
+ ink_release_assert(num_to_write <= BUF_SIZE);
+ if (safe_write(fd, _buffer, num_to_write) == -1) {
+ log_log_error("Could not write creation_time: %s\n", strerror(errno));
}
}
if (_flags & VALID_SIGNATURE) {
log_log_trace("Writing signature to %s\n", _filename);
- n = snprintf(_buffer, BUF_SIZE, "object_signature = %" PRIu64 "\n", _log_object_signature);
+ int const num_to_write = snprintf(_buffer, BUF_SIZE, "object_signature = %" PRIu64 "\n", _log_object_signature);
// TODO modify this runtime check so that it is not an assertion
- ink_release_assert(n <= BUF_SIZE);
- if (write(fd, _buffer, n) == -1) {
- log_log_error("Could not write object_signature\n");
+ ink_release_assert(num_to_write <= BUF_SIZE);
+ if (safe_write(fd, _buffer, num_to_write) == -1) {
+ log_log_error("Could not write object_signature: %s\n", strerror(errno));
}
log_log_trace("BaseMetaInfo::_write_to_file\n"
"\tfilename = %s\n"
@@ -558,6 +558,9 @@ BaseMetaInfo::_write_to_file()
_filename, _log_object_signature, _buffer);
}
+ if (fsync(fd) == -1) {
+ log_log_error("Could not fsync the log meta file: %s\n", strerror(errno));
+ }
close(fd);
}
diff --git a/src/tscore/ink_sock.cc b/src/tscore/ink_sock.cc
index dbc0ae2..20332c4 100644
--- a/src/tscore/ink_sock.cc
+++ b/src/tscore/ink_sock.cc
@@ -27,6 +27,7 @@
***************************************************************************/
+#include "tscore/ink_sock.h"
#include "tscore/ink_platform.h"
#include "tscore/ink_assert.h"
#include "tscore/ink_string.h"
@@ -112,6 +113,29 @@ safe_clr_fl(int fd, int arg)
}
int
+safe_write(int fd, const char *buffer, int len)
+{
+ int num_written = 0;
+ while (num_written < len) {
+ int const ret = write(fd, buffer + num_written, len - num_written);
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ // The errno indicates that we should attempt the write again. Poll
+ // until the socket is ready for writing then try again.
+ if (write_ready(fd) != 1) {
+ return -1;
+ }
+ continue;
+ }
+ // Some unexpected errno was encountered.
+ return ret;
+ }
+ num_written += ret;
+ }
+ return num_written;
+}
+
+int
safe_nonblocking(int fd)
{
return safe_set_fl(fd, O_NONBLOCK);
@@ -143,6 +167,25 @@ read_ready(int fd, int timeout_msec)
}
int
+write_ready(int fd, int timeout_msec)
+{
+ struct pollfd p;
+ p.events = POLLOUT;
+ p.fd = fd;
+ int r = poll(&p, 1, timeout_msec);
+ if (r <= 0) {
+ return r;
+ }
+ if (p.revents & (POLLERR | POLLNVAL)) {
+ return -1;
+ }
+ if (p.revents & POLLOUT) {
+ return 1;
+ }
+ return 0;
+}
+
+int
safe_ioctl(int fd, int request, char *arg)
{
int r = -1;