unioil-loyalty-rn-app/ios/Pods/RCT-Folly/folly/lang/SafeAssert.cpp

588 lines
13 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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 <folly/lang/SafeAssert.h>
#include <algorithm>
#include <cerrno>
#include <cstdarg>
#include <folly/detail/FileUtilDetail.h>
#include <folly/lang/ToAscii.h>
#include <folly/portability/SysTypes.h>
#include <folly/portability/Windows.h>
#if defined(_WIN32)
#include <fileapi.h> // @manual
#else
// @lint-ignore CLANGTIDY
#include <unistd.h>
#endif
// This header takes care to have minimal dependencies.
namespace folly {
namespace detail {
namespace {
// script (centos):
//
// for e in $(
// cat /usr/include/asm*/errno*.h | awk '{print $2}' | grep -P '^E' | sort
// ) ; do
// echo "#if defined($e)"
// echo " FOLLY_DETAIL_ERROR($e),"
// echo "#endif"
// done
#define FOLLY_DETAIL_ERROR(name) \
{ name, #name }
constexpr std::pair<int, const char*> errors[] = {
#if defined(E2BIG)
FOLLY_DETAIL_ERROR(E2BIG),
#endif
#if defined(EACCES)
FOLLY_DETAIL_ERROR(EACCES),
#endif
#if defined(EADDRINUSE)
FOLLY_DETAIL_ERROR(EADDRINUSE),
#endif
#if defined(EADDRNOTAVAIL)
FOLLY_DETAIL_ERROR(EADDRNOTAVAIL),
#endif
#if defined(EADV)
FOLLY_DETAIL_ERROR(EADV),
#endif
#if defined(EAFNOSUPPORT)
FOLLY_DETAIL_ERROR(EAFNOSUPPORT),
#endif
#if defined(EAGAIN)
FOLLY_DETAIL_ERROR(EAGAIN),
#endif
#if defined(EALREADY)
FOLLY_DETAIL_ERROR(EALREADY),
#endif
#if defined(EBADE)
FOLLY_DETAIL_ERROR(EBADE),
#endif
#if defined(EBADF)
FOLLY_DETAIL_ERROR(EBADF),
#endif
#if defined(EBADFD)
FOLLY_DETAIL_ERROR(EBADFD),
#endif
#if defined(EBADMSG)
FOLLY_DETAIL_ERROR(EBADMSG),
#endif
#if defined(EBADR)
FOLLY_DETAIL_ERROR(EBADR),
#endif
#if defined(EBADRQC)
FOLLY_DETAIL_ERROR(EBADRQC),
#endif
#if defined(EBADSLT)
FOLLY_DETAIL_ERROR(EBADSLT),
#endif
#if defined(EBFONT)
FOLLY_DETAIL_ERROR(EBFONT),
#endif
#if defined(EBUSY)
FOLLY_DETAIL_ERROR(EBUSY),
#endif
#if defined(ECANCELED)
FOLLY_DETAIL_ERROR(ECANCELED),
#endif
#if defined(ECHILD)
FOLLY_DETAIL_ERROR(ECHILD),
#endif
#if defined(ECHRNG)
FOLLY_DETAIL_ERROR(ECHRNG),
#endif
#if defined(ECOMM)
FOLLY_DETAIL_ERROR(ECOMM),
#endif
#if defined(ECONNABORTED)
FOLLY_DETAIL_ERROR(ECONNABORTED),
#endif
#if defined(ECONNREFUSED)
FOLLY_DETAIL_ERROR(ECONNREFUSED),
#endif
#if defined(ECONNRESET)
FOLLY_DETAIL_ERROR(ECONNRESET),
#endif
#if defined(EDEADLK)
FOLLY_DETAIL_ERROR(EDEADLK),
#endif
#if defined(EDEADLOCK)
FOLLY_DETAIL_ERROR(EDEADLOCK),
#endif
#if defined(EDESTADDRREQ)
FOLLY_DETAIL_ERROR(EDESTADDRREQ),
#endif
#if defined(EDOM)
FOLLY_DETAIL_ERROR(EDOM),
#endif
#if defined(EDOTDOT)
FOLLY_DETAIL_ERROR(EDOTDOT),
#endif
#if defined(EDQUOT)
FOLLY_DETAIL_ERROR(EDQUOT),
#endif
#if defined(EEXIST)
FOLLY_DETAIL_ERROR(EEXIST),
#endif
#if defined(EFAULT)
FOLLY_DETAIL_ERROR(EFAULT),
#endif
#if defined(EFBIG)
FOLLY_DETAIL_ERROR(EFBIG),
#endif
#if defined(EHOSTDOWN)
FOLLY_DETAIL_ERROR(EHOSTDOWN),
#endif
#if defined(EHOSTUNREACH)
FOLLY_DETAIL_ERROR(EHOSTUNREACH),
#endif
#if defined(EHWPOISON)
FOLLY_DETAIL_ERROR(EHWPOISON),
#endif
#if defined(EIDRM)
FOLLY_DETAIL_ERROR(EIDRM),
#endif
#if defined(EILSEQ)
FOLLY_DETAIL_ERROR(EILSEQ),
#endif
#if defined(EINPROGRESS)
FOLLY_DETAIL_ERROR(EINPROGRESS),
#endif
#if defined(EINTR)
FOLLY_DETAIL_ERROR(EINTR),
#endif
#if defined(EINVAL)
FOLLY_DETAIL_ERROR(EINVAL),
#endif
#if defined(EIO)
FOLLY_DETAIL_ERROR(EIO),
#endif
#if defined(EISCONN)
FOLLY_DETAIL_ERROR(EISCONN),
#endif
#if defined(EISDIR)
FOLLY_DETAIL_ERROR(EISDIR),
#endif
#if defined(EISNAM)
FOLLY_DETAIL_ERROR(EISNAM),
#endif
#if defined(EKEYEXPIRED)
FOLLY_DETAIL_ERROR(EKEYEXPIRED),
#endif
#if defined(EKEYREJECTED)
FOLLY_DETAIL_ERROR(EKEYREJECTED),
#endif
#if defined(EKEYREVOKED)
FOLLY_DETAIL_ERROR(EKEYREVOKED),
#endif
#if defined(EL2HLT)
FOLLY_DETAIL_ERROR(EL2HLT),
#endif
#if defined(EL2NSYNC)
FOLLY_DETAIL_ERROR(EL2NSYNC),
#endif
#if defined(EL3HLT)
FOLLY_DETAIL_ERROR(EL3HLT),
#endif
#if defined(EL3RST)
FOLLY_DETAIL_ERROR(EL3RST),
#endif
#if defined(ELIBACC)
FOLLY_DETAIL_ERROR(ELIBACC),
#endif
#if defined(ELIBBAD)
FOLLY_DETAIL_ERROR(ELIBBAD),
#endif
#if defined(ELIBEXEC)
FOLLY_DETAIL_ERROR(ELIBEXEC),
#endif
#if defined(ELIBMAX)
FOLLY_DETAIL_ERROR(ELIBMAX),
#endif
#if defined(ELIBSCN)
FOLLY_DETAIL_ERROR(ELIBSCN),
#endif
#if defined(ELNRNG)
FOLLY_DETAIL_ERROR(ELNRNG),
#endif
#if defined(ELOOP)
FOLLY_DETAIL_ERROR(ELOOP),
#endif
#if defined(EMEDIUMTYPE)
FOLLY_DETAIL_ERROR(EMEDIUMTYPE),
#endif
#if defined(EMFILE)
FOLLY_DETAIL_ERROR(EMFILE),
#endif
#if defined(EMLINK)
FOLLY_DETAIL_ERROR(EMLINK),
#endif
#if defined(EMSGSIZE)
FOLLY_DETAIL_ERROR(EMSGSIZE),
#endif
#if defined(EMULTIHOP)
FOLLY_DETAIL_ERROR(EMULTIHOP),
#endif
#if defined(ENAMETOOLONG)
FOLLY_DETAIL_ERROR(ENAMETOOLONG),
#endif
#if defined(ENAVAIL)
FOLLY_DETAIL_ERROR(ENAVAIL),
#endif
#if defined(ENETDOWN)
FOLLY_DETAIL_ERROR(ENETDOWN),
#endif
#if defined(ENETRESET)
FOLLY_DETAIL_ERROR(ENETRESET),
#endif
#if defined(ENETUNREACH)
FOLLY_DETAIL_ERROR(ENETUNREACH),
#endif
#if defined(ENFILE)
FOLLY_DETAIL_ERROR(ENFILE),
#endif
#if defined(ENOANO)
FOLLY_DETAIL_ERROR(ENOANO),
#endif
#if defined(ENOBUFS)
FOLLY_DETAIL_ERROR(ENOBUFS),
#endif
#if defined(ENOCSI)
FOLLY_DETAIL_ERROR(ENOCSI),
#endif
#if defined(ENODATA)
FOLLY_DETAIL_ERROR(ENODATA),
#endif
#if defined(ENODEV)
FOLLY_DETAIL_ERROR(ENODEV),
#endif
#if defined(ENOENT)
FOLLY_DETAIL_ERROR(ENOENT),
#endif
#if defined(ENOEXEC)
FOLLY_DETAIL_ERROR(ENOEXEC),
#endif
#if defined(ENOKEY)
FOLLY_DETAIL_ERROR(ENOKEY),
#endif
#if defined(ENOLCK)
FOLLY_DETAIL_ERROR(ENOLCK),
#endif
#if defined(ENOLINK)
FOLLY_DETAIL_ERROR(ENOLINK),
#endif
#if defined(ENOMEDIUM)
FOLLY_DETAIL_ERROR(ENOMEDIUM),
#endif
#if defined(ENOMEM)
FOLLY_DETAIL_ERROR(ENOMEM),
#endif
#if defined(ENOMSG)
FOLLY_DETAIL_ERROR(ENOMSG),
#endif
#if defined(ENONET)
FOLLY_DETAIL_ERROR(ENONET),
#endif
#if defined(ENOPKG)
FOLLY_DETAIL_ERROR(ENOPKG),
#endif
#if defined(ENOPROTOOPT)
FOLLY_DETAIL_ERROR(ENOPROTOOPT),
#endif
#if defined(ENOSPC)
FOLLY_DETAIL_ERROR(ENOSPC),
#endif
#if defined(ENOSR)
FOLLY_DETAIL_ERROR(ENOSR),
#endif
#if defined(ENOSTR)
FOLLY_DETAIL_ERROR(ENOSTR),
#endif
#if defined(ENOSYS)
FOLLY_DETAIL_ERROR(ENOSYS),
#endif
#if defined(ENOTBLK)
FOLLY_DETAIL_ERROR(ENOTBLK),
#endif
#if defined(ENOTCONN)
FOLLY_DETAIL_ERROR(ENOTCONN),
#endif
#if defined(ENOTDIR)
FOLLY_DETAIL_ERROR(ENOTDIR),
#endif
#if defined(ENOTEMPTY)
FOLLY_DETAIL_ERROR(ENOTEMPTY),
#endif
#if defined(ENOTNAM)
FOLLY_DETAIL_ERROR(ENOTNAM),
#endif
#if defined(ENOTRECOVERABLE)
FOLLY_DETAIL_ERROR(ENOTRECOVERABLE),
#endif
#if defined(ENOTSOCK)
FOLLY_DETAIL_ERROR(ENOTSOCK),
#endif
#if defined(ENOTTY)
FOLLY_DETAIL_ERROR(ENOTTY),
#endif
#if defined(ENOTUNIQ)
FOLLY_DETAIL_ERROR(ENOTUNIQ),
#endif
#if defined(ENXIO)
FOLLY_DETAIL_ERROR(ENXIO),
#endif
#if defined(EOPNOTSUPP)
FOLLY_DETAIL_ERROR(EOPNOTSUPP),
#endif
#if defined(EOVERFLOW)
FOLLY_DETAIL_ERROR(EOVERFLOW),
#endif
#if defined(EOWNERDEAD)
FOLLY_DETAIL_ERROR(EOWNERDEAD),
#endif
#if defined(EPERM)
FOLLY_DETAIL_ERROR(EPERM),
#endif
#if defined(EPFNOSUPPORT)
FOLLY_DETAIL_ERROR(EPFNOSUPPORT),
#endif
#if defined(EPIPE)
FOLLY_DETAIL_ERROR(EPIPE),
#endif
#if defined(EPROTO)
FOLLY_DETAIL_ERROR(EPROTO),
#endif
#if defined(EPROTONOSUPPORT)
FOLLY_DETAIL_ERROR(EPROTONOSUPPORT),
#endif
#if defined(EPROTOTYPE)
FOLLY_DETAIL_ERROR(EPROTOTYPE),
#endif
#if defined(ERANGE)
FOLLY_DETAIL_ERROR(ERANGE),
#endif
#if defined(EREMCHG)
FOLLY_DETAIL_ERROR(EREMCHG),
#endif
#if defined(EREMOTE)
FOLLY_DETAIL_ERROR(EREMOTE),
#endif
#if defined(EREMOTEIO)
FOLLY_DETAIL_ERROR(EREMOTEIO),
#endif
#if defined(ERESTART)
FOLLY_DETAIL_ERROR(ERESTART),
#endif
#if defined(ERFKILL)
FOLLY_DETAIL_ERROR(ERFKILL),
#endif
#if defined(EROFS)
FOLLY_DETAIL_ERROR(EROFS),
#endif
#if defined(ESHUTDOWN)
FOLLY_DETAIL_ERROR(ESHUTDOWN),
#endif
#if defined(ESOCKTNOSUPPORT)
FOLLY_DETAIL_ERROR(ESOCKTNOSUPPORT),
#endif
#if defined(ESPIPE)
FOLLY_DETAIL_ERROR(ESPIPE),
#endif
#if defined(ESRCH)
FOLLY_DETAIL_ERROR(ESRCH),
#endif
#if defined(ESRMNT)
FOLLY_DETAIL_ERROR(ESRMNT),
#endif
#if defined(ESTALE)
FOLLY_DETAIL_ERROR(ESTALE),
#endif
#if defined(ESTRPIPE)
FOLLY_DETAIL_ERROR(ESTRPIPE),
#endif
#if defined(ETIME)
FOLLY_DETAIL_ERROR(ETIME),
#endif
#if defined(ETIMEDOUT)
FOLLY_DETAIL_ERROR(ETIMEDOUT),
#endif
#if defined(ETOOMANYREFS)
FOLLY_DETAIL_ERROR(ETOOMANYREFS),
#endif
#if defined(ETXTBSY)
FOLLY_DETAIL_ERROR(ETXTBSY),
#endif
#if defined(EUCLEAN)
FOLLY_DETAIL_ERROR(EUCLEAN),
#endif
#if defined(EUNATCH)
FOLLY_DETAIL_ERROR(EUNATCH),
#endif
#if defined(EUSERS)
FOLLY_DETAIL_ERROR(EUSERS),
#endif
#if defined(EWOULDBLOCK)
FOLLY_DETAIL_ERROR(EWOULDBLOCK),
#endif
#if defined(EXDEV)
FOLLY_DETAIL_ERROR(EXDEV),
#endif
#if defined(EXFULL)
FOLLY_DETAIL_ERROR(EXFULL),
#endif
};
#undef FOLLY_DETAIL_ERROR
#if defined(_WIN32)
constexpr int stderr_fileno = 2;
ssize_t write(int fh, void const* buf, size_t count) {
auto r = _write(fh, buf, static_cast<unsigned int>(count));
if ((r > 0 && size_t(r) != count) || (r == -1 && errno == ENOSPC)) {
// Writing to a pipe with a full buffer doesn't generate
// any error type, unless it caused us to write exactly 0
// bytes, so we have to see if we have a pipe first. We
// don't touch the errno for anything else.
HANDLE h = (HANDLE)_get_osfhandle(fh);
if (GetFileType(h) == FILE_TYPE_PIPE) {
DWORD state = 0;
if (GetNamedPipeHandleState(
h, &state, nullptr, nullptr, nullptr, nullptr, 0)) {
if ((state & PIPE_NOWAIT) == PIPE_NOWAIT) {
errno = EAGAIN;
return -1;
}
}
}
}
return r;
}
int fsync(int fh) {
HANDLE h = (HANDLE)_get_osfhandle(fh);
if (!FlushFileBuffers(h)) {
return -1;
}
return 0;
}
#else
constexpr int stderr_fileno = STDERR_FILENO;
#endif
#if !defined(_WIN32) && !defined(_POSIX_FSYNC)
int fsync(int fh) {
return 0;
}
#endif
void writeStderr(const char* s, size_t len) {
fileutil_detail::wrapFull(write, stderr_fileno, const_cast<char*>(s), len);
}
void writeStderr(const char* s) {
writeStderr(s, strlen(s));
}
void flushStderr() {
fileutil_detail::wrapNoInt(fsync, stderr_fileno);
}
[[noreturn]] FOLLY_COLD void safe_assert_terminate_v(
safe_assert_arg const* arg_, int const error, va_list msg) noexcept {
auto const& arg = *arg_;
char buf[to_ascii_size_max_decimal<uint64_t>];
writeStderr("\n\nAssertion failure: ");
writeStderr(arg.expr + 1, strlen(arg.expr) - 2);
if (*arg.msg_types != safe_assert_msg_type::term) {
writeStderr("\nMessage: ");
auto msg_types = arg.msg_types;
bool stop = false;
while (!stop) {
switch (*msg_types++) {
case safe_assert_msg_type::term:
stop = true;
break;
case safe_assert_msg_type::cstr:
writeStderr(va_arg(msg, char const*));
break;
case safe_assert_msg_type::ui64:
writeStderr(buf, to_ascii_decimal(buf, va_arg(msg, uint64_t)));
break;
}
}
}
writeStderr("\nFile: ");
writeStderr(arg.file);
writeStderr("\nLine: ");
writeStderr(buf, to_ascii_decimal(buf, arg.line));
writeStderr("\nFunction: ");
writeStderr(arg.function);
if (error) {
// if errno is set, print the number and the symbolic constant
// the symbolic constant is necessary since actual numbers may vary
// for simplicity, do not attempt to mimic strerror printing descriptions
writeStderr("\nError: ");
writeStderr(buf, to_ascii_decimal(buf, error));
writeStderr(" (");
// the list is not required to be sorted; but the program is about to die
auto const pred = [=](auto const e) { return e.first == error; };
auto const it = std::find_if(std::begin(errors), std::end(errors), pred);
writeStderr(it != std::end(errors) ? it->second : "<unknown>");
writeStderr(")");
}
writeStderr("\n");
flushStderr();
abort();
}
} // namespace
template <>
void safe_assert_terminate<0>(safe_assert_arg const* arg, ...) noexcept {
va_list msg;
va_start(msg, arg);
safe_assert_terminate_v(arg, 0, msg);
va_end(msg);
}
template <>
void safe_assert_terminate<1>(safe_assert_arg const* arg, ...) noexcept {
va_list msg;
va_start(msg, arg);
safe_assert_terminate_v(arg, errno, msg);
va_end(msg);
}
} // namespace detail
} // namespace folly