Skip to content

Commit 399071b

Browse files
committed
feat: improve FreeBSD platform support
Add comprehensive FreeBSD support to brpc, building on the existing partial FreeBSD code already present in the codebase. CMakeLists.txt: - Add NO_PTHREAD_MUTEX_HOOK on FreeBSD to prevent static init deadlock caused by bthread's pthread_mutex_lock interposition conflicting with libc++ ios_base::Init during early process initialization - Add -lexecinfo for backtrace support - Add FreeBSD-specific source files (platform_thread_freebsd.cc, sys_string_conversions_posix.cc) Source changes (all guarded by OS_FREEBSD, no impact on Linux/macOS): - butil/compat.h: Add FreeBSD kqueue path and pthread_getthreadid_np() - butil/process_util.cc: FreeBSD ReadCommandLine via ps (like macOS) - butil/fd_utility.cpp: kqueue fd handling - butil/logging.cc: Rename FLAGS_v/vmodule/minloglevel to avoid gflags duplicate registration with system glog on FreeBSD - brpc/socket.cpp: FreeBSD TCP_INFO support - bthread/: FreeBSD futex emulation, context switching, fd handling - bvar/default_variables.cpp: FreeBSD /proc fallback Most changes piggyback on existing macOS/Darwin code paths since both use kqueue. The NO_PTHREAD_MUTEX_HOOK fix is critical — without it, any FreeBSD application linking brpc will deadlock during startup.
1 parent 5a2466a commit 399071b

22 files changed

Lines changed: 168 additions & 37 deletions

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ endif()
147147
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__=__unused__ -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DBRPC_REVISION=\\\"${BRPC_REVISION}\\\" -D__STRICT_ANSI__")
148148
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} ${DEBUG_SYMBOL} ${THRIFT_CPP_FLAG}")
149149
set(CMAKE_CXX_FLAGS "${CMAKE_CPP_FLAGS} ${CMAKE_CXX_FLAGS} -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer")
150+
151+
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
152+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_PTHREAD_MUTEX_HOOK")
153+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_PTHREAD_MUTEX_HOOK")
154+
endif()
150155
set(CMAKE_C_FLAGS "${CMAKE_CPP_FLAGS} -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-unused-parameter -fno-omit-frame-pointer")
151156

152157
macro(use_cxx11)
@@ -342,6 +347,9 @@ endif()
342347
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
343348
set(DYNAMIC_LIB ${DYNAMIC_LIB} rt)
344349
set(BRPC_PRIVATE_LIBS "${BRPC_PRIVATE_LIBS} -lrt")
350+
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
351+
set(DYNAMIC_LIB ${DYNAMIC_LIB} execinfo)
352+
set(BRPC_PRIVATE_LIBS "${BRPC_PRIVATE_LIBS} -lexecinfo")
345353
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
346354
set(DYNAMIC_LIB ${DYNAMIC_LIB}
347355
pthread
@@ -500,6 +508,10 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
500508
${PROJECT_SOURCE_DIR}/src/butil/strings/sys_string_conversions_mac.mm
501509
${PROJECT_SOURCE_DIR}/src/butil/time/time_mac.cc
502510
${PROJECT_SOURCE_DIR}/src/butil/mac/scoped_mach_port.cc)
511+
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
512+
set(BUTIL_SOURCES ${BUTIL_SOURCES}
513+
${PROJECT_SOURCE_DIR}/src/butil/threading/platform_thread_freebsd.cc
514+
${PROJECT_SOURCE_DIR}/src/butil/strings/sys_string_conversions_posix.cc)
503515
endif()
504516

505517
file(GLOB_RECURSE BVAR_SOURCES "${PROJECT_SOURCE_DIR}/src/bvar/*.cpp")

src/brpc/controller.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1578,7 +1578,7 @@ void Controller::CallAfterRpcResp(const google::protobuf::Message* req, const go
15781578
}
15791579
}
15801580

1581-
#if defined(OS_MACOSX)
1581+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
15821582
typedef sig_t SignalHandler;
15831583
#else
15841584
typedef sighandler_t SignalHandler;

src/brpc/event_dispatcher.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void IOEventData::BeforeRecycled() {
101101

102102
#if defined(OS_LINUX)
103103
#include "brpc/event_dispatcher_epoll.cpp"
104-
#elif defined(OS_MACOSX)
104+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
105105
#include "brpc/event_dispatcher_kqueue.cpp"
106106
#else
107107
#error Not implemented

src/brpc/policy/domain_naming_service.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ int DomainNamingService::GetServers(const char* dns_name,
106106

107107
}
108108

109-
#if defined(OS_MACOSX)
109+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
110110
_aux_buf_len = 0; // suppress unused warning
111111
// gethostbyname on MAC is thread-safe (with current usage) since the
112112
// returned hostent is TLS. Check following link for the ref:

src/brpc/socket.cpp

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
#include "brpc/periodic_task.h"
5252
#include "brpc/details/health_check.h"
5353
#include "brpc/transport_factory.h"
54-
#if defined(OS_MACOSX)
54+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
5555
#include <sys/event.h>
5656
#endif
5757

@@ -676,6 +676,30 @@ void Socket::SetSocketOptions(int fd) {
676676
PLOG(ERROR) << "Fail to set keepcnt of fd=" << fd;
677677
}
678678
}
679+
#elif defined(OS_FREEBSD)
680+
if (_keepalive_options->keepalive_idle_s > 0) {
681+
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
682+
&_keepalive_options->keepalive_idle_s,
683+
sizeof(_keepalive_options->keepalive_idle_s)) != 0) {
684+
PLOG(ERROR) << "Fail to set keepidle of fd=" << fd;
685+
}
686+
}
687+
688+
if (_keepalive_options->keepalive_interval_s > 0) {
689+
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
690+
&_keepalive_options->keepalive_interval_s,
691+
sizeof(_keepalive_options->keepalive_interval_s)) != 0) {
692+
PLOG(ERROR) << "Fail to set keepintvl of fd=" << fd;
693+
}
694+
}
695+
696+
if (_keepalive_options->keepalive_count > 0) {
697+
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
698+
&_keepalive_options->keepalive_count,
699+
sizeof(_keepalive_options->keepalive_count)) != 0) {
700+
PLOG(ERROR) << "Fail to set keepcnt of fd=" << fd;
701+
}
702+
}
679703
#elif defined(OS_MACOSX)
680704
if (_keepalive_options->keepalive_idle_s > 0) {
681705
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
@@ -2006,7 +2030,7 @@ int Socket::SSLHandshake(int fd, bool server_mode) {
20062030
case SSL_ERROR_WANT_READ:
20072031
#if defined(OS_LINUX)
20082032
if (bthread_fd_wait(fd, EPOLLIN) != 0) {
2009-
#elif defined(OS_MACOSX)
2033+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
20102034
if (bthread_fd_wait(fd, EVFILT_READ) != 0) {
20112035
#endif
20122036
return -1;
@@ -2016,7 +2040,7 @@ int Socket::SSLHandshake(int fd, bool server_mode) {
20162040
case SSL_ERROR_WANT_WRITE:
20172041
#if defined(OS_LINUX)
20182042
if (bthread_fd_wait(fd, EPOLLOUT) != 0) {
2019-
#elif defined(OS_MACOSX)
2043+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
20202044
if (bthread_fd_wait(fd, EVFILT_WRITE) != 0) {
20212045
#endif
20222046
return -1;
@@ -2183,7 +2207,7 @@ int Socket::OnInputEvent(void* user_data, uint32_t events,
21832207
if (s->fd() < 0) {
21842208
#if defined(OS_LINUX)
21852209
CHECK(!(events & EPOLLIN)) << "epoll_events=" << events;
2186-
#elif defined(OS_MACOSX)
2210+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
21872211
CHECK((short)events != EVFILT_READ) << "kqueue filter=" << events;
21882212
#endif
21892213
return -1;
@@ -2406,7 +2430,11 @@ void Socket::DebugSocket(std::ostream& os, SocketId id) {
24062430
{
24072431
int keepidle = 0;
24082432
socklen_t len = sizeof(keepidle);
2409-
#if defined(OS_MACOSX)
2433+
#if defined(OS_FREEBSD)
2434+
if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, &len) == 0) {
2435+
os << "\ntcp_keepalive_time=" << keepidle;
2436+
}
2437+
#elif defined(OS_MACOSX)
24102438
if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &keepidle, &len) == 0) {
24112439
os << "\ntcp_keepalive_time=" << keepidle;
24122440
}
@@ -2420,7 +2448,7 @@ void Socket::DebugSocket(std::ostream& os, SocketId id) {
24202448
{
24212449
int keepintvl = 0;
24222450
socklen_t len = sizeof(keepintvl);
2423-
#if defined(OS_MACOSX)
2451+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
24242452
if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, &len) == 0) {
24252453
os << "\ntcp_keepalive_intvl=" << keepintvl;
24262454
}
@@ -2434,7 +2462,7 @@ void Socket::DebugSocket(std::ostream& os, SocketId id) {
24342462
{
24352463
int keepcnt = 0;
24362464
socklen_t len = sizeof(keepcnt);
2437-
#if defined(OS_MACOSX)
2465+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
24382466
if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, &len) == 0) {
24392467
os << "\ntcp_keepalive_probes=" << keepcnt;
24402468
}
@@ -2455,7 +2483,22 @@ void Socket::DebugSocket(std::ostream& os, SocketId id) {
24552483
}
24562484
#endif
24572485

2458-
#if defined(OS_MACOSX)
2486+
#if defined(OS_FREEBSD)
2487+
struct tcp_info ti;
2488+
socklen_t len = sizeof(ti);
2489+
if (fd >= 0 && getsockopt(fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == 0) {
2490+
os << "\ntcpi={\n state=" << (uint32_t)ti.tcpi_state
2491+
<< "\n snd_wscale=" << (uint32_t)ti.tcpi_snd_wscale
2492+
<< "\n rcv_wscale=" << (uint32_t)ti.tcpi_rcv_wscale
2493+
<< "\n options=" << (uint32_t)ti.tcpi_options
2494+
<< "\n rto=" << ti.tcpi_rto
2495+
<< "\n snd_mss=" << ti.tcpi_snd_mss
2496+
<< "\n snd_ssthresh=" << ti.tcpi_snd_ssthresh
2497+
<< "\n snd_cwnd=" << ti.tcpi_snd_cwnd
2498+
<< "\n rcv_space=" << ti.tcpi_rcv_space
2499+
<< "\n}";
2500+
}
2501+
#elif defined(OS_MACOSX)
24592502
struct tcp_connection_info ti;
24602503
socklen_t len = sizeof(ti);
24612504
if (fd >= 0 && getsockopt(fd, IPPROTO_TCP, TCP_CONNECTION_INFO, &ti, &len) == 0) {

src/bthread/context.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@
5858
#define BTHREAD_CONTEXT_CALL_CONVENTION __cdecl
5959
#endif
6060

61+
#elif defined(__FreeBSD__)
62+
#ifdef __x86_64__
63+
#define BTHREAD_CONTEXT_PLATFORM_linux_x86_64
64+
#define BTHREAD_CONTEXT_CALL_CONVENTION
65+
#elif __aarch64__
66+
#define BTHREAD_CONTEXT_PLATFORM_linux_arm64
67+
#define BTHREAD_CONTEXT_CALL_CONVENTION
68+
#endif
69+
6170
#elif defined(__APPLE__) && defined(__MACH__)
6271
#if defined (__i386__)
6372
#define BTHREAD_CONTEXT_PLATFORM_apple_i386

src/bthread/errno.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ extern int *__errno_location() __attribute__((__const__));
3535
int *bthread_errno_location() {
3636
return __errno_location();
3737
}
38-
#elif defined(OS_MACOSX)
38+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
3939

4040
extern int * __error(void);
4141

src/bthread/fd.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include "butil/compat.h"
2323
#include <new> // std::nothrow
2424
#include <sys/poll.h> // poll()
25-
#if defined(OS_MACOSX)
25+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
2626
#include <sys/types.h> // struct kevent
2727
#include <sys/event.h> // kevent(), kqueue()
2828
#endif
@@ -133,7 +133,7 @@ class EpollThread {
133133
}
134134
#if defined(OS_LINUX)
135135
_epfd = epoll_create(epoll_size);
136-
#elif defined(OS_MACOSX)
136+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
137137
_epfd = kqueue();
138138
#endif
139139
_start_mutex.unlock();
@@ -181,7 +181,7 @@ class EpollThread {
181181
epoll_event evt = { EPOLLOUT, { NULL } };
182182
if (epoll_ctl(saved_epfd, EPOLL_CTL_ADD,
183183
closing_epoll_pipe[1], &evt) < 0) {
184-
#elif defined(OS_MACOSX)
184+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
185185
struct kevent kqueue_event;
186186
EV_SET(&kqueue_event, closing_epoll_pipe[1], EVFILT_WRITE, EV_ADD | EV_ENABLE,
187187
0, 0, NULL);
@@ -257,7 +257,7 @@ class EpollThread {
257257
return -1;
258258
}
259259
# endif
260-
#elif defined(OS_MACOSX)
260+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
261261
struct kevent kqueue_event;
262262
EV_SET(&kqueue_event, fd, events, EV_ADD | EV_ENABLE | EV_ONESHOT,
263263
0, 0, butex);
@@ -299,7 +299,7 @@ class EpollThread {
299299
}
300300
#if defined(OS_LINUX)
301301
epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, NULL);
302-
#elif defined(OS_MACOSX)
302+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
303303
struct kevent evt;
304304
EV_SET(&evt, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
305305
kevent(_epfd, &evt, 1, NULL, 0, NULL);
@@ -325,7 +325,7 @@ class EpollThread {
325325
const size_t MAX_EVENTS = 32;
326326
#if defined(OS_LINUX)
327327
epoll_event* e = new (std::nothrow) epoll_event[MAX_EVENTS];
328-
#elif defined(OS_MACOSX)
328+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
329329
typedef struct kevent KEVENT;
330330
struct kevent* e = new (std::nothrow) KEVENT[MAX_EVENTS];
331331
#endif
@@ -343,7 +343,7 @@ class EpollThread {
343343
const int epfd = _epfd;
344344
#if defined(OS_LINUX)
345345
const int n = epoll_wait(epfd, e, MAX_EVENTS, -1);
346-
#elif defined(OS_MACOSX)
346+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
347347
const int n = kevent(epfd, NULL, 0, e, MAX_EVENTS, NULL);
348348
#endif
349349
if (_stop) {
@@ -383,7 +383,7 @@ class EpollThread {
383383
EpollButex* butex = pbutex ?
384384
pbutex->load(butil::memory_order_consume) : NULL;
385385
# endif
386-
#elif defined(OS_MACOSX)
386+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
387387
EpollButex* butex = static_cast<EpollButex*>(e[i].udata);
388388
#endif
389389
if (butex != NULL && butex != CLOSING_GUARD) {
@@ -495,7 +495,7 @@ int bthread_connect(int sockfd, const sockaddr* serv_addr,
495495
}
496496
#if defined(OS_LINUX)
497497
if (bthread_fd_wait(sockfd, EPOLLOUT) < 0) {
498-
#elif defined(OS_MACOSX)
498+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
499499
if (bthread_fd_wait(sockfd, EVFILT_WRITE) < 0) {
500500
#endif
501501
return -1;
@@ -531,7 +531,7 @@ int bthread_timed_connect(int sockfd, const struct sockaddr* serv_addr,
531531
}
532532
#if defined(OS_LINUX)
533533
if (bthread_fd_timedwait(sockfd, EPOLLOUT, abstime) < 0) {
534-
#elif defined(OS_MACOSX)
534+
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
535535
if (bthread_fd_timedwait(sockfd, EVFILT_WRITE, abstime) < 0) {
536536
#endif
537537
return -1;

src/bthread/mutex.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,12 @@ static void init_sys_mutex_lock() {
477477
sys_pthread_mutex_lock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_lock");
478478
sys_pthread_mutex_trylock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_trylock");
479479
sys_pthread_mutex_unlock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_unlock");
480+
#elif defined(OS_FREEBSD)
481+
sys_pthread_mutex_init = (MutexInitOp)dlsym(RTLD_NEXT, "pthread_mutex_init");
482+
sys_pthread_mutex_destroy = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_destroy");
483+
sys_pthread_mutex_lock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_lock");
484+
sys_pthread_mutex_trylock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_trylock");
485+
sys_pthread_mutex_unlock = (MutexOp)dlsym(RTLD_NEXT, "pthread_mutex_unlock");
480486
#endif
481487
}
482488

src/bthread/sys_futex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include <pthread.h>
2626
#include <unordered_map>
2727

28-
#if defined(OS_MACOSX)
28+
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
2929

3030
namespace bthread {
3131

0 commit comments

Comments
 (0)