/* * Copyright 2017-present 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 DEFINE_string( category, "", "Crash with a message to this category instead of the default"); DEFINE_bool(crash, true, "Crash with a fatal log message."); DEFINE_bool( check_debug, false, "Print whether this binary was built in debug mode " "and then exit successfully"); DEFINE_bool(fail_fatal_xlog_if, false, "Fail an XLOG_IF(FATAL) check."); DEFINE_bool(fail_dfatal_xlog_if, false, "Fail an XLOG_IF(DFATAL) check."); DEFINE_bool(fail_xcheck, false, "Fail an XCHECK() test."); DEFINE_bool( fail_xcheck_nomsg, false, "Fail an XCHECK() test with no additional message."); DEFINE_bool(fail_xdcheck, false, "Fail an XDCHECK() test."); using folly::LogLevel; namespace { /** * Helper class to optionally log a fatal message during static initialization * or destruction. * * Since command line arguments have not been processed during static * initialization, we check an environment variable. */ class InitChecker { public: InitChecker() : value_{getenv("CRASH_DURING_INIT")} { if (value_ && strcmp(value_, "shutdown") != 0) { XLOG(FATAL) << "crashing during static initialization"; } } ~InitChecker() { if (value_) { XLOG(FATAL) << "crashing during static destruction"; } } const char* value_{nullptr}; }; static InitChecker initChecker; } // namespace namespace { int runHelper() { if (!FLAGS_category.empty()) { folly::Logger logger{FLAGS_category}; FB_LOG(logger, FATAL, "crashing to category ", FLAGS_category); } if (!FLAGS_crash) { return 0; } XLOG(FATAL) << "test program crashing!"; // Even though this function is defined to return an integer, the compiler // should be able to detect that XLOG(FATAL) never returns. It shouldn't // complain that we don't return an integer here. } } // namespace std::string fbLogFatalCheck() { folly::Logger logger("some.category"); FB_LOG(logger, FATAL) << "we always crash"; // This function mostly exists to make sure the compiler does not warn // about a missing return statement here. } /* * This is a simple helper program to exercise the LOG(FATAL) functionality. */ int main(int argc, char* argv[]) { auto init = folly::Init(&argc, &argv); if (FLAGS_check_debug) { std::cout << "DEBUG=" << static_cast(folly::kIsDebug) << "\n"; return 0; } XLOG_IF(FATAL, FLAGS_fail_fatal_xlog_if) << "--fail_fatal_xlog_if specified!"; XLOG_IF(DFATAL, FLAGS_fail_dfatal_xlog_if) << "--fail_dfatal_xlog_if specified!"; XCHECK(!FLAGS_fail_xcheck) << ": --fail_xcheck specified!"; XCHECK(!FLAGS_fail_xcheck_nomsg); XDCHECK(!FLAGS_fail_xdcheck) << ": --fail_xdcheck specified!"; // Do most of the work in a separate helper function. // // The main reason for putting this in a helper function is to ensure that // the compiler does not warn about missing return statements on XLOG(FATAL) // code paths. Unfortunately it appears like some compilers always suppress // this warning for main(). return runHelper(); }