From: Denis Samoylov Date: Thu, 28 Jan 2016 19:18:54 +0000 (-0800) Subject: A common init function for binaries and a default main function for tests X-Git-Tag: deprecate-dynamic-initializer~125 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=754568a3ca0583bc4aa9f64a5b09fa9c3743876f A common init function for binaries and a default main function for tests Summary: Added initialization routines to test main function that can help with debugging tests Reviewed By: markisaa, yfeldblum Differential Revision: D2839759 fb-gh-sync-id: 71cad45f3747336c8c7f8706db139cd060e1442b --- diff --git a/README.md b/README.md index fb6c1243..ad8f49b7 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,10 @@ sudo apt-get install \ zlib1g-dev \ binutils-dev \ libjemalloc-dev \ - libssl-dev + libssl-dev \ + libunwind8-dev \ + libelf-dev \ + libdwarf-dev ``` Ubuntu 14.04 LTS @@ -163,3 +166,6 @@ Other Linux distributions - double-conversion-devel - openssl-devel - libevent-devel + - libdwarf-dev + - libelf-dev + - libunwind8-dev diff --git a/folly/Makefile.am b/folly/Makefile.am index e5427199..63edfd81 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -1,4 +1,8 @@ +if HAVE_LINUX +SUBDIRS = . experimental init test +else SUBDIRS = . test +endif ACLOCAL_AMFLAGS = -I m4 @@ -119,6 +123,13 @@ nobase_follyinclude_HEADERS = \ experimental/NestedCommandLineApp.h \ experimental/ProgramOptions.h \ experimental/ReadMostlySharedPtr.h \ + experimental/symbolizer/Elf.h \ + experimental/symbolizer/ElfCache.h \ + experimental/symbolizer/Dwarf.h \ + experimental/symbolizer/LineReader.h \ + experimental/symbolizer/SignalHandler.h \ + experimental/symbolizer/StackTrace.cpp \ + experimental/symbolizer/Symbolizer.h \ experimental/Select64.h \ experimental/StringKeyedCommon.h \ experimental/StringKeyedUnorderedMap.h \ @@ -184,6 +195,7 @@ nobase_follyinclude_HEADERS = \ IPAddressV6.h \ IPAddressException.h \ IndexedMemPool.h \ + init/Init.h \ IntrusiveList.h \ io/Compression.h \ io/Cursor.h \ diff --git a/folly/configure.ac b/folly/configure.ac index a60af3c5..d7ddb657 100644 --- a/folly/configure.ac +++ b/folly/configure.ac @@ -468,6 +468,9 @@ AC_CHECK_HEADER([snappy.h], AC_CHECK_LIB([snappy], [main])) AC_CHECK_HEADER([zlib.h], AC_CHECK_LIB([z], [main])) AC_CHECK_HEADER([lzma.h], AC_CHECK_LIB([lzma], [main])) AC_CHECK_HEADER([zstd.h], AC_CHECK_LIB([zstd], [main])) +AC_CHECK_HEADERS([libdwarf.h dwarf.h],, AC_MSG_ERROR([Please install libdwarf development package])) +AC_CHECK_HEADERS([libelf.h elf.h],, AC_MSG_ERROR([Please install libelf development package])) +AC_CHECK_HEADERS(libunwind.h, ac_cv_have_libunwind_h=1, ac_cv_have_libunwind_h=0) # Include directory that contains "folly" so #include works AM_CPPFLAGS='-I$(top_srcdir)/..' @@ -494,5 +497,8 @@ AM_CONDITIONAL([HAVE_EXTRANDOM_SFMT19937], # Output AC_CONFIG_FILES([Makefile test/Makefile - test/function_benchmark/Makefile]) + test/function_benchmark/Makefile + experimental/Makefile + experimental/symbolizer/Makefile + init/Makefile]) AC_OUTPUT diff --git a/folly/experimental/Makefile.am b/folly/experimental/Makefile.am new file mode 100644 index 00000000..4cdff7ed --- /dev/null +++ b/folly/experimental/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = symbolizer diff --git a/folly/experimental/symbolizer/Makefile.am b/folly/experimental/symbolizer/Makefile.am new file mode 100644 index 00000000..8473959d --- /dev/null +++ b/folly/experimental/symbolizer/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS = . + +lib_LTLIBRARIES = libfollysymbolizer.la + +libfollysymbolizer_la_SOURCES = \ + Elf.cpp \ + ElfCache.cpp \ + Dwarf.cpp \ + LineReader.cpp \ + SignalHandler.cpp \ + StackTrace.cpp \ + Symbolizer.cpp + +libfollysymbolizer_la_LIBADD = $(top_builddir)/libfolly.la +libfollysymbolizer_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LT_VERSION) diff --git a/folly/init/Init.cpp b/folly/init/Init.cpp new file mode 100644 index 00000000..46d30a08 --- /dev/null +++ b/folly/init/Init.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +#include +#include + +namespace folly { + +void init(int* argc, char*** argv, bool removeFlags) { + // Install the handler now, to trap errors received during startup. + // The callbacks, if any, can be installed later + folly::symbolizer::installFatalSignalHandler(); + + google::ParseCommandLineFlags(argc, argv, removeFlags); + + auto programName = argc && argv && *argc > 0 ? (*argv)[0] : "unknown"; + google::InitGoogleLogging(programName); + + // Don't use glog's DumpStackTraceAndExit; rely on our signal handler. + google::InstallFailureFunction(abort); + + // Move from the registration phase to the "you can actually instantiate + // things now" phase. + folly::SingletonVault::singleton()->registrationComplete(); + + // Actually install the callbacks into the handler. + folly::symbolizer::installFatalSignalCallbacks(); +} +} //!folly diff --git a/folly/init/Init.h b/folly/init/Init.h new file mode 100644 index 00000000..8c1bc7e5 --- /dev/null +++ b/folly/init/Init.h @@ -0,0 +1,35 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INIT_LIGHT_BASE_H +#define INIT_LIGHT_BASE_H + +/* + * Calls common init functions in the necessary order + * Among other things, this ensures that folly::Singletons are initialized + * correctly and installs signal handlers for a superior debugging experience. + * It also initializes gflags and glog. + * + * @param argc, argv arguments to your main + * @param removeFlags if true, will update argc,argv to remove recognized + * gflags passed on the command line + */ +namespace folly { + +void init(int* argc, char*** argv, bool removeFlags = true); + +} // folly + +#endif diff --git a/folly/init/Makefile.am b/folly/init/Makefile.am new file mode 100644 index 00000000..40320ac6 --- /dev/null +++ b/folly/init/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = . + +lib_LTLIBRARIES = libfollyinit.la + +libfollyinit_la_SOURCES = Init.cpp +libfollyinit_la_LIBADD = $(top_builddir)/libfolly.la $(top_builddir)/experimental/symbolizer/libfollysymbolizer.la +libfollyinit_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LT_VERSION) diff --git a/folly/test/Makefile.am b/folly/test/Makefile.am index c9dec173..11d68151 100644 --- a/folly/test/Makefile.am +++ b/folly/test/Makefile.am @@ -14,182 +14,189 @@ TESTS= \ bits_test \ bit_iterator_test -check_LTLIBRARIES = libgtestmain.la libgtest.la +check_LTLIBRARIES = libfollytestmain.la libgtest.la check_PROGRAMS = -libgtestmain_la_CPPFLAGS = -Igtest-1.7.0 -Igtest-1.7.0/src -libgtestmain_la_SOURCES = gtest-1.7.0/src/gtest-all.cc gtest-1.7.0/src/gtest_main.cc - libgtest_la_CPPFLAGS = -Igtest-1.7.0 -Igtest-1.7.0/src libgtest_la_SOURCES = gtest-1.7.0/src/gtest-all.cc +if HAVE_LINUX +libfollytestmain_la_CPPFLAGS = $(AM_CPPFLAGS) $(libgtest_la_CPPFLAGS) +libfollytestmain_la_SOURCES = $(libgtest_la_SOURCES) common/TestMain.cpp +libfollytestmain_la_LIBADD = $(top_builddir)/init/libfollyinit.la $(top_builddir)/libfolly.la +else +libfollytestmain_la_CPPFLAGS = $(libgtest_la_CPPFLAGS) +libfollytestmain_la_SOURCES = $(libgtest_la_SOURCES) gtest-1.7.0/src/gtest_main.cc +libfollytestmain_la_LIBADD = $(top_builddir)/libfolly.la +endif + noinst_HEADERS = FBStringTestBenchmarks.cpp.h \ - FBVectorTestBenchmarks.cpp.h + FBVectorTestBenchmarks.cpp.h spin_lock_test_SOURCES = SpinLockTest.cpp -spin_lock_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +spin_lock_test_LDADD = libfollytestmain.la TESTS += spin_lock_test if RUN_ARCH_SPECIFIC_TESTS small_locks_test_SOURCES = SmallLocksTest.cpp -small_locks_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +small_locks_test_LDADD = libfollytestmain.la TESTS += small_locks_test # Fails with WARNING: Logging before InitGoogleLogging() is written to STDERR packed_sync_ptr_test_SOURCES = PackedSyncPtrTest.cpp -packed_sync_ptr_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +packed_sync_ptr_test_LDADD = libfollytestmain.la TESTS += packed_sync_ptr_test small_vector_test_SOURCES = small_vector_test.cpp -small_vector_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +small_vector_test_LDADD = libfollytestmain.la TESTS += small_vector_test discriminated_ptr_test_SOURCES = DiscriminatedPtrTest.cpp -discriminated_ptr_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +discriminated_ptr_test_LDADD = libfollytestmain.la TESTS += discriminated_ptr_test if !HAVE_PPC64 cpuid_test_SOURCES = CpuIdTest.cpp -cpuid_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +cpuid_test_LDADD = libfollytestmain.la TESTS += cpuid_test endif endif sorted_vector_types_test_SOURCES = sorted_vector_test.cpp -sorted_vector_types_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +sorted_vector_types_test_LDADD = libfollytestmain.la foreach_test_SOURCES = ForeachTest.cpp -foreach_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +foreach_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la hash_test_SOURCES = HashTest.cpp -hash_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +hash_test_LDADD = libfollytestmain.la fbstring_test_using_jemalloc_SOURCES = FBStringTest.cpp -fbstring_test_using_jemalloc_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +fbstring_test_using_jemalloc_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += fbstring_test_using_jemalloc thread_cached_int_test_SOURCES = ThreadCachedIntTest.cpp -thread_cached_int_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +thread_cached_int_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la thread_local_test_SOURCES = ThreadLocalTest.cpp -thread_local_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +thread_local_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la thread_local_test_LDFLAGS = -ldl TESTS += thread_cached_int_test thread_local_test fbvector_test_SOURCES = FBVectorTest.cpp -fbvector_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +fbvector_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += fbvector_test # fails due to cout dynamic_test_SOURCES = DynamicTest.cpp -dynamic_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la $(top_builddir)/libfolly.la +dynamic_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += dynamic_test # fails due to cout json_test_SOURCES = JsonTest.cpp -json_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la $(top_builddir)/libfolly.la +json_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += json_test benchmark_test_SOURCES = BenchmarkTest.cpp -benchmark_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +benchmark_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la check_PROGRAMS += benchmark_test # fails due to destructor scope_guard_test_SOURCES = ScopeGuardTest.cpp -scope_guard_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +scope_guard_test_LDADD = libfollytestmain.la TESTS += scope_guard_test timeout_queue_test_SOURCES = TimeoutQueueTest.cpp -timeout_queue_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +timeout_queue_test_LDADD = libfollytestmain.la conv_test_SOURCES = ConvTest.cpp -conv_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +conv_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la range_test_SOURCES = RangeTest.cpp -range_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +range_test_LDADD = libfollytestmain.la bits_test_SOURCES = BitsTest.cpp -bits_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +bits_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la bit_iterator_test_SOURCES = BitIteratorTest.cpp -bit_iterator_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +bit_iterator_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la endian_test_SOURCES = EndianTest.cpp -endian_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +endian_test_LDADD = libfollytestmain.la TESTS += endian_test rw_spinlock_test_SOURCES = RWSpinLockTest.cpp -rw_spinlock_test_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +rw_spinlock_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += rw_spinlock_test synchronized_test_SOURCES = SynchronizedTest.cpp -synchronized_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +synchronized_test_LDADD = libfollytestmain.la TESTS += synchronized_test concurrent_skiplist_test_SOURCES = ConcurrentSkipListTest.cpp -concurrent_skiplist_test_LDADD = libgtest.la $(top_builddir)/libfolly.la +concurrent_skiplist_test_LDADD = libfollytestmain.la TESTS += concurrent_skiplist_test concurrent_skiplist_benchmark_SOURCES = ConcurrentSkipListBenchmark.cpp -concurrent_skiplist_benchmark_LDADD = libgtestmain.la $(top_builddir)/libfollybenchmark.la $(top_builddir)/libfolly.la +concurrent_skiplist_benchmark_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la check_PROGRAMS += concurrent_skiplist_benchmark histogram_test_SOURCES = HistogramTest.cpp -histogram_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +histogram_test_LDADD = libfollytestmain.la TESTS += histogram_test group_varint_test_SOURCES = GroupVarintTest.cpp -group_varint_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +group_varint_test_LDADD = libfollytestmain.la TESTS += group_varint_test map_util_test_SOURCES = MapUtilTest.cpp -map_util_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +map_util_test_LDADD = libfollytestmain.la TESTS += map_util_test string_test_SOURCES = StringTest.cpp -string_test_LDADD = libgtest.la $(top_builddir)/libfolly.la +string_test_LDADD = libfollytestmain.la TESTS += string_test producer_consumer_queue_test_SOURCES = ProducerConsumerQueueTest.cpp -producer_consumer_queue_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +producer_consumer_queue_test_LDADD = libfollytestmain.la TESTS += producer_consumer_queue_test atomic_hash_array_test_SOURCES = AtomicHashArrayTest.cpp -atomic_hash_array_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +atomic_hash_array_test_LDADD = libfollytestmain.la TESTS += atomic_hash_array_test atomic_hash_map_test_SOURCES = AtomicHashMapTest.cpp -atomic_hash_map_test_LDADD = libgtest.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la +atomic_hash_map_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += atomic_hash_map_test format_test_SOURCES = FormatTest.cpp -format_test_LDADD = libgtest.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la +format_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += format_test fingerprint_test_SOURCES = FingerprintTest.cpp -fingerprint_test_LDADD = libgtest.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la +fingerprint_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += fingerprint_test portability_test_SOURCES = PortabilityTest.cpp -portability_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +portability_test_LDADD = libfollytestmain.la TESTS += portability_test spooky_hash_v1_test_SOURCES = SpookyHashV1Test.cpp -spooky_hash_v1_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la +spooky_hash_v1_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += spooky_hash_v1_test spooky_hash_v2_test_SOURCES = SpookyHashV2Test.cpp -spooky_hash_v2_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la +spooky_hash_v2_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += spooky_hash_v2_test token_bucket_test_SOURCES = TokenBucketTest.cpp -token_bucket_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la +token_bucket_test_LDADD = libfollytestmain.la $(top_builddir)/libfollybenchmark.la TESTS += token_bucket_test thread_name_test_SOURCES = ThreadNameTest.cpp -thread_name_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +thread_name_test_LDADD = libfollytestmain.la TESTS += thread_name_test @@ -225,7 +232,7 @@ futures_test_SOURCES = \ ../futures/test/WhenTest.cpp \ ../futures/test/WhileDoTest.cpp -futures_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la +futures_test_LDADD = libfollytestmain.la TESTS += futures_test check_PROGRAMS += $(TESTS) diff --git a/folly/test/common/TestMain.cpp b/folly/test/common/TestMain.cpp new file mode 100644 index 00000000..c8e08d8a --- /dev/null +++ b/folly/test/common/TestMain.cpp @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +/* + * This is the recommended main function for all tests. + * The Makefile links it into all of the test programs so that tests do not need + * to - and indeed should typically not - define their own main() functions + */ +int main(int argc, char** argv) __attribute__((__weak__)); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + folly::init(&argc, &argv); + return RUN_ALL_TESTS(); +}