Update Libmv to latest upstream

This is mainly a maintaince commit which syncs changes
between Blender and Libmv upstream also bringing new
GLog version.

This GLog version is presumably have better support of
MinGW from "the box".

This commit is also aimed to make further 3d part libs
update easier.
This commit is contained in:
Sergey Sharybin 2014-03-20 23:03:11 +06:00
parent 2ea78fb28f
commit 6ba5c0c268
28 changed files with 996 additions and 670 deletions

@ -44,6 +44,8 @@ if(WITH_LIBMV)
)
list(APPEND INC
third_party/gflags
third_party/glog/src
third_party/ceres/include
../../intern/guardedalloc
)
@ -218,10 +220,6 @@ if(WITH_LIBMV)
third_party/glog/src/symbolize.h
third_party/glog/src/utilities.h
)
list(APPEND INC
third_party/glog/src
)
endif()
else()
list(APPEND SRC

285
extern/libmv/ChangeLog vendored

@ -1,3 +1,135 @@
commit a4f387680dbc1f8818fe3cd79174a9983127d89e
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Mar 20 23:07:34 2014 +0600
Compilation fixes for MinGW
Many thanks to Antony Riakiotakis for the patch!
commit f1aefcbf58fe04ea2967434f39f703bb486777c8
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Feb 27 16:21:19 2014 +0600
Implement separate BA step for tracks which have constant zero weight
This is needed to minimize their reprojection error over the footage.
Without this extra step positions of such tracks were calculated by
algebraic intersection code only, which doesn't give best precision.
commit bcf7f9470b2ea33cf89a31a72037ec03be631637
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Feb 27 14:16:42 2014 +0600
Avoid zero-sized problem when doing euclidean intersection
Zero-sized problem might occur when intersecting track with
constant zero weight. For such tracks we'll just use result
of algebraic intersection.
TODO: We probably need to have a separate BA step to adjust
positions of tracks with constant zero weight.
commit f884bb20a93189b8210639f3de939c64177d66b3
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Feb 26 18:00:40 2014 +0600
Ignore zero weighted markers in keyframe selection
It doesn't make sense to use zero-weighted tracks as a correspondences
in keyframe selection.
Such tracks are not guaranteed to be tracked accurately because their
purpose is to add reference points in 3D space without affecting the
solution.
commit 74db5175cdbcabe673b82eef59c88fb7f342c43f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Feb 26 13:23:02 2014 +0600
Tweaks to make bundling into Blender warning-less
Mainly issue i caused by conflicts in include directories,
so glog used to include config.h from gflags. It might be
fixed by splitting gflags/glog from Libmv in Blender build
system but that's not something fun to work on. Fixed by
making include directories bit more explicit.
Also solved no-previous-prototype warnings.
commit bc4bc66af0115069562b79e837ccf4fd95c8f97e
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 21 14:55:13 2014 +0600
Raise epsilon used for model solver test
It was too much small leading to false failure triggering
caused simply by precision issues.
commit bf750590a6af4af3622c01fd1004c44da60484a7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Feb 18 23:35:52 2014 +0600
Made it possible to link against Ceres installed on the system
Main purpose of this is to get away from bundled Ceres library
which is not so trivial to re-bundle and takes some to do this
(not talking about CMake options conflicts and pollution).
Enabled by setting WITH_SYSTEM_CERES=ON. Default paths to search
Ceres library:
- /usr/local
- /sw
- /opt/local
- /opt/csw
- /opt/lib/ceres
You might also specify Ceres root directory using CERES_ROOT_DIR
variable (both CMake and environment variables are supported).
If your Ceres is build statically, you're to control all additional
libraries needed to link against using CMAKE_EXE_LINKER_FLAGS.
commit c9156fbf80c86853806844b754b1e48f45c5ec11
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Feb 18 19:38:22 2014 +0600
Remove .orig file which was added by accident
commit 62597e3cf0f266a2fefec415c89759e502793e06
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Jan 2 16:02:08 2014 +0600
Upgrade glog to latest svn r139
The intention of this upgrade is to get rid of custom patches
we've been having to support compilation on different platforms
and compilers.
commit 2452d5d42b390c7ab853e6fe60e58bdd7a01a004
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Feb 18 18:46:08 2014 +0600
Tweak Ceres CMake to detect uninstall target properly on Windows
commit 98a281d58ce2301f3dd239a97a448e53f48d0258
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 14 00:36:44 2014 +0600
Fix order of third party libs compilation and options used by them
WITH_FAST_DETECTOR was defined too late and third_party folder
didn't see this option.
commit 4962bccd643ec0f2aed3035170d5f20e8f6efc85
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Feb 13 23:55:03 2014 +0600
Disable Ceres unit tests and examples by default
Actually we're to switch to external Ceres rather than
bundled one, would make life much easier actually.
commit b1381540305d69c702eb2f051bd543fb5c1c3e2c
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Feb 6 18:01:58 2014 +0600
@ -538,156 +670,3 @@ Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri May 10 13:27:21 2013 +0600
Left extra debugging print in reconstruction scale by accident.
commit 7971967d24e3d8d505bd6e54523161ab5dd5b728
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri May 10 12:23:03 2013 +0600
Add check for points behind camera in euclidan BA cost functor
In cases keyframes are no so good, algebraic two frames construction
could produce result, for which more aggressive Ceres-based BA code
will fall to a solution for which points goes behind the camera,
which is not so nice.
Seems in newer Ceres returning false from cost functor wouldn't
abort solution, but will restrict solver from moving points behind
the camera.
Works fine in own tests, but requires more tests.
commit f34e73f6bd0041a31f779a78e1c2324f9799a4a2
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Apr 24 22:06:38 2013 +0600
Forgot to add reconstruction scale to CMakeLists
commit de08cbaebe1b95673c4bc8f639aa0228414cf4a2
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Apr 24 19:40:39 2013 +0600
Reconstructed scene scale ambiguity improvement
Added a function EuclideanScaleToUnity() which is
aimed to solve scale ambiguity by scaling solution
in a way cameras centers variance in unity.
Currently only available for euclidean pipeline,
projective one is not finished anyway.
commit 30ecb7dd075527c0e49220744bae65ec208dbdf5
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Apr 23 01:41:29 2013 +0600
Use epsilon in modal solver test
Default epsilon for isApprox was too small,
leading to some false test failures.
commit d03b303c171b0b0a33ed0b31c9a744c9676492a9
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Apr 23 01:35:56 2013 +0600
Update Ceres to current HEAD
Brings optimization for DENSE_NORMAL_CHOLESKY and
also fixes threading issues with BLAS.
commit 0a352686de0e87d59a2e37dbd0fddb351cbea2b7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 15 05:35:33 2013 +0600
Fix for bundle adjusting with motion restricted
Was a bug introduced in previous commit, which
was trying to set parameterization for non-existing
camera->t parameter block.
Replaced with subset parameterization.
Also added basic synthetic unit test for modal solver.
commit 1742515b89ad5da53be95bfc574cbeffc51dc0e2
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 8 23:33:20 2013 +0600
Bundle adjustment improvements
- Get rid of rotation matrix parameterization,
use angle-axis instead.
Also Joined rotation and translation into
a single parameter block.
This made minimization go significantly faster,
like 1.3x times in average.
- Fix first camera when bundling. This is to
address orientation ambiguity.
Reconstruction result could still vary in
size, but that's another issue to be addressed
later.
Additional change:
Split EuclideanBundleCommonIntrinsics into
smaller functions, so it's now a bit easier
to follow.
commit 74bbeabf1c4570bfe04f3034afcde95134b3e161
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 8 23:31:57 2013 +0600
Update Ceres to current HEAD
Brings up some noticeable speed improvements. In particular
the automatic differentiation and bundle adjustment solvers.
commit e47519b0442527533ee046dd9881212d169561da
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 8 02:21:26 2013 +0600
Corrected path to gflags
Currently tools/track.cc is not used, but let's
keep things a bit more up-to-date :)
commit f617741b1f2a0ac7981dd71144eba187521d9ac4
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 8 02:17:16 2013 +0600
Re-enable tests for multiview and image
For as long code is in repo and used by some tools
better to have it covered by tests.
Some of them are failing tho, but that's completely
different story to be addressed later.
commit 7dbb5a37333fb6c5a729b8bafb317ea210735cbc
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 8 02:10:07 2013 +0600
Do not modify cache's CMAKE_CXX_FLAGS_RELEASE when configuring Ceres
Otherwise you'll have infinite appending of Ceres-specific flags
on every saving of any CmakeLists.txt.
commit b413d22280de2481a2e2acdcda8431f601d65448
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Sun Apr 7 21:53:23 2013 +0600
Fixed compilation with BUILD_TOOLS enabled
This commit mainly reverts parts of following commits:
0eebc21db831211738acc938566bbc29d68d45db
d8109b7a4fede1660e0dbd73735f1a9e3fd79eec
e59595806c045916ab4ef15ef7047c1a728b2da9
2d6cd58ee1cd7c5073980f358c71b2898ad16b4c
They declared lots of stuff deprecated, but in
fact it's not deprecated just a bit different
usage pipeline. Anyway, deprecation shall not
happen spontaneously as a part of other changes.
And for sure shall not break anything.

@ -26,7 +26,7 @@ if env['WITH_BF_LIBMV']:
src += env.Glob('libmv/tracking/*.cc')
src += env.Glob('third_party/gflags/*.cc')
incs += ' ../Eigen3 third_party/ceres/include ../../intern/guardedalloc'
incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include ../../intern/guardedalloc'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']

@ -132,6 +132,8 @@ if(WITH_LIBMV)
)
list(APPEND INC
third_party/gflags
third_party/glog/src
third_party/ceres/include
../../intern/guardedalloc
)
@ -195,10 +197,6 @@ ${third_glog_sources}
${third_glog_headers}
)
list(APPEND INC
third_party/glog/src
)
endif()
else()
list(APPEND SRC
@ -237,7 +235,7 @@ if env['WITH_BF_LIBMV']:
src = env.Glob("libmv-capi.cc")
$src
incs += ' ../Eigen3 third_party/ceres/include ../../intern/guardedalloc'
incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include ../../intern/guardedalloc'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']

@ -49,17 +49,17 @@
#endif
namespace google {
#if 1 // the C99 format
#if defined(__GNUC__) || defined(__MINGW32__) // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif 1 // the BSD format
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) // the BSD format
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif 0 // the windows (vc7) format
#elif defined(_MSC_VER) // the windows (vc7) format
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;

@ -1,3 +1,18 @@
2013-02-01 Google Inc. <opensource@google.com>
* google-glog: version 0.3.3
* Add --disable-rtti option for configure.
* Visual Studio build and test fix.
* QNX build fix (thanks vanuan).
* Reduce warnings.
* Fixed LOG_SYSRESULT (thanks ukai).
* FreeBSD build fix (thanks yyanagisawa).
* Clang build fix.
* Now users can re-initialize glog after ShutdownGoogleLogging.
* Color output support by GLOG_colorlogtostderr (thanks alexs).
* Now glog's ABI around flags are compatible with gflags.
* Document mentions how to modify flags from user programs.
2012-01-12 Google Inc. <opensource@google.com>
* google-glog: version 0.3.2

@ -1,25 +1,9 @@
Project: Google Logging
URL: http://code.google.com/p/google-glog/
License: New BSD
Upstream version: 0.3.2
Upstream version: 0.3.3, r139
Local modifications:
Upgrading Notes
* Replace <gflags/gflags.h> with "third_party/gflags/gflags/gflags.h" which is easier
to setup things in libmv and also helps with setting up building libmv into
external applications.
* Replace "glog/logging.h" and "glog/logging.h" with <glog/logging.h> and <glog/logging.h>
which is needed on Windows platform because otherwise files like logging.cc will be using
relative path which points to headers used by linux instead of headers need to be used
on Windows.
* Replace _asm int 3 with __debugbreak(). Such assembler code is obsolete and doesn't work
with 64bit versions of MSVC compilers.
* Do not use stacktrace for MinGW and FreeBSD because it leads into issues accessing
some specific data on this platforms.
* Define HAVE_LIB_GFLAGS for Windows builds.
* Do not define __declspec(dllimport) for MinGW platforms.
* Setup proper includes and datatypes for int32, uint32, int64 and uint64 for MinGW
* Do not define va_copy for MinGW platforms (it's already defined there).
* Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
of lack of needed functions.
* Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
* Added per-platform config.h files so no configuration-time
checks for functions and so are needed.
* See glog_tweaks.patch to see other tweaks which are done
against glog upstream.

@ -48,56 +48,57 @@
#ifndef BASE_COMMANDLINEFLAGS_H__
#define BASE_COMMANDLINEFLAGS_H__
#include "config.h"
#include "../config.h"
#include <string>
#include <string.h> // for memchr
#include <stdlib.h> // for getenv
#ifdef HAVE_LIB_GFLAGS
#include "third_party/gflags/gflags/gflags.h"
#include <gflags/gflags.h>
#else
#include <glog/logging.h>
#include "glog/logging.h"
#define DECLARE_VARIABLE(type, name, tn) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
#define DEFINE_VARIABLE(type, name, value, meaning, tn) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead { \
GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value); \
char FLAGS_no##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \
namespace fL##shorttype { \
GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value); \
char FLAGS_no##name; \
} \
using fL##shorttype::FLAGS_##name
// bool specialization
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, name, bool)
DECLARE_VARIABLE(bool, B, name, bool)
#define DEFINE_bool(name, value, meaning) \
DEFINE_VARIABLE(bool, name, value, meaning, bool)
DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
// int32 specialization
#define DECLARE_int32(name) \
DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, name, int32)
DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, int32)
#define DEFINE_int32(name, value, meaning) \
DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, name, value, meaning, int32)
DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, value, meaning, int32)
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \
extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
#define DEFINE_string(name, value, meaning) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \
GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name(value); \
char FLAGS_no##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
#define DECLARE_string(name) \
namespace fLS { \
extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#define DEFINE_string(name, value, meaning) \
namespace fLS { \
std::string FLAGS_##name##_buf(value); \
GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name = FLAGS_##name##_buf; \
char FLAGS_no##name; \
} \
using fLS::FLAGS_##name
#endif // HAVE_LIB_GFLAGS

@ -102,12 +102,14 @@
#ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_
#include "config.h" // to figure out pthreads support
#include "../config.h" // to figure out pthreads support
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
@ -117,9 +119,13 @@
# endif
# endif
// To avoid macro definition of ERROR.
# define NOGDI
# ifndef NOGDI
# define NOGDI
# endif
// To avoid macro definition of min/max.
# define NOMINMAX
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
typedef CRITICAL_SECTION MutexType;
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)

@ -46,12 +46,18 @@
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES 1
/* Define if you have the 'pread' function */
#define HAVE_PREAD 1
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define if you have the 'pwrite' function */
#define HAVE_PWRITE 1
/* define if the compiler implements pthread_rwlock_* */
#define HAVE_RWLOCK 1

@ -46,12 +46,18 @@
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES 1
/* Define if you have the 'pread' function */
#define HAVE_PREAD 1
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define if you have the 'pwrite' function */
#define HAVE_PWRITE 1
/* define if the compiler implements pthread_rwlock_* */
#define HAVE_RWLOCK 1

@ -46,12 +46,18 @@
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES 1
/* Define if you have the 'pread' function */
#define HAVE_PREAD 1
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define if you have the 'pwrite' function */
#define HAVE_PWRITE 1
/* define if the compiler implements pthread_rwlock_* */
#define HAVE_RWLOCK 1

@ -46,12 +46,18 @@
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES 1
/* Define if you have the 'pread' function */
#define HAVE_PREAD 1
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define if you have the 'pwrite' function */
#define HAVE_PWRITE 1
/* define if the compiler implements pthread_rwlock_* */
#define HAVE_RWLOCK 1

@ -33,24 +33,23 @@
// Pretty much everybody needs to #include this file so that they can
// log various happenings.
//
#ifdef WIN32
# include "windows/glog/logging.h"
#else // WIN32
#ifndef _LOGGING_H_
#define _LOGGING_H_
#include <errno.h>
#include <string.h>
#include <time.h>
#include <iosfwd>
#include <ostream>
#include <sstream>
#include <string>
#if 1
# include <unistd.h>
#endif
#ifdef __DEPRECATED
// Make GCC quiet.
# undef __DEPRECATED
# include <strstream>
# define __DEPRECATED
#else
# include <strstream>
#endif
#include <vector>
// Annoying stuff for windows -- makes sure clients can import these functions
@ -61,6 +60,14 @@
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
#if defined(_MSC_VER)
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
__pragma(warning(disable:n))
#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
#else
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
#define GLOG_MSVC_POP_WARNING()
#endif
// We care a lot about number of bits things take up. Unfortunately,
// systems define their bit-specific ints in a lot of different ways.
@ -79,7 +86,7 @@
#endif
#if 1
#include "third_party/gflags/gflags/gflags.h"
#include <gflags/gflags.h>
#endif
namespace google {
@ -126,8 +133,12 @@ typedef unsigned __int64 uint64;
#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
#if 1
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
#define GOOGLE_PREDICT_FALSE(x) x
#define GOOGLE_PREDICT_TRUE(x) x
#endif
#endif
@ -286,27 +297,27 @@ typedef unsigned __int64 uint64;
#ifndef DECLARE_VARIABLE
#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
#define DECLARE_VARIABLE(type, name, tn) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
// bool specialization
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, name, bool)
DECLARE_VARIABLE(bool, B, name, bool)
// int32 specialization
#define DECLARE_int32(name) \
DECLARE_VARIABLE(google::int32, name, int32)
DECLARE_VARIABLE(google::int32, I, name, int32)
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \
extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
#define DECLARE_string(name) \
namespace fLS { \
extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#endif
// Set whether log messages go to stderr instead of logfiles
@ -315,6 +326,9 @@ DECLARE_bool(logtostderr);
// Set whether log messages go to stderr in addition to logfiles.
DECLARE_bool(alsologtostderr);
// Set color messages logged to stderr (if supported by terminal).
DECLARE_bool(colorlogtostderr);
// Log messages at a level >= this flag are automatically sent to
// stderr in addition to log files.
DECLARE_int32(stderrthreshold);
@ -447,15 +461,16 @@ DECLARE_bool(stop_logging_if_full_disk);
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
// A very useful logging macro to log windows errors:
#define LOG_SYSRESULT(result) \
if (FAILED(result)) { \
LPTSTR message = NULL; \
LPTSTR msg = reinterpret_cast<LPTSTR>(&message); \
DWORD message_length = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
if (FAILED(HRESULT_FROM_WIN32(result))) { \
LPSTR message = NULL; \
LPSTR msg = reinterpret_cast<LPSTR>(&message); \
DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
FORMAT_MESSAGE_FROM_SYSTEM, \
0, result, 0, msg, 100, NULL); \
if (message_length > 0) { \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
&google::LogMessage::SendToLog).stream() << message; \
&google::LogMessage::SendToLog).stream() \
<< reinterpret_cast<const char*>(message); \
LocalFree(message); \
} \
}
@ -597,18 +612,68 @@ inline std::ostream& operator<<(
namespace google {
// Build the error message string.
template<class t1, class t2>
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
// It means that we cannot use stl_logging if compiler doesn't
// support using expression for operator.
// TODO(hamaji): Figure out a way to fix.
#if 1
using ::operator<<;
#endif
std::strstream ss;
ss << names << " (" << v1 << " vs. " << v2 << ")";
return new std::string(ss.str(), ss.pcount());
// This formats a value for a failing CHECK_XX statement. Ordinarily,
// it uses the definition for operator<<, with a few special cases below.
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
// Overrides for char types provide readable values for unprintable
// characters.
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const char& v);
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const signed char& v);
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
// Build the error message string. Specify no inlining for code size.
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
__attribute__ ((noinline));
namespace base {
namespace internal {
// If "s" is less than base_logging::INFO, returns base_logging::INFO.
// If "s" is greater than base_logging::FATAL, returns
// base_logging::ERROR. Otherwise, returns "s".
LogSeverity NormalizeSeverity(LogSeverity s);
} // namespace internal
// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
// statement. See MakeCheckOpString for sample usage. Other
// approaches were considered: use of a template method (e.g.,
// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
// base::Print<T2>, &v2), however this approach has complications
// related to volatile arguments and function-pointer arguments).
class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder {
public:
// Inserts "exprtext" and " (" to the stream.
explicit CheckOpMessageBuilder(const char *exprtext);
// Deletes "stream_".
~CheckOpMessageBuilder();
// For inserting the first variable.
std::ostream* ForVar1() { return stream_; }
// For inserting the second variable (adds an intermediate " vs. ").
std::ostream* ForVar2();
// Get the result (inserts the closing ")").
std::string* NewString();
private:
std::ostringstream *stream_;
};
} // namespace base
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
base::CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}
// Helper functions for CHECK_OP macro.
@ -616,26 +681,26 @@ std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <class t1, class t2> \
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (v1 op v2) return NULL; \
else return MakeCheckOpString(v1, v2, names); \
template <typename T1, typename T2> \
inline std::string* name##Impl(const T1& v1, const T2& v2, \
const char* exprtext) { \
if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
else return MakeCheckOpString(v1, v2, exprtext); \
} \
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
return Check##name##Impl<int, int>(v1, v2, names); \
inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
return name##Impl<int, int>(v1, v2, exprtext); \
}
// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h
// provides its own #defines for the simpler names EQ, NE, LE, etc.
// We use the full name Check_EQ, Check_NE, etc. in case the file including
// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
// This happens if, for example, those are used as token names in a
// yacc grammar.
DEFINE_CHECK_OP_IMPL(_EQ, ==)
DEFINE_CHECK_OP_IMPL(_NE, !=)
DEFINE_CHECK_OP_IMPL(_LE, <=)
DEFINE_CHECK_OP_IMPL(_LT, < )
DEFINE_CHECK_OP_IMPL(_GE, >=)
DEFINE_CHECK_OP_IMPL(_GT, > )
DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
DEFINE_CHECK_OP_IMPL(Check_LE, <=)
DEFINE_CHECK_OP_IMPL(Check_LT, < )
DEFINE_CHECK_OP_IMPL(Check_GE, >=)
DEFINE_CHECK_OP_IMPL(Check_GT, > )
#undef DEFINE_CHECK_OP_IMPL
// Helper macro for binary operators.
@ -940,52 +1005,65 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
#define DLOG_ASSERT(condition) \
true ? (void) 0 : LOG_ASSERT(condition)
// MSVC warning C4127: conditional expression is constant
#define DCHECK(condition) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK(condition)
GLOG_MSVC_POP_WARNING() CHECK(condition)
#define DCHECK_EQ(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_EQ(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_NE(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_LE(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_LT(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_GE(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_GT(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
// You may see warnings in release mode if you don't use the return
// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
#define DCHECK_NOTNULL(val) (val)
#define DCHECK_STREQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STREQ(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
#define DCHECK_STRCASEEQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STRCASEEQ(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
#define DCHECK_STRNE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STRNE(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
#define DCHECK_STRCASENE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STRCASENE(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
#endif // NDEBUG
@ -1002,6 +1080,29 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
namespace base_logging {
// LogMessage::LogStream is a std::ostream backed by this streambuf.
// This class ignores overflow and leaves two bytes at the end of the
// buffer to allow for a '\n' and '\0'.
class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf {
public:
// REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
LogStreamBuf(char *buf, int len) {
setp(buf, buf + len - 2);
}
// This effectively ignores overflow.
virtual int_type overflow(int_type ch) {
return ch;
}
// Legacy public ostrstream method.
size_t pcount() const { return pptr() - pbase(); }
char* pbase() const { return std::streambuf::pbase(); }
};
} // namespace base_logging
//
// This class more or less represents a particular log message. You
// create an instance of LogMessage and then stream stuff to it.
@ -1031,22 +1132,30 @@ public:
#ifdef _MSC_VER
# pragma warning(disable: 4275)
#endif
class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream {
class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
#ifdef _MSC_VER
# pragma warning(default: 4275)
#endif
public:
LogStream(char *buf, int len, int ctr_in)
: ostrstream(buf, len),
ctr_(ctr_in) {
self_ = this;
LogStream(char *buf, int len, int ctr)
: std::ostream(NULL),
streambuf_(buf, len),
ctr_(ctr),
self_(this) {
rdbuf(&streambuf_);
}
int ctr() const { return ctr_; }
void set_ctr(int ctr_in) { ctr_ = ctr_in; }
void set_ctr(int ctr) { ctr_ = ctr; }
LogStream* self() const { return self_; }
// Legacy std::streambuf methods.
size_t pcount() const { return streambuf_.pcount(); }
char* pbase() const { return streambuf_.pbase(); }
char* str() const { return pbase(); }
private:
base_logging::LogStreamBuf streambuf_;
int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
LogStream *self_; // Consistency check hack
};
@ -1115,13 +1224,15 @@ public:
// Call abort() or similar to perform LOG(FATAL) crash.
static void Fail() __attribute__ ((noreturn));
std::ostream& stream() { return *(data_->stream_); }
std::ostream& stream();
int preserved_errno() const { return data_->preserved_errno_; }
int preserved_errno() const;
// Must be called without the log_mutex held. (L < log_mutex)
static int64 num_messages(int severity);
struct LogMessageData;
private:
// Fully internal SendMethod cases:
void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs
@ -1143,41 +1254,6 @@ private:
// We keep the data in a separate struct so that each instance of
// LogMessage uses less stack space.
struct GOOGLE_GLOG_DLL_DECL LogMessageData {
LogMessageData() {};
int preserved_errno_; // preserved errno
char* buf_;
char* message_text_; // Complete message text (points to selected buffer)
LogStream* stream_alloc_;
LogStream* stream_;
char severity_; // What level is this LogMessage logged at?
int line_; // line number where logging call is.
void (LogMessage::*send_method_)(); // Call this in destructor to send
union { // At most one of these is used: union to keep the size low.
LogSink* sink_; // NULL or sink to send message to
std::vector<std::string>* outvec_; // NULL or vector to push message onto
std::string* message_; // NULL or string to write message into
};
time_t timestamp_; // Time of creation of LogMessage
struct ::tm tm_time_; // Time of creation of LogMessage
size_t num_prefix_chars_; // # of chars of prefix in this message
size_t num_chars_to_log_; // # of chars of msg to send to log
size_t num_chars_to_syslog_; // # of chars of msg to send to syslog
const char* basename_; // basename of file that called LOG
const char* fullname_; // fullname of file that called LOG
bool has_been_flushed_; // false => data has not been flushed
bool first_fatal_; // true => this was first fatal msg
~LogMessageData();
private:
LogMessageData(const LogMessageData&);
void operator=(const LogMessageData&);
};
static LogMessageData fatal_msg_data_exclusive_;
static LogMessageData fatal_msg_data_shared_;
LogMessageData* allocated_;
LogMessageData* data_;
@ -1456,8 +1532,12 @@ extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
// be set to an empty string, if this function failed. This means, in most
// cases, you do not need to check the error code and you can directly
// use the value of "buf". It will never have an undefined value.
// DEPRECATED: Use StrError(int) instead.
GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len);
// A thread-safe replacement for strerror(). Returns a string describing the
// given POSIX error code.
GOOGLE_GLOG_DLL_DECL std::string StrError(int err);
// A class for which we define operator<<, which does nothing.
class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
@ -1525,3 +1605,5 @@ GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
}
#endif // _LOGGING_H_
#endif // WIN32

@ -33,6 +33,10 @@
// acquire any locks, and can therefore be used by low-level memory
// allocation and synchronization code.
#ifdef WIN32
# include "windows/glog/raw_logging.h"
#else // WIN32
#ifndef BASE_RAW_LOGGING_H_
#define BASE_RAW_LOGGING_H_
@ -183,3 +187,5 @@ GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs);
}
#endif // BASE_RAW_LOGGING_H_
#endif // WIN32

@ -34,7 +34,6 @@
#include <assert.h>
#include <iomanip>
#include <string>
#include <algorithm>
#ifdef HAVE_UNISTD_H
# include <unistd.h> // For _exit.
#endif
@ -59,8 +58,8 @@
#include <errno.h> // for errno
#include <sstream>
#include "base/commandlineflags.h" // to get the program name
#include <glog/logging.h>
#include <glog/raw_logging.h>
#include "glog/logging.h"
#include "glog/raw_logging.h"
#include "base/googleinit.h"
#ifdef HAVE_STACKTRACE
@ -69,7 +68,6 @@
using std::string;
using std::vector;
using std::ostrstream;
using std::setw;
using std::setfill;
using std::hex;
@ -77,7 +75,17 @@ using std::dec;
using std::min;
using std::ostream;
using std::ostringstream;
using std::strstream;
using std::FILE;
using std::fwrite;
using std::fclose;
using std::fflush;
using std::fprintf;
using std::perror;
#ifdef __QNX__
using std::fdopen;
#endif
// There is no thread annotation support.
#define EXCLUSIVE_LOCKS_REQUIRED(mu)
@ -94,6 +102,8 @@ GLOG_DEFINE_bool(logtostderr, BoolFromEnv("GOOGLE_LOGTOSTDERR", false),
"log messages go to stderr instead of logfiles");
GLOG_DEFINE_bool(alsologtostderr, BoolFromEnv("GOOGLE_ALSOLOGTOSTDERR", false),
"log messages go to stderr in addition to logfiles");
GLOG_DEFINE_bool(colorlogtostderr, false,
"color messages logged to stderr (if supported by terminal)");
#ifdef OS_LINUX
GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. "
"Logs can grow very quickly and they are rarely read before they "
@ -169,6 +179,38 @@ GLOG_DEFINE_string(log_backtrace_at, "",
// TODO(hamaji): consider windows
#define PATH_SEPARATOR '/'
#ifndef HAVE_PREAD
static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1)
return -1;
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
return -1;
ssize_t len = read(fd, buf, count);
if (len < 0)
return len;
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
return -1;
return len;
}
#endif // !HAVE_PREAD
#ifndef HAVE_PWRITE
static ssize_t pwrite(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1)
return -1;
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
return -1;
ssize_t len = write(fd, buf, count);
if (len < 0)
return len;
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
return -1;
return len;
}
#endif // !HAVE_PWRITE
static void GetHostName(string* hostname) {
#if defined(HAVE_SYS_UTSNAME_H)
struct utsname buf;
@ -191,13 +233,125 @@ static void GetHostName(string* hostname) {
#endif
}
// Returns true iff terminal supports using colors in output.
static bool TerminalSupportsColor() {
bool term_supports_color = false;
#ifdef OS_WINDOWS
// on Windows TERM variable is usually not set, but the console does
// support colors.
term_supports_color = true;
#else
// On non-Windows platforms, we rely on the TERM variable.
const char* const term = getenv("TERM");
if (term != NULL && term[0] != '\0') {
term_supports_color =
!strcmp(term, "xterm") ||
!strcmp(term, "xterm-color") ||
!strcmp(term, "xterm-256color") ||
!strcmp(term, "screen") ||
!strcmp(term, "linux") ||
!strcmp(term, "cygwin");
}
#endif
return term_supports_color;
}
_START_GOOGLE_NAMESPACE_
enum GLogColor {
COLOR_DEFAULT,
COLOR_RED,
COLOR_GREEN,
COLOR_YELLOW
};
static GLogColor SeverityToColor(LogSeverity severity) {
assert(severity >= 0 && severity < NUM_SEVERITIES);
GLogColor color = COLOR_DEFAULT;
switch (severity) {
case GLOG_INFO:
color = COLOR_DEFAULT;
break;
case GLOG_WARNING:
color = COLOR_YELLOW;
break;
case GLOG_ERROR:
case GLOG_FATAL:
color = COLOR_RED;
break;
default:
// should never get here.
assert(false);
}
return color;
}
#ifdef OS_WINDOWS
// Returns the character attribute for the given color.
WORD GetColorAttribute(GLogColor color) {
switch (color) {
case COLOR_RED: return FOREGROUND_RED;
case COLOR_GREEN: return FOREGROUND_GREEN;
case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
default: return 0;
}
}
#else
// Returns the ANSI color code for the given color.
static const char* GetAnsiColorCode(GLogColor color) {
switch (color) {
case COLOR_RED: return "1";
case COLOR_GREEN: return "2";
case COLOR_YELLOW: return "3";
case COLOR_DEFAULT: return "";
};
return NULL; // stop warning about return type.
}
#endif // OS_WINDOWS
// Safely get max_log_size, overriding to 1 if it somehow gets defined as 0
static int32 MaxLogSize() {
return (FLAGS_max_log_size > 0 ? FLAGS_max_log_size : 1);
}
// An arbitrary limit on the length of a single log message. This
// is so that streaming can be done more efficiently.
const size_t LogMessage::kMaxLogMessageLen = 30000;
struct LogMessage::LogMessageData {
LogMessageData();
int preserved_errno_; // preserved errno
// Buffer space; contains complete message text.
char message_text_[LogMessage::kMaxLogMessageLen+1];
LogStream stream_;
char severity_; // What level is this LogMessage logged at?
int line_; // line number where logging call is.
void (LogMessage::*send_method_)(); // Call this in destructor to send
union { // At most one of these is used: union to keep the size low.
LogSink* sink_; // NULL or sink to send message to
std::vector<std::string>* outvec_; // NULL or vector to push message onto
std::string* message_; // NULL or string to write message into
};
time_t timestamp_; // Time of creation of LogMessage
struct ::tm tm_time_; // Time of creation of LogMessage
size_t num_prefix_chars_; // # of chars of prefix in this message
size_t num_chars_to_log_; // # of chars of msg to send to log
size_t num_chars_to_syslog_; // # of chars of msg to send to syslog
const char* basename_; // basename of file that called LOG
const char* fullname_; // fullname of file that called LOG
bool has_been_flushed_; // false => data has not been flushed
bool first_fatal_; // true => this was first fatal msg
private:
LogMessageData(const LogMessageData&);
void operator=(const LogMessageData&);
};
// A mutex that allows only one thread to log at a time, to keep things from
// getting jumbled. Some other very uncommon logging operations (like
// changing the destination file for log messages of a given severity) also
@ -279,7 +433,7 @@ class LogFileObject : public base::Logger {
// Actually create a logfile using the value of base_filename_ and the
// supplied argument time_pid_string
// REQUIRES: lock_ is held
bool CreateLogfile(const char* time_pid_string);
bool CreateLogfile(const string& time_pid_string);
};
} // namespace
@ -312,6 +466,9 @@ class LogDestination {
static const int kNetworkBytes = 1400;
static const string& hostname();
static const bool& terminal_supports_color() {
return terminal_supports_color_;
}
static void DeleteLogDestinations();
@ -362,6 +519,7 @@ class LogDestination {
static LogSeverity email_logging_severity_;
static string addresses_;
static string hostname_;
static bool terminal_supports_color_;
// arbitrary global logging destinations.
static vector<LogSink*>* sinks_;
@ -383,6 +541,7 @@ string LogDestination::hostname_;
vector<LogSink*>* LogDestination::sinks_ = NULL;
Mutex LogDestination::sink_mutex_;
bool LogDestination::terminal_supports_color_ = TerminalSupportsColor();
/* static */
const string& LogDestination::hostname() {
@ -503,6 +662,43 @@ inline void LogDestination::SetEmailLogging(LogSeverity min_severity,
LogDestination::addresses_ = addresses;
}
static void ColoredWriteToStderr(LogSeverity severity,
const char* message, size_t len) {
const GLogColor color =
(LogDestination::terminal_supports_color() && FLAGS_colorlogtostderr) ?
SeverityToColor(severity) : COLOR_DEFAULT;
// Avoid using cerr from this module since we may get called during
// exit code, and cerr may be partially or fully destroyed by then.
if (COLOR_DEFAULT == color) {
fwrite(message, len, 1, stderr);
return;
}
#ifdef OS_WINDOWS
const HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
// Gets the current text color.
CONSOLE_SCREEN_BUFFER_INFO buffer_info;
GetConsoleScreenBufferInfo(stderr_handle, &buffer_info);
const WORD old_color_attrs = buffer_info.wAttributes;
// We need to flush the stream buffers into the console before each
// SetConsoleTextAttribute call lest it affect the text that is already
// printed but has not yet reached the console.
fflush(stderr);
SetConsoleTextAttribute(stderr_handle,
GetColorAttribute(color) | FOREGROUND_INTENSITY);
fwrite(message, len, 1, stderr);
fflush(stderr);
// Restores the text color.
SetConsoleTextAttribute(stderr_handle, old_color_attrs);
#else
fprintf(stderr, "\033[0;3%sm", GetAnsiColorCode(color));
fwrite(message, len, 1, stderr);
fprintf(stderr, "\033[m"); // Resets the terminal to default.
#endif // OS_WINDOWS
}
static void WriteToStderr(const char* message, size_t len) {
// Avoid using cerr from this module since we may get called during
// exit code, and cerr may be partially or fully destroyed by then.
@ -512,7 +708,7 @@ static void WriteToStderr(const char* message, size_t len) {
inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
const char* message, size_t len) {
if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
WriteToStderr(message, len);
ColoredWriteToStderr(severity, message, len);
#ifdef OS_WINDOWS
// On Windows, also output to the debugger
::OutputDebugStringA(string(message,len).c_str());
@ -561,12 +757,12 @@ inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
const char* message,
size_t len) {
if ( FLAGS_logtostderr ) // global flag: never log to file
WriteToStderr(message, len);
else
if ( FLAGS_logtostderr ) { // global flag: never log to file
ColoredWriteToStderr(severity, message, len);
} else {
for (int i = severity; i >= 0; --i)
LogDestination::MaybeLogToLogfile(i, timestamp, message, len);
}
}
inline void LogDestination::LogToSinks(LogSeverity severity,
@ -691,7 +887,7 @@ void LogFileObject::FlushUnlocked(){
next_flush_time_ = CycleClock_Now() + UsecToCycles(next);
}
bool LogFileObject::CreateLogfile(const char* time_pid_string) {
bool LogFileObject::CreateLogfile(const string& time_pid_string) {
string string_filename = base_filename_+filename_extension_+
time_pid_string;
const char* filename = string_filename.c_str();
@ -724,8 +920,10 @@ bool LogFileObject::CreateLogfile(const char* time_pid_string) {
linkpath += linkname;
unlink(linkpath.c_str()); // delete old one if it exists
#if defined(OS_WINDOWS)
// TODO(hamaji): Create lnk file on Windows?
#elif defined(HAVE_UNISTD_H)
// We must have unistd.h.
#ifdef HAVE_UNISTD_H
// Make the symlink be relative (in the same dir) so that if the
// entire log directory gets relocated the link is still valid.
const char *linkdest = slash ? (slash + 1) : filename;
@ -779,24 +977,24 @@ void LogFileObject::Write(bool force_flush,
localtime_r(&timestamp, &tm_time);
// The logfile's filename will have the date/time & pid in it
char time_pid_string[256]; // More than enough chars for time, pid, \0
ostrstream time_pid_stream(time_pid_string, sizeof(time_pid_string));
ostringstream time_pid_stream;
time_pid_stream.fill('0');
time_pid_stream << 1900+tm_time.tm_year
<< setw(2) << 1+tm_time.tm_mon
<< setw(2) << tm_time.tm_mday
<< '-'
<< setw(2) << tm_time.tm_hour
<< setw(2) << tm_time.tm_min
<< setw(2) << tm_time.tm_sec
<< '.'
<< GetMainThreadPid()
<< '\0';
<< setw(2) << 1+tm_time.tm_mon
<< setw(2) << tm_time.tm_mday
<< '-'
<< setw(2) << tm_time.tm_hour
<< setw(2) << tm_time.tm_min
<< setw(2) << tm_time.tm_sec
<< '.'
<< GetMainThreadPid();
const string& time_pid_string = time_pid_stream.str();
if (base_filename_selected_) {
if (!CreateLogfile(time_pid_string)) {
perror("Could not create log file");
fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n", time_pid_string);
fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n",
time_pid_string.c_str());
return;
}
} else {
@ -844,15 +1042,14 @@ void LogFileObject::Write(bool force_flush,
// If we never succeeded, we have to give up
if ( success == false ) {
perror("Could not create logging file");
fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!", time_pid_string);
fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!",
time_pid_string.c_str());
return;
}
}
// Write a header message into the log file
char file_header_string[512]; // Enough chars for time and binary info
ostrstream file_header_stream(file_header_string,
sizeof(file_header_string));
ostringstream file_header_stream;
file_header_stream.fill('0');
file_header_stream << "Log file created at: "
<< 1900+tm_time.tm_year << '/'
@ -865,10 +1062,11 @@ void LogFileObject::Write(bool force_flush,
<< "Running on machine: "
<< LogDestination::hostname() << '\n'
<< "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
<< "threadid file:line] msg" << '\n'
<< '\0';
int header_len = strlen(file_header_string);
fwrite(file_header_string, 1, header_len, file_);
<< "threadid file:line] msg" << '\n';
const string& file_header_string = file_header_stream.str();
const int header_len = file_header_string.size();
fwrite(file_header_string.data(), 1, header_len, file_);
file_length_ += header_len;
bytes_since_flush_ += header_len;
}
@ -916,9 +1114,6 @@ void LogFileObject::Write(bool force_flush,
} // namespace
// An arbitrary limit on the length of a single log message. This
// is so that streaming can be done more efficiently.
const size_t LogMessage::kMaxLogMessageLen = 30000;
// Static log data space to avoid alloc failures in a LOG(FATAL)
//
@ -929,55 +1124,55 @@ const size_t LogMessage::kMaxLogMessageLen = 30000;
static Mutex fatal_msg_lock;
static CrashReason crash_reason;
static bool fatal_msg_exclusive = true;
static char fatal_msg_buf_exclusive[LogMessage::kMaxLogMessageLen+1];
static char fatal_msg_buf_shared[LogMessage::kMaxLogMessageLen+1];
static LogMessage::LogStream fatal_msg_stream_exclusive(
fatal_msg_buf_exclusive, LogMessage::kMaxLogMessageLen, 0);
static LogMessage::LogStream fatal_msg_stream_shared(
fatal_msg_buf_shared, LogMessage::kMaxLogMessageLen, 0);
LogMessage::LogMessageData LogMessage::fatal_msg_data_exclusive_;
LogMessage::LogMessageData LogMessage::fatal_msg_data_shared_;
static LogMessage::LogMessageData fatal_msg_data_exclusive;
static LogMessage::LogMessageData fatal_msg_data_shared;
LogMessage::LogMessageData::~LogMessageData() {
delete[] buf_;
delete stream_alloc_;
LogMessage::LogMessageData::LogMessageData()
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
int ctr, void (LogMessage::*send_method)()) {
int ctr, void (LogMessage::*send_method)())
: allocated_(NULL) {
Init(file, line, severity, send_method);
data_->stream_->set_ctr(ctr);
data_->stream_.set_ctr(ctr);
}
LogMessage::LogMessage(const char* file, int line,
const CheckOpString& result) {
const CheckOpString& result)
: allocated_(NULL) {
Init(file, line, GLOG_FATAL, &LogMessage::SendToLog);
stream() << "Check failed: " << (*result.str_) << " ";
}
LogMessage::LogMessage(const char* file, int line) {
LogMessage::LogMessage(const char* file, int line)
: allocated_(NULL) {
Init(file, line, GLOG_INFO, &LogMessage::SendToLog);
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity) {
LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
: allocated_(NULL) {
Init(file, line, severity, &LogMessage::SendToLog);
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
LogSink* sink, bool also_send_to_log) {
LogSink* sink, bool also_send_to_log)
: allocated_(NULL) {
Init(file, line, severity, also_send_to_log ? &LogMessage::SendToSinkAndLog :
&LogMessage::SendToSink);
data_->sink_ = sink; // override Init()'s setting to NULL
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
vector<string> *outvec) {
vector<string> *outvec)
: allocated_(NULL) {
Init(file, line, severity, &LogMessage::SaveOrSendToLog);
data_->outvec_ = outvec; // override Init()'s setting to NULL
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
string *message) {
string *message)
: allocated_(NULL) {
Init(file, line, severity, &LogMessage::WriteToStringAndLog);
data_->message_ = message; // override Init()'s setting to NULL
}
@ -990,27 +1185,17 @@ void LogMessage::Init(const char* file,
if (severity != GLOG_FATAL || !exit_on_dfatal) {
allocated_ = new LogMessageData();
data_ = allocated_;
data_->buf_ = new char[kMaxLogMessageLen+1];
data_->message_text_ = data_->buf_;
data_->stream_alloc_ =
new LogStream(data_->message_text_, kMaxLogMessageLen, 0);
data_->stream_ = data_->stream_alloc_;
data_->first_fatal_ = false;
} else {
MutexLock l(&fatal_msg_lock);
if (fatal_msg_exclusive) {
fatal_msg_exclusive = false;
data_ = &fatal_msg_data_exclusive_;
data_->message_text_ = fatal_msg_buf_exclusive;
data_->stream_ = &fatal_msg_stream_exclusive;
data_ = &fatal_msg_data_exclusive;
data_->first_fatal_ = true;
} else {
data_ = &fatal_msg_data_shared_;
data_->message_text_ = fatal_msg_buf_shared;
data_->stream_ = &fatal_msg_stream_shared;
data_ = &fatal_msg_data_shared;
data_->first_fatal_ = false;
}
data_->stream_alloc_ = NULL;
}
stream().fill('0');
@ -1051,7 +1236,7 @@ void LogMessage::Init(const char* file,
<< ' '
<< data_->basename_ << ':' << data_->line_ << "] ";
}
data_->num_prefix_chars_ = data_->stream_->pcount();
data_->num_prefix_chars_ = data_->stream_.pcount();
if (!FLAGS_log_backtrace_at.empty()) {
char fileline[128];
@ -1071,13 +1256,21 @@ LogMessage::~LogMessage() {
delete allocated_;
}
int LogMessage::preserved_errno() const {
return data_->preserved_errno_;
}
ostream& LogMessage::stream() {
return data_->stream_;
}
// Flush buffered message, called by the destructor, or any other function
// that needs to synchronize the log.
void LogMessage::Flush() {
if (data_->has_been_flushed_ || data_->severity_ < FLAGS_minloglevel)
return;
data_->num_chars_to_log_ = data_->stream_->pcount();
data_->num_chars_to_log_ = data_->stream_.pcount();
data_->num_chars_to_syslog_ =
data_->num_chars_to_log_ - data_->num_prefix_chars_;
@ -1127,7 +1320,7 @@ void LogMessage::Flush() {
// Copy of first FATAL log message so that we can print it out again
// after all the stack traces. To preserve legacy behavior, we don't
// use fatal_msg_buf_exclusive.
// use fatal_msg_data_exclusive.
static time_t fatal_time;
static char fatal_message[256];
@ -1135,7 +1328,7 @@ void ReprintFatalMessage() {
if (fatal_message[0]) {
const int n = strlen(fatal_message);
if (!FLAGS_logtostderr) {
// Also write to stderr
// Also write to stderr (don't color to avoid terminal checks)
WriteToStderr(fatal_message, n);
}
LogDestination::LogToAllLogfiles(GLOG_ERROR, fatal_time, fatal_message, n);
@ -1164,7 +1357,8 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
// file if we haven't parsed the command line flags to get the
// program name.
if (FLAGS_logtostderr || !IsGoogleLoggingInitialized()) {
WriteToStderr(data_->message_text_, data_->num_chars_to_log_);
ColoredWriteToStderr(data_->severity_,
data_->message_text_, data_->num_chars_to_log_);
// this could be protected by a flag if necessary.
LogDestination::LogToSinks(data_->severity_,
@ -1236,10 +1430,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
void LogMessage::RecordCrashReason(
glog_internal_namespace_::CrashReason* reason) {
reason->filename = fatal_msg_data_exclusive_.fullname_;
reason->line_number = fatal_msg_data_exclusive_.line_;
reason->message = fatal_msg_buf_exclusive +
fatal_msg_data_exclusive_.num_prefix_chars_;
reason->filename = fatal_msg_data_exclusive.fullname_;
reason->line_number = fatal_msg_data_exclusive.line_;
reason->message = fatal_msg_data_exclusive.message_text_ +
fatal_msg_data_exclusive.num_prefix_chars_;
#ifdef HAVE_STACKTRACE
// Retrieve the stack trace, omitting the logging frames that got us here.
reason->depth = GetStackTrace(reason->stack, ARRAYSIZE(reason->stack), 4);
@ -1366,8 +1560,13 @@ int64 LogMessage::num_messages(int severity) {
// Output the COUNTER value. This is only valid if ostream is a
// LogStream.
ostream& operator<<(ostream &os, const PRIVATE_Counter&) {
#ifdef DISABLE_RTTI
LogMessage::LogStream *log = static_cast<LogMessage::LogStream*>(&os);
#else
LogMessage::LogStream *log = dynamic_cast<LogMessage::LogStream*>(&os);
CHECK(log == log->self());
#endif
CHECK(log && log == log->self())
<< "You must not use COUNTER with non-glog ostream";
os << log->ctr();
return os;
}
@ -1381,9 +1580,8 @@ ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
ErrnoLogMessage::~ErrnoLogMessage() {
// Don't access errno directly because it may have been altered
// while streaming the message.
char buf[100];
posix_strerror_r(preserved_errno(), buf, sizeof(buf));
stream() << ": " << buf << " [" << preserved_errno() << "]";
stream() << ": " << StrError(preserved_errno()) << " ["
<< preserved_errno() << "]";
}
void FlushLogFiles(LogSeverity min_severity) {
@ -1465,9 +1663,7 @@ void LogToStderr() {
namespace base {
namespace internal {
/* Put prototypes here to suppress strict compiler warnings */
bool GetExitOnDFatal();
void SetExitOnDFatal(bool value);
namespace {
bool GetExitOnDFatal() {
MutexLock l(&log_mutex);
@ -1489,6 +1685,8 @@ void SetExitOnDFatal(bool value) {
exit_on_dfatal = value;
}
} // namespace
} // namespace internal
} // namespace base
@ -1516,13 +1714,11 @@ static bool SendEmailInternal(const char*dest, const char *subject,
bool ok = pclose(pipe) != -1;
if ( !ok ) {
if ( use_logging ) {
char buf[100];
posix_strerror_r(errno, buf, sizeof(buf));
LOG(ERROR) << "Problems sending mail to " << dest << ": " << buf;
LOG(ERROR) << "Problems sending mail to " << dest << ": "
<< StrError(errno);
} else {
char buf[100];
posix_strerror_r(errno, buf, sizeof(buf));
fprintf(stderr, "Problems sending mail to %s: %s\n", dest, buf);
fprintf(stderr, "Problems sending mail to %s: %s\n",
dest, StrError(errno).c_str());
}
}
return ok;
@ -1644,8 +1840,11 @@ void TruncateLogFile(const char *path, int64 limit, int64 keep) {
int64 read_offset, write_offset;
// Don't follow symlinks unless they're our own fd symlinks in /proc
int flags = O_RDWR;
// TODO(hamaji): Support other environments.
#ifdef OS_LINUX
const char *procfd_prefix = "/proc/self/fd/";
if (strncmp(procfd_prefix, path, strlen(procfd_prefix))) flags |= O_NOFOLLOW;
#endif
int fd = open(path, flags);
if (fd == -1) {
@ -1730,11 +1929,11 @@ void TruncateStdoutStderr() {
bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
if (equal == expected) return NULL; \
else { \
strstream ss; \
ostringstream ss; \
if (!s1) s1 = ""; \
if (!s2) s2 = ""; \
ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
return new string(ss.str(), ss.pcount()); \
return new string(ss.str()); \
} \
}
DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
@ -1793,6 +1992,15 @@ int posix_strerror_r(int err, char *buf, size_t len) {
}
}
string StrError(int err) {
char buf[100];
int rc = posix_strerror_r(err, buf, sizeof(buf));
if ((rc < 0) || (buf[0] == '\000')) {
snprintf(buf, sizeof(buf), "Error number %d", err);
}
return buf;
}
LogMessageFatal::LogMessageFatal(const char* file, int line) :
LogMessage(file, line, GLOG_FATAL) {}
@ -1805,6 +2013,56 @@ LogMessageFatal::~LogMessageFatal() {
LogMessage::Fail();
}
namespace base {
CheckOpMessageBuilder::CheckOpMessageBuilder(const char *exprtext)
: stream_(new ostringstream) {
*stream_ << exprtext << " (";
}
CheckOpMessageBuilder::~CheckOpMessageBuilder() {
delete stream_;
}
ostream* CheckOpMessageBuilder::ForVar2() {
*stream_ << " vs. ";
return stream_;
}
string* CheckOpMessageBuilder::NewString() {
*stream_ << ")";
return new string(stream_->str());
}
} // namespace base
template <>
void MakeCheckOpValueString(std::ostream* os, const char& v) {
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
(*os) << "char value " << (short)v;
}
}
template <>
void MakeCheckOpValueString(std::ostream* os, const signed char& v) {
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
(*os) << "signed char value " << (short)v;
}
}
template <>
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v) {
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
(*os) << "unsigned char value " << (unsigned short)v;
}
}
void InitGoogleLogging(const char* argv0) {
glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
}

@ -42,8 +42,8 @@
#include <fcntl.h> // for open()
#include <time.h>
#include "config.h"
#include <glog/logging.h> // To pick up flag settings etc.
#include <glog/raw_logging.h>
#include "glog/logging.h" // To pick up flag settings etc.
#include "glog/raw_logging.h"
#include "base/commandlineflags.h"
#ifdef HAVE_STACKTRACE

@ -34,7 +34,7 @@
#include "utilities.h"
#include "stacktrace.h"
#include "symbolize.h"
#include <glog/logging.h>
#include "glog/logging.h"
#include <signal.h>
#include <time.h>
@ -48,6 +48,9 @@
_START_GOOGLE_NAMESPACE_
// TOOD(hamaji): Use signal instead of sigaction?
#ifdef HAVE_SIGACTION
namespace {
// We'll install the failure signal handler for these signals. We could
@ -330,7 +333,10 @@ void FailureSignalHandler(int signal_number,
} // namespace
#endif // HAVE_SIGACTION
void InstallFailureSignalHandler() {
#ifdef HAVE_SIGACTION
// Build the sigaction struct.
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
@ -341,10 +347,13 @@ void InstallFailureSignalHandler() {
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
}
#endif // HAVE_SIGACTION
}
void InstallFailureWriter(void (*writer)(const char* data, int size)) {
#ifdef HAVE_SIGACTION
g_failure_writer = writer;
#endif // HAVE_SIGACTION
}
_END_GOOGLE_NAMESPACE_

@ -37,7 +37,7 @@ extern "C" {
#define UNW_LOCAL_ONLY
#include <libunwind.h>
}
#include <glog/raw_logging.h>
#include "glog/raw_logging.h"
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_

@ -111,7 +111,7 @@ _END_GOOGLE_NAMESPACE_
#include "symbolize.h"
#include "config.h"
#include <glog/raw_logging.h>
#include "glog/raw_logging.h"
// Re-runs fn until it doesn't cause EINTR.
#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
@ -232,7 +232,7 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
}
char header_name[kMaxSectionNameLen];
if (sizeof(header_name) < name_len) {
RAW_LOG(WARNING, "Section name '%s' is too long (%"PRIuS"); "
RAW_LOG(WARNING, "Section name '%s' is too long (%" PRIuS "); "
"section will not be found (even if present).", name, name_len);
// No point in even trying.
return false;

@ -56,7 +56,7 @@
#include "utilities.h"
#include "config.h"
#include <glog/logging.h>
#include "glog/logging.h"
#ifdef HAVE_SYMBOLIZE

@ -136,6 +136,8 @@ static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg) {
static void DumpStackTraceAndExit() {
DumpStackTrace(1, DebugWriteToStderr, NULL);
// TOOD(hamaji): Use signal instead of sigaction?
#ifdef HAVE_SIGACTION
// Set the default signal handler for SIGABRT, to avoid invoking our
// own signal handler installed by InstallFailedSignalHandler().
struct sigaction sig_action;
@ -143,6 +145,7 @@ static void DumpStackTraceAndExit() {
sigemptyset(&sig_action.sa_mask);
sig_action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sig_action, NULL);
#endif // HAVE_SIGACTION
abort();
}
@ -233,7 +236,7 @@ bool PidHasChanged() {
}
pid_t GetTID() {
// On Linux and MACOSX , we try to use gettid().
// On Linux and MacOSX, we try to use gettid().
#if defined OS_LINUX || defined OS_MACOSX
#ifndef __NR_gettid
#ifdef OS_MACOSX
@ -331,6 +334,7 @@ void InitGoogleLoggingUtilities(const char* argv0) {
void ShutdownGoogleLoggingUtilities() {
CHECK(IsGoogleLoggingInitialized())
<< "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
g_program_invocation_short_name = NULL;
#ifdef HAVE_SYSLOG_H
closelog();
#endif

@ -79,7 +79,7 @@
#endif
#include "config.h"
#include <glog/logging.h>
#include "glog/logging.h"
// There are three different ways we can try to get the stack trace:
//
@ -108,7 +108,7 @@
#elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
# elif defined(__x86_64__) && __GNUC__ >= 2
# elif defined(__x86_64__) && __GNUC__ >= 2 && HAVE_UNWIND_H
# define STACKTRACE_H "stacktrace_x86_64-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"

@ -40,8 +40,8 @@
#include <cstdio>
#include <string>
#include "base/commandlineflags.h"
#include <glog/logging.h>
#include <glog/raw_logging.h>
#include "glog/logging.h"
#include "glog/raw_logging.h"
#include "base/googleinit.h"
// glog doesn't have annotation
@ -62,11 +62,7 @@ _START_GOOGLE_NAMESPACE_
namespace glog_internal_namespace_ {
// Put protytype here to suppress strict compiler flags
GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
size_t patt_len,
const char* str,
size_t str_len);
namespace {
// Implementation of fnmatch that does not need 0-termination
// of arguments and does not allocate any memory,
@ -101,6 +97,8 @@ GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
}
}
} // namespace
} // namespace glog_internal_namespace_
using glog_internal_namespace_::SafeFNMatch_;

@ -1,122 +1,10 @@
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Namespace for Google classes */
#define GOOGLE_NAMESPACE google
/* Define if you have the `dladdr' function */
#undef HAVE_DLADDR
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <execinfo.h> header file. */
#undef HAVE_EXECINFO_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <libunwind.h> header file. */
#undef HAVE_LIBUNWIND_H
/* define if you have google gflags library */
#define HAVE_LIB_GFLAGS 1
/* define if you have libunwind */
#undef HAVE_LIB_UNWIND
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* define if the compiler implements namespaces */
#undef HAVE_NAMESPACES
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* define if the compiler implements pthread_rwlock_* */
#undef HAVE_RWLOCK
/* Define if you have the `sigaltstack' function */
#undef HAVE_SIGALTSTACK
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <syscall.h> header file. */
#undef HAVE_SYSCALL_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/syscall.h> header file. */
#undef HAVE_SYS_SYSCALL_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <ucontext.h> header file. */
#undef HAVE_UCONTEXT_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* define if the compiler supports using expression for operator */
#undef HAVE_USING_OPERATOR
/* define if your compiler has __attribute__ */
#undef HAVE___ATTRIBUTE__
/* define if your compiler has __builtin_expect */
#undef HAVE___BUILTIN_EXPECT
/* define if your compiler has __sync_val_compare_and_swap */
#undef HAVE___SYNC_VAL_COMPARE_AND_SWAP
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* How to access the PC from a struct ucontext */
#undef PC_FROM_UCONTEXT
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
/* The size of `void *', as computed by sizeof. */
#undef SIZEOF_VOID_P
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* the namespace where STL code like vector<> is defined */
#undef STL_NAMESPACE
/* Version number of package */
#undef VERSION
/* Namespace for Google classes */
#define GOOGLE_NAMESPACE google
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }

@ -43,18 +43,13 @@
#include <errno.h>
#include <string.h>
#include <time.h>
#include <iosfwd>
#include <ostream>
#include <sstream>
#include <string>
#if 0
# include <unistd.h>
#endif
#ifdef __DEPRECATED
// Make GCC quiet.
# undef __DEPRECATED
# include <strstream>
# define __DEPRECATED
#else
# include <strstream>
#endif
#include <vector>
// Annoying stuff for windows -- makes sure clients can import these functions
@ -65,6 +60,14 @@
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
#if defined(_MSC_VER)
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
__pragma(warning(disable:n))
#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
#else
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
#define GLOG_MSVC_POP_WARNING()
#endif
// We care a lot about number of bits things take up. Unfortunately,
// systems define their bit-specific ints in a lot of different ways.
@ -83,7 +86,7 @@
#endif
#if 1
#include "third_party/gflags/gflags/gflags.h"
#include <gflags/gflags.h>
#endif
#ifdef __MINGW32__
@ -97,7 +100,7 @@
namespace google {
#if 0 // the C99 format
#if defined(__MINGW32__) // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
@ -107,16 +110,11 @@ typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif defined(_MSC_VER)
#elif defined(_MSC_VER) // the windows (vc7) format
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#elif defined(__MINGW32__)
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
@ -144,8 +142,12 @@ typedef uint64_t uint64;
#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
#if 0
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
#define GOOGLE_PREDICT_FALSE(x) x
#define GOOGLE_PREDICT_TRUE(x) x
#endif
#endif
@ -304,27 +306,27 @@ typedef uint64_t uint64;
#ifndef DECLARE_VARIABLE
#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
#define DECLARE_VARIABLE(type, name, tn) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
// bool specialization
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, name, bool)
DECLARE_VARIABLE(bool, B, name, bool)
// int32 specialization
#define DECLARE_int32(name) \
DECLARE_VARIABLE(google::int32, name, int32)
DECLARE_VARIABLE(google::int32, I, name, int32)
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \
extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name; \
} \
using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
#define DECLARE_string(name) \
namespace fLS { \
extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#endif
// Set whether log messages go to stderr instead of logfiles
@ -333,6 +335,9 @@ DECLARE_bool(logtostderr);
// Set whether log messages go to stderr in addition to logfiles.
DECLARE_bool(alsologtostderr);
// Set color messages logged to stderr (if supported by terminal).
DECLARE_bool(colorlogtostderr);
// Log messages at a level >= this flag are automatically sent to
// stderr in addition to log files.
DECLARE_int32(stderrthreshold);
@ -465,15 +470,16 @@ DECLARE_bool(stop_logging_if_full_disk);
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
// A very useful logging macro to log windows errors:
#define LOG_SYSRESULT(result) \
if (FAILED(result)) { \
LPTSTR message = NULL; \
LPTSTR msg = reinterpret_cast<LPTSTR>(&message); \
DWORD message_length = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
if (FAILED(HRESULT_FROM_WIN32(result))) { \
LPSTR message = NULL; \
LPSTR msg = reinterpret_cast<LPSTR>(&message); \
DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
FORMAT_MESSAGE_FROM_SYSTEM, \
0, result, 0, msg, 100, NULL); \
if (message_length > 0) { \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
&google::LogMessage::SendToLog).stream() << message; \
&google::LogMessage::SendToLog).stream() \
<< reinterpret_cast<const char*>(message); \
LocalFree(message); \
} \
}
@ -615,18 +621,68 @@ inline std::ostream& operator<<(
namespace google {
// Build the error message string.
template<class t1, class t2>
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
// It means that we cannot use stl_logging if compiler doesn't
// support using expression for operator.
// TODO(hamaji): Figure out a way to fix.
#if 1
using ::operator<<;
#endif
std::strstream ss;
ss << names << " (" << v1 << " vs. " << v2 << ")";
return new std::string(ss.str(), ss.pcount());
// This formats a value for a failing CHECK_XX statement. Ordinarily,
// it uses the definition for operator<<, with a few special cases below.
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
// Overrides for char types provide readable values for unprintable
// characters.
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const char& v);
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const signed char& v);
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
// Build the error message string. Specify no inlining for code size.
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
;
namespace base {
namespace internal {
// If "s" is less than base_logging::INFO, returns base_logging::INFO.
// If "s" is greater than base_logging::FATAL, returns
// base_logging::ERROR. Otherwise, returns "s".
LogSeverity NormalizeSeverity(LogSeverity s);
} // namespace internal
// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
// statement. See MakeCheckOpString for sample usage. Other
// approaches were considered: use of a template method (e.g.,
// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
// base::Print<T2>, &v2), however this approach has complications
// related to volatile arguments and function-pointer arguments).
class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder {
public:
// Inserts "exprtext" and " (" to the stream.
explicit CheckOpMessageBuilder(const char *exprtext);
// Deletes "stream_".
~CheckOpMessageBuilder();
// For inserting the first variable.
std::ostream* ForVar1() { return stream_; }
// For inserting the second variable (adds an intermediate " vs. ").
std::ostream* ForVar2();
// Get the result (inserts the closing ")").
std::string* NewString();
private:
std::ostringstream *stream_;
};
} // namespace base
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
base::CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}
// Helper functions for CHECK_OP macro.
@ -634,26 +690,26 @@ std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <class t1, class t2> \
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (v1 op v2) return NULL; \
else return MakeCheckOpString(v1, v2, names); \
template <typename T1, typename T2> \
inline std::string* name##Impl(const T1& v1, const T2& v2, \
const char* exprtext) { \
if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
else return MakeCheckOpString(v1, v2, exprtext); \
} \
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
return Check##name##Impl<int, int>(v1, v2, names); \
inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
return name##Impl<int, int>(v1, v2, exprtext); \
}
// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h
// provides its own #defines for the simpler names EQ, NE, LE, etc.
// We use the full name Check_EQ, Check_NE, etc. in case the file including
// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
// This happens if, for example, those are used as token names in a
// yacc grammar.
DEFINE_CHECK_OP_IMPL(_EQ, ==)
DEFINE_CHECK_OP_IMPL(_NE, !=)
DEFINE_CHECK_OP_IMPL(_LE, <=)
DEFINE_CHECK_OP_IMPL(_LT, < )
DEFINE_CHECK_OP_IMPL(_GE, >=)
DEFINE_CHECK_OP_IMPL(_GT, > )
DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
DEFINE_CHECK_OP_IMPL(Check_LE, <=)
DEFINE_CHECK_OP_IMPL(Check_LT, < )
DEFINE_CHECK_OP_IMPL(Check_GE, >=)
DEFINE_CHECK_OP_IMPL(Check_GT, > )
#undef DEFINE_CHECK_OP_IMPL
// Helper macro for binary operators.
@ -958,52 +1014,65 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
#define DLOG_ASSERT(condition) \
true ? (void) 0 : LOG_ASSERT(condition)
// MSVC warning C4127: conditional expression is constant
#define DCHECK(condition) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK(condition)
GLOG_MSVC_POP_WARNING() CHECK(condition)
#define DCHECK_EQ(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_EQ(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_NE(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_LE(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_LT(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_GE(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_GT(val1, val2)
GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
// You may see warnings in release mode if you don't use the return
// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
#define DCHECK_NOTNULL(val) (val)
#define DCHECK_STREQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STREQ(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
#define DCHECK_STRCASEEQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STRCASEEQ(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
#define DCHECK_STRNE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STRNE(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
#define DCHECK_STRCASENE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
CHECK_STRCASENE(str1, str2)
GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
#endif // NDEBUG
@ -1020,6 +1089,29 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
namespace base_logging {
// LogMessage::LogStream is a std::ostream backed by this streambuf.
// This class ignores overflow and leaves two bytes at the end of the
// buffer to allow for a '\n' and '\0'.
class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf {
public:
// REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
LogStreamBuf(char *buf, int len) {
setp(buf, buf + len - 2);
}
// This effectively ignores overflow.
virtual int_type overflow(int_type ch) {
return ch;
}
// Legacy public ostrstream method.
size_t pcount() const { return pptr() - pbase(); }
char* pbase() const { return std::streambuf::pbase(); }
};
} // namespace base_logging
//
// This class more or less represents a particular log message. You
// create an instance of LogMessage and then stream stuff to it.
@ -1049,22 +1141,30 @@ public:
#ifdef _MSC_VER
# pragma warning(disable: 4275)
#endif
class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream {
class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
#ifdef _MSC_VER
# pragma warning(default: 4275)
#endif
public:
LogStream(char *buf, int len, int ctr_in)
: ostrstream(buf, len),
ctr_(ctr_in) {
self_ = this;
LogStream(char *buf, int len, int ctr)
: std::ostream(NULL),
streambuf_(buf, len),
ctr_(ctr),
self_(this) {
rdbuf(&streambuf_);
}
int ctr() const { return ctr_; }
void set_ctr(int ctr_in) { ctr_ = ctr_in; }
void set_ctr(int ctr) { ctr_ = ctr; }
LogStream* self() const { return self_; }
// Legacy std::streambuf methods.
size_t pcount() const { return streambuf_.pcount(); }
char* pbase() const { return streambuf_.pbase(); }
char* str() const { return pbase(); }
private:
base_logging::LogStreamBuf streambuf_;
int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
LogStream *self_; // Consistency check hack
};
@ -1133,13 +1233,15 @@ public:
// Call abort() or similar to perform LOG(FATAL) crash.
static void Fail() ;
std::ostream& stream() { return *(data_->stream_); }
std::ostream& stream();
int preserved_errno() const { return data_->preserved_errno_; }
int preserved_errno() const;
// Must be called without the log_mutex held. (L < log_mutex)
static int64 num_messages(int severity);
struct LogMessageData;
private:
// Fully internal SendMethod cases:
void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs
@ -1161,41 +1263,6 @@ private:
// We keep the data in a separate struct so that each instance of
// LogMessage uses less stack space.
struct GOOGLE_GLOG_DLL_DECL LogMessageData {
LogMessageData() {};
int preserved_errno_; // preserved errno
char* buf_;
char* message_text_; // Complete message text (points to selected buffer)
LogStream* stream_alloc_;
LogStream* stream_;
char severity_; // What level is this LogMessage logged at?
int line_; // line number where logging call is.
void (LogMessage::*send_method_)(); // Call this in destructor to send
union { // At most one of these is used: union to keep the size low.
LogSink* sink_; // NULL or sink to send message to
std::vector<std::string>* outvec_; // NULL or vector to push message onto
std::string* message_; // NULL or string to write message into
};
time_t timestamp_; // Time of creation of LogMessage
struct ::tm tm_time_; // Time of creation of LogMessage
size_t num_prefix_chars_; // # of chars of prefix in this message
size_t num_chars_to_log_; // # of chars of msg to send to log
size_t num_chars_to_syslog_; // # of chars of msg to send to syslog
const char* basename_; // basename of file that called LOG
const char* fullname_; // fullname of file that called LOG
bool has_been_flushed_; // false => data has not been flushed
bool first_fatal_; // true => this was first fatal msg
~LogMessageData();
private:
LogMessageData(const LogMessageData&);
void operator=(const LogMessageData&);
};
static LogMessageData fatal_msg_data_exclusive_;
static LogMessageData fatal_msg_data_shared_;
LogMessageData* allocated_;
LogMessageData* data_;
@ -1474,8 +1541,12 @@ extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
// be set to an empty string, if this function failed. This means, in most
// cases, you do not need to check the error code and you can directly
// use the value of "buf". It will never have an undefined value.
// DEPRECATED: Use StrError(int) instead.
GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len);
// A thread-safe replacement for strerror(). Returns a string describing the
// given POSIX error code.
GOOGLE_GLOG_DLL_DECL std::string StrError(int err);
// A class for which we define operator<<, which does nothing.
class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {

@ -55,7 +55,6 @@ int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
return _vsnprintf(str, size-1, format, ap);
}
// MinGW64 defines
#ifndef __MINGW64__
int snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;

@ -45,7 +45,10 @@
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
#endif
#include <windows.h>
#include <winsock.h> /* for gethostname */
#include <io.h> /* because we so often use open/close/etc */
@ -59,6 +62,8 @@
* used by both C and C++ code, so we put all the C++ together.
*/
#ifdef _MSC_VER
/* 4244: otherwise we get problems when substracting two size_t's to an int
* 4251: it's complaining about a private struct I've chosen not to dllexport
* 4355: we use this in a constructor, but we do it safely
@ -111,9 +116,7 @@ extern int snprintf(char *str, size_t size,
extern int safe_vsnprintf(char *str, size_t size,
const char *format, va_list ap);
#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
#if !defined(__MINGW32__)
#define va_copy(dst, src) (dst) = (src)
#endif
/* Windows doesn't support specifying the number of buckets as a
* hash_map constructor arg, so we leave this blank.
@ -123,11 +126,14 @@ extern int safe_vsnprintf(char *str, size_t size,
#define DEFAULT_TEMPLATE_ROOTDIR ".."
// ----------------------------------- SYSTEM/PROCESS
#ifndef __MINGW64__
typedef int pid_t;
#endif
#define getpid _getpid
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif // _MSC_VER
// ----------------------------------- THREADS
typedef DWORD pthread_t;
typedef DWORD pthread_key_t;