blob: 0529391c51fab1ed34ed627a897fd69a5001a10d [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_LIBC_CLOSE_TRACKING_H_
#define CHROME_BROWSER_CHROMEOS_LIBC_CLOSE_TRACKING_H_
// Debugging code for http://crbug.com/660960 where close() fails with EBADF.
// The primary suspicion is that some piece of code is closing a FD that does
// not belong to it. Unfortunately the PCHECK in ScopedFDCloseTraits::Free
// is too late and reports only victim rather than the culprit. Another
// possibility is memory corruption (or object holding fd released and its
// memory got over-written). In such case, LOG(FATAL) includes fd and errno
// and it should help us to identify the case.
//
// The code here interposes libc close() calls to track the last good calls
// on a fd and reports it when libc close() on it fails.
//
// Note:
// 1. The libc close() interposition happens at build time by exporting
// "close" symbol and alias it to our CloseOverride function. All close()
// calls will be redirected regardless whether stack tracking is enabled
// or not.
// 2. Interposition captures libc close() calls but not direct syscalls.
// To capture direct syscalls, ptrace is needed and it needs to run in a
// master process with chrome browser process as its debuggee. This would
// need a complicated setup and introduce significant overhead as all close
// calls are hooked to the master process to extract stacks etc. Since
// most (all?) chrome code calls libc close() instead of direct syscalls,
// the interposition way is a better first step.
//
// TODO(xiyuan): Remove after http://crbug.com/660960.
namespace base {
namespace debug {
class StackTrace;
} // namespace debug
} // namespace base
namespace chromeos {
// Enables the stack tracking for the process where InitCloseTracking gets
// called (this should be the browser process) so that last good close stacks
// are collected and sent along with crash reports.
void InitCloseTracking();
// Cleans up and disables the stack tracking for close().
void ShutdownCloseTracking();
// Gets the last close stack trace for the given fd.
const base::debug::StackTrace* GetLastCloseStackForTest(int fd);
// Sets the boolean flag to ignore pid check for tracking in test.
void SetCloseTrackingIgnorePidForTest(bool ignore_pid);
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LIBC_CLOSE_TRACKING_H_