You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by wz...@apache.org on 2021/11/17 16:51:51 UTC

[impala] 02/02: IMPALA-11020: Reattach STDOUT/STDERR independently.

This is an automated email from the ASF dual-hosted git repository.

wzhou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit a690b746271c55408ce8a3f0dd0251a8f3ff8cfc
Author: Riza Suminto <ri...@cloudera.com>
AuthorDate: Mon Nov 15 14:01:18 2021 -0800

    IMPALA-11020: Reattach STDOUT/STDERR independently.
    
    IMPALA-5256 made an incorrect assumption that glog will rotate both INFO
    and ERROR logs at the same time. A race condition can happen between
    glog's log rotation and symlink resolutions in AttachStdoutStderrLocked
    because impala does not hold glog's log_mutex.
    
    This patch fixes the issue by replacing the DCHECK with a log, warning
    if only one symlink has changed. We then reattach the stream only for
    the one pointing to a new file. The next AttachStdoutStderr call after
    logbufsecs will handle redirection for the slower log rotation. This
    patch also adds explicit log flush after logging statements that intent
    to initialize a new log file.
    
    Testing:
    - Pass the exhaustive test.
    
    Change-Id: I35bbed631773bf7a4d55b2b77df1a093f34dedc5
    Reviewed-on: http://gerrit.cloudera.org:8080/18031
    Reviewed-by: Joe McDonnell <jo...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/common/logging.cc | 44 +++++++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/be/src/common/logging.cc b/be/src/common/logging.cc
index debdd2f..7291858 100644
--- a/be/src/common/logging.cc
+++ b/be/src/common/logging.cc
@@ -97,8 +97,8 @@ impala::Status ResolveLogSymlink(const string& symlink_path, string& canonical_p
 // The main implementation of AttachStdoutStderr().
 // Caller must hold lock over logging_mutex.
 impala::Status AttachStdoutStderrLocked() {
+  // Redirect stdout to INFO log and stderr to ERROR log.
   // Needs to be done after InitGoogleLogging, to get the INFO/ERROR file paths.
-  // Redirect stdout to INFO log and stderr to ERROR log
   string info_log_symlink_path, error_log_symlink_path;
   impala::GetFullLogFilename(google::INFO, &info_log_symlink_path);
   impala::GetFullLogFilename(google::ERROR, &error_log_symlink_path);
@@ -107,29 +107,37 @@ impala::Status AttachStdoutStderrLocked() {
   RETURN_IF_ERROR(ResolveLogSymlink(info_log_symlink_path, info_log_path));
   RETURN_IF_ERROR(ResolveLogSymlink(error_log_symlink_path, error_log_path));
 
-  if (last_info_log_path != info_log_path || last_error_log_path != error_log_path) {
-    // Both INFO and ERROR log should be rotated together at the same time.
-    DCHECK_NE(last_info_log_path, info_log_path);
-    DCHECK_NE(last_error_log_path, error_log_path);
-
-    // The log files are created on first use, log something to each before redirecting.
-    LOG(INFO) << "stdout will be logged to this file.";
-    LOG(ERROR) << "stderr will be logged to this file.";
+  bool info_log_rotated = last_info_log_path != info_log_path;
+  bool error_log_rotated = last_error_log_path != error_log_path;
+
+  if (info_log_rotated != error_log_rotated) {
+    // Since we're not holding glog's log_mutex when resolving the symlinks, it is
+    // possible that glog rotates the INFO and ERROR log independently in between our
+    // symlink resolution. If this happens, log a warning and continue.
+    // Next AttachStdoutStderrLocked call should redirect the stream to the newer file.
+    LOG(WARNING) << "INFO and ERROR log is not rotated at the same time "
+                 << "(info_log_rotated=" << info_log_rotated << ", "
+                 << "error_log_rotated=" << error_log_rotated << "). "
+                 << "STDOUT/STDERR might still write to an older log file.";
+  }
 
-    // Print to stderr/stdout before redirecting so people looking for these logs in
-    // the standard place know where to look.
+  if (info_log_rotated) {
+    // Print to stdout before redirecting so people looking for these logs in the standard
+    // place know where to look.
     cout << "Redirecting stdout to " << info_log_symlink_path << endl;
-    cerr << "Redirecting stderr to " << error_log_symlink_path << endl;
-
     // TODO: how to handle these errors? Maybe abort the process?
     if (freopen(info_log_path.c_str(), "a", stdout) == NULL) {
       cout << "Could not redirect stdout: " << impala::GetStrErrMsg();
     }
+    last_info_log_path = info_log_path;
+  }
+
+  if (error_log_rotated) {
+    // Similar to stdout, do the same thing for stderr.
+    cerr << "Redirecting stderr to " << error_log_symlink_path << endl;
     if (freopen(error_log_path.c_str(), "a", stderr) == NULL) {
       cerr << "Could not redirect stderr: " << impala::GetStrErrMsg();
     }
-
-    last_info_log_path = info_log_path;
     last_error_log_path = error_log_path;
   }
   return impala::Status::OK();
@@ -189,6 +197,11 @@ void impala::InitGoogleLoggingSafe(const char* arg) {
   }
 
   if (RedirectStdoutStderr()) {
+    // The log files are created on first use, log something to each and flush before
+    // redirecting.
+    LOG(INFO) << "stdout will be logged to this file.";
+    LOG(ERROR) << "stderr will be logged to this file.";
+    google::FlushLogFiles(google::GLOG_INFO);
     Status status = AttachStdoutStderrLocked();
     if (!status.ok()) {
       LOG(ERROR) << "Failed to attach STDOUT/STDERR: " << status.GetDetail();
@@ -233,6 +246,7 @@ void impala::ForceRotateLog() {
   google::SetLogFilenameExtension("");
   LOG(INFO) << "INFO log rotated by Impala due to max_log_size exceeded.";
   LOG(ERROR) << "ERROR log rotated by Impala due to max_log_size exceeded.";
+  google::FlushLogFiles(google::GLOG_INFO);
 }
 
 bool impala::RedirectStdoutStderr() {