File: logging.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (131 lines) | stat: -rw-r--r-- 4,745 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/logging/logging.h"

#include <cstdio>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/platform_file.h"
#include "base/files/scoped_file.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/system/sys_info.h"
#include "base/task/thread_pool.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/zygote_host/zygote_host_linux.h"

namespace ash {

namespace {

// This is true when logging redirect was tried for the first user in the
// session.
bool g_chrome_logging_redirect_tried = false;

// This should be set to true for tests that rely on log redirection.
bool g_force_log_redirection = false;

template <typename ProcessHost>
void ReinitializeLoggingForProcessHost(ProcessHost* process_host,
                                       const logging::LoggingSettings& settings,
                                       base::PlatformFile raw_log_file_fd) {
  static_assert(std::is_same<content::ChildProcessHost, ProcessHost>() ||
                std::is_same<content::RenderProcessHost, ProcessHost>());

  base::ScopedFD log_file_descriptor(HANDLE_EINTR(dup(raw_log_file_fd)));
  if (log_file_descriptor.get() < 0) {
    DLOG(WARNING) << "Unable to duplicate log file handle";
    return;
  }

  process_host->ReinitializeLogging(settings.logging_dest,
                                    std::move(log_file_descriptor));
}

void LogFileSetUp(const base::CommandLine& command_line,
                  const base::FilePath& log_path,
                  const base::FilePath& target_path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // The |log_path| is the new log file after log rotation. so it shouldn't be
  // deleted even if it already exists.
  logging::LoggingSettings settings;
  settings.logging_dest = logging::DetermineLoggingDestination(command_line);
  settings.log_file_path = log_path.value().c_str();
  if (!logging::InitLogging(settings)) {
    DLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
    base::ThreadPool::PostTask(
        FROM_HERE, {base::MayBlock()},
        base::BindOnce(&logging::RemoveSymlinkAndLog, log_path, target_path));
    return;
  }

  base::ScopedFILE log_file(logging::DuplicateLogFILE());
  base::PlatformFile log_file_fd = fileno(log_file.get());
  if (log_file_fd < 0) {
    DLOG(WARNING) << "Unable to duplicate log file handle";
    return;
  }

  // Redirect Zygote and future children's logs.
  content::ZygoteHost::GetInstance()->ReinitializeLogging(settings.logging_dest,
                                                          log_file_fd);

  // Redirect child processes' logs.
  for (content::BrowserChildProcessHostIterator it; !it.Done(); ++it)
    ReinitializeLoggingForProcessHost(it.GetHost(), settings, log_file_fd);

  for (auto it(content::RenderProcessHost::AllHostsIterator()); !it.IsAtEnd();
       it.Advance()) {
    ReinitializeLoggingForProcessHost(it.GetCurrentValue(), settings,
                                      log_file_fd);
  }
}

}  // namespace

void ForceLogRedirectionForTesting() {
  g_force_log_redirection = true;
}

void RedirectChromeLogging(const base::CommandLine& command_line) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Only redirect when on an actual device. To do otherwise conflicts with
  // --vmodule that developers may want to use.
  if (!base::SysInfo::IsRunningOnChromeOS() && !g_force_log_redirection)
    return;

  if (g_chrome_logging_redirect_tried) {
    LOG(WARNING) << "NOT redirecting logging for multi-profiles case.";
    return;
  }

  g_chrome_logging_redirect_tried = true;

  if (command_line.HasSwitch(switches::kDisableLoggingRedirect))
    return;

  // Redirect logs to the session log directory, if set.  Otherwise
  // defaults to the profile dir.
  const base::FilePath log_path = logging::GetSessionLogFile(command_line);

  LOG(WARNING) << "Redirecting post-login logging to " << log_path.value();

  // Rotate the old log files when redirecting.
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE, {base::MayBlock()},
      base::BindOnce(&logging::SetUpLogFile, log_path, /*new_log=*/true),
      base::BindOnce(&LogFileSetUp, command_line, log_path));
}

}  // namespace ash