mirror of
https://github.com/gabime/spdlog.git
synced 2025-10-02 11:29:01 +08:00
merge with v1.x
This commit is contained in:
@@ -23,16 +23,9 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX // prevent windows redefining min/max
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <io.h> // _get_osfhandle and _isatty support
|
||||
#include <process.h> // _get_pid support
|
||||
#include <windows.h>
|
||||
#include <spdlog/details/windows_include.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <share.h>
|
||||
@@ -126,23 +119,6 @@ SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT
|
||||
return gmtime(now_t);
|
||||
}
|
||||
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
SPDLOG_INLINE void prevent_child_fd(FILE *f)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(f)));
|
||||
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
|
||||
SPDLOG_THROW(spdlog_ex("SetHandleInformation failed", errno));
|
||||
#else
|
||||
auto fd = ::fileno(f);
|
||||
if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("fcntl with FD_CLOEXEC failed", errno));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // SPDLOG_PREVENT_CHILD_FD
|
||||
|
||||
// fopen_s on non windows for writing
|
||||
SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode)
|
||||
{
|
||||
@@ -152,17 +128,35 @@ SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename
|
||||
#else
|
||||
*fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
|
||||
#endif
|
||||
#else // unix
|
||||
*fp = ::fopen((filename.c_str()), mode.c_str());
|
||||
#endif
|
||||
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
// prevent child processes from inheriting log file descriptors
|
||||
#if defined(SPDLOG_PREVENT_CHILD_FD)
|
||||
if (*fp != nullptr)
|
||||
{
|
||||
prevent_child_fd(*fp);
|
||||
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(*fp)));
|
||||
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
|
||||
{
|
||||
:fclose(*fp);
|
||||
*fp = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else // unix
|
||||
#if defined(SPDLOG_PREVENT_CHILD_FD)
|
||||
const int mode_flag = mode == SPDLOG_FILENAME_T("ab") ? O_APPEND : O_TRUNC;
|
||||
const int fd = ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644));
|
||||
if (fd == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*fp = ::fdopen(fd, mode.c_str());
|
||||
if (*fp == nullptr)
|
||||
{
|
||||
::close(fd);
|
||||
}
|
||||
#else
|
||||
*fp = ::fopen((filename.c_str()), mode.c_str());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return *fp == nullptr;
|
||||
}
|
||||
|
||||
|
@@ -38,10 +38,6 @@ static const char folder_sep = '\\';
|
||||
SPDLOG_CONSTEXPR static const char folder_sep = '/';
|
||||
#endif
|
||||
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
void prevent_child_fd(FILE *f);
|
||||
#endif
|
||||
|
||||
// fopen_s on non windows for writing
|
||||
bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
|
||||
|
||||
|
149
include/spdlog/details/tcp_client.h
Normal file
149
include/spdlog/details/tcp_client.h
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#error tcp_client not supported under windows yet
|
||||
#endif
|
||||
|
||||
// tcp client helper
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
class tcp_client
|
||||
{
|
||||
int socket_ = -1;
|
||||
|
||||
public:
|
||||
bool is_connected() const
|
||||
{
|
||||
return socket_ != -1;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (is_connected())
|
||||
{
|
||||
::close(socket_);
|
||||
socket_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int fd() const
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
|
||||
~tcp_client()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
// try to connect or throw on failure
|
||||
void connect(const std::string &host, int port)
|
||||
{
|
||||
close();
|
||||
spdlog::info("Connecting..");
|
||||
struct addrinfo hints{};
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET; // IPv4
|
||||
hints.ai_socktype = SOCK_STREAM; // TCP
|
||||
hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value
|
||||
hints.ai_protocol = 0;
|
||||
|
||||
auto port_str = std::to_string(port);
|
||||
struct addrinfo *addrinfo_result;
|
||||
auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);
|
||||
if (rv != 0)
|
||||
{
|
||||
auto msg = fmt::format("::getaddrinfo failed: {}", gai_strerror(rv));
|
||||
SPDLOG_THROW(spdlog::spdlog_ex(msg));
|
||||
}
|
||||
|
||||
// Try each address until we successfully connect(2).
|
||||
int last_errno = 0;
|
||||
for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)
|
||||
{
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
int const flags = SOCK_CLOEXEC;
|
||||
#else
|
||||
int const flags = 0;
|
||||
#endif
|
||||
socket_ = ::socket(rp->ai_family, rp->ai_socktype | flags, rp->ai_protocol);
|
||||
if (socket_ == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
continue;
|
||||
}
|
||||
rv = ::connect(socket_, rp->ai_addr, rp->ai_addrlen);
|
||||
if (rv == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_errno = errno;
|
||||
::close(socket_);
|
||||
socket_ = -1;
|
||||
}
|
||||
}
|
||||
::freeaddrinfo(addrinfo_result);
|
||||
if (socket_ == -1)
|
||||
{
|
||||
SPDLOG_THROW(spdlog::spdlog_ex("::connect failed", last_errno));
|
||||
}
|
||||
|
||||
// set TCP_NODELAY
|
||||
int enable_flag = 1;
|
||||
::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (char *)&enable_flag, sizeof(enable_flag));
|
||||
|
||||
// prevent sigpipe on systems where MSG_NOSIGNAL is not available
|
||||
#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
|
||||
::setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, (char *)&enable_flag, sizeof(enable_flag));
|
||||
#endif
|
||||
|
||||
#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
|
||||
#error "tcp_sink would raise SIGPIPE since niether SO_NOSIGPIPE nor MSG_NOSIGNAL are available"
|
||||
#endif
|
||||
}
|
||||
|
||||
// Send exactly n_bytes of the given data.
|
||||
// On error close the connection and throw.
|
||||
void send(const char *data, size_t n_bytes)
|
||||
{
|
||||
size_t bytes_sent = 0;
|
||||
while (bytes_sent < n_bytes)
|
||||
{
|
||||
#if defined(MSG_NOSIGNAL)
|
||||
const int send_flags = MSG_NOSIGNAL;
|
||||
#else
|
||||
const int send_flags = 0;
|
||||
#endif
|
||||
auto write_result = ::send(socket_, data + bytes_sent, n_bytes - bytes_sent, send_flags);
|
||||
if (write_result < 0)
|
||||
{
|
||||
close();
|
||||
SPDLOG_THROW(spdlog::spdlog_ex("write(2) failed", errno));
|
||||
}
|
||||
|
||||
if (write_result == 0) // (probably should not happen but in any case..)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes_sent += static_cast<size_t>(write_result);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
11
include/spdlog/details/windows_include.h
Normal file
11
include/spdlog/details/windows_include.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX // prevent windows redefining min/max
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
Reference in New Issue
Block a user