mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-10-04 23:50:50 +00:00
233 lines
10 KiB
C++
233 lines
10 KiB
C++
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
|
|
// Copyright (c) 2006, Google Inc.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following disclaimer
|
|
// in the documentation and/or other materials provided with the
|
|
// distribution.
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
// contributors may be used to endorse or promote products derived from
|
|
// this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
// All functions here are thread-hostile due to file caching unless
|
|
// commented otherwise.
|
|
|
|
#ifndef _SYSINFO_H_
|
|
#define _SYSINFO_H_
|
|
|
|
#include "../config.h"
|
|
|
|
#include <time.h>
|
|
#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
|
|
#include <windows.h> // for DWORD
|
|
#include <tlhelp32.h> // for CreateToolhelp32Snapshot
|
|
#endif
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h> // for pid_t
|
|
#endif
|
|
#include <stddef.h> // for size_t
|
|
#include <limits.h> // for PATH_MAX
|
|
#include "base/basictypes.h"
|
|
#include "base/logging.h" // for RawFD
|
|
|
|
// This getenv function is safe to call before the C runtime is initialized.
|
|
// On Windows, it utilizes GetEnvironmentVariable() and on unix it uses
|
|
// /proc/self/environ instead calling getenv(). It's intended to be used in
|
|
// routines that run before main(), when the state required for getenv() may
|
|
// not be set up yet. In particular, errno isn't set up until relatively late
|
|
// (after the pthreads library has a chance to make it threadsafe), and
|
|
// getenv() doesn't work until then.
|
|
// On some platforms, this call will utilize the same, static buffer for
|
|
// repeated GetenvBeforeMain() calls. Callers should not expect pointers from
|
|
// this routine to be long lived.
|
|
// Note that on unix, /proc only has the environment at the time the
|
|
// application was started, so this routine ignores setenv() calls/etc. Also
|
|
// note it only reads the first 16K of the environment.
|
|
extern const char* GetenvBeforeMain(const char* name);
|
|
|
|
// This takes as an argument an environment-variable name (like
|
|
// CPUPROFILE) whose value is supposed to be a file-path, and sets
|
|
// path to that path, and returns true. Non-trivial for surprising
|
|
// reasons, as documented in sysinfo.cc. path must have space PATH_MAX.
|
|
extern bool GetUniquePathFromEnv(const char* env_name, char* path);
|
|
|
|
extern int GetSystemCPUsCount();
|
|
|
|
void SleepForMilliseconds(int milliseconds);
|
|
|
|
// Return true if we're running POSIX (e.g., NPTL on Linux) threads,
|
|
// as opposed to a non-POSIX thread library. The thing that we care
|
|
// about is whether a thread's pid is the same as the thread that
|
|
// spawned it. If so, this function returns true.
|
|
// Thread-safe.
|
|
// Note: We consider false negatives to be OK.
|
|
bool HasPosixThreads();
|
|
|
|
#ifndef SWIG // SWIG doesn't like struct Buffer and variable arguments.
|
|
|
|
// A ProcMapsIterator abstracts access to /proc/maps for a given
|
|
// process. Needs to be stack-allocatable and avoid using stdio/malloc
|
|
// so it can be used in the google stack dumper, heap-profiler, etc.
|
|
//
|
|
// On Windows and Mac OS X, this iterator iterates *only* over DLLs
|
|
// mapped into this process space. For Linux, FreeBSD, and Solaris,
|
|
// it iterates over *all* mapped memory regions, including anonymous
|
|
// mmaps. For other O/Ss, it is unlikely to work at all, and Valid()
|
|
// will always return false. Also note: this routine only works on
|
|
// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
|
|
// proc /proc procfs rw 0 0
|
|
class ProcMapsIterator {
|
|
public:
|
|
struct Buffer {
|
|
#ifdef __FreeBSD__
|
|
// FreeBSD requires us to read all of the maps file at once, so
|
|
// we have to make a buffer that's "always" big enough
|
|
static const size_t kBufSize = 102400;
|
|
#else // a one-line buffer is good enough
|
|
static const size_t kBufSize = PATH_MAX + 1024;
|
|
#endif
|
|
char buf_[kBufSize];
|
|
};
|
|
|
|
|
|
// Create a new iterator for the specified pid. pid can be 0 for "self".
|
|
explicit ProcMapsIterator(pid_t pid);
|
|
|
|
// Create an iterator with specified storage (for use in signal
|
|
// handler). "buffer" should point to a ProcMapsIterator::Buffer
|
|
// buffer can be NULL in which case a bufer will be allocated.
|
|
ProcMapsIterator(pid_t pid, Buffer *buffer);
|
|
|
|
// Iterate through maps_backing instead of maps if use_maps_backing
|
|
// is true. Otherwise the same as above. buffer can be NULL and
|
|
// it will allocate a buffer itself.
|
|
ProcMapsIterator(pid_t pid, Buffer *buffer,
|
|
bool use_maps_backing);
|
|
|
|
// Returns true if the iterator successfully initialized;
|
|
bool Valid() const;
|
|
|
|
// Returns a pointer to the most recently parsed line. Only valid
|
|
// after Next() returns true, and until the iterator is destroyed or
|
|
// Next() is called again. This may give strange results on non-Linux
|
|
// systems. Prefer FormatLine() if that may be a concern.
|
|
const char *CurrentLine() const { return stext_; }
|
|
|
|
// Writes the "canonical" form of the /proc/xxx/maps info for a single
|
|
// line to the passed-in buffer. Returns the number of bytes written,
|
|
// or 0 if it was not able to write the complete line. (To guarantee
|
|
// success, buffer should have size at least Buffer::kBufSize.)
|
|
// Takes as arguments values set via a call to Next(). The
|
|
// "canonical" form of the line (taken from linux's /proc/xxx/maps):
|
|
// <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> +
|
|
// <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
|
|
// eg
|
|
// 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat
|
|
// If you don't have the dev_t (dev), feel free to pass in 0.
|
|
// (Next() doesn't return a dev_t, though NextExt does.)
|
|
//
|
|
// Note: if filename and flags were obtained via a call to Next(),
|
|
// then the output of this function is only valid if Next() returned
|
|
// true, and only until the iterator is destroyed or Next() is
|
|
// called again. (Since filename, at least, points into CurrentLine.)
|
|
static int FormatLine(char* buffer, int bufsize,
|
|
uint64 start, uint64 end, const char *flags,
|
|
uint64 offset, int64 inode, const char *filename,
|
|
dev_t dev);
|
|
|
|
// Find the next entry in /proc/maps; return true if found or false
|
|
// if at the end of the file.
|
|
//
|
|
// Any of the result pointers can be NULL if you're not interested
|
|
// in those values.
|
|
//
|
|
// If "flags" and "filename" are passed, they end up pointing to
|
|
// storage within the ProcMapsIterator that is valid only until the
|
|
// iterator is destroyed or Next() is called again. The caller may
|
|
// modify the contents of these strings (up as far as the first NUL,
|
|
// and only until the subsequent call to Next()) if desired.
|
|
|
|
// The offsets are all uint64 in order to handle the case of a
|
|
// 32-bit process running on a 64-bit kernel
|
|
//
|
|
// IMPORTANT NOTE: see top-of-class notes for details about what
|
|
// mapped regions Next() iterates over, depending on O/S.
|
|
// TODO(csilvers): make flags and filename const.
|
|
bool Next(uint64 *start, uint64 *end, char **flags,
|
|
uint64 *offset, int64 *inode, char **filename);
|
|
|
|
bool NextExt(uint64 *start, uint64 *end, char **flags,
|
|
uint64 *offset, int64 *inode, char **filename,
|
|
uint64 *file_mapping, uint64 *file_pages,
|
|
uint64 *anon_mapping, uint64 *anon_pages,
|
|
dev_t *dev);
|
|
|
|
~ProcMapsIterator();
|
|
|
|
private:
|
|
void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);
|
|
|
|
char *ibuf_; // input buffer
|
|
char *stext_; // start of text
|
|
char *etext_; // end of text
|
|
char *nextline_; // start of next line
|
|
char *ebuf_; // end of buffer (1 char for a nul)
|
|
#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
|
|
HANDLE snapshot_; // filehandle on dll info
|
|
// In a change from the usual W-A pattern, there is no A variant of
|
|
// MODULEENTRY32. Tlhelp32.h #defines the W variant, but not the A.
|
|
// We want the original A variants, and this #undef is the only
|
|
// way I see to get them. Redefining it when we're done prevents us
|
|
// from affecting other .cc files.
|
|
# ifdef MODULEENTRY32 // Alias of W
|
|
# undef MODULEENTRY32
|
|
MODULEENTRY32 module_; // info about current dll (and dll iterator)
|
|
# define MODULEENTRY32 MODULEENTRY32W
|
|
# else // It's the ascii, the one we want.
|
|
MODULEENTRY32 module_; // info about current dll (and dll iterator)
|
|
# endif
|
|
#elif defined(__MACH__)
|
|
int current_image_; // dll's are called "images" in macos parlance
|
|
int current_load_cmd_; // the segment of this dll we're examining
|
|
#elif defined(__sun__) // Solaris
|
|
int fd_;
|
|
char current_filename_[PATH_MAX];
|
|
#else
|
|
int fd_; // filehandle on /proc/*/maps
|
|
#endif
|
|
pid_t pid_;
|
|
char flags_[10];
|
|
Buffer* dynamic_buffer_; // dynamically-allocated Buffer
|
|
bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
|
|
};
|
|
|
|
#endif /* #ifndef SWIG */
|
|
|
|
// Helper routines
|
|
|
|
namespace tcmalloc {
|
|
int FillProcSelfMaps(char buf[], int size, bool* wrote_all);
|
|
void DumpProcSelfMaps(RawFD fd);
|
|
}
|
|
|
|
#endif /* #ifndef _SYSINFO_H_ */
|