How to Integrate libfiber with a MySQL Driver Without Modifying the Source Code
libfiber intercepts POSIX socket calls used by the MySQL C client library, allowing you to run standard libmysqlclient code inside coroutines without recompiling or patching the driver.
The iqiyi/libfiber library provides a transparent API hooking mechanism that converts blocking network I/O into fiber-aware operations. Because the official MySQL C client (libmysqlclient) relies exclusively on standard POSIX networking APIs, you can achieve high-concurrency database access by wrapping existing MySQL code in libfiber coroutines. This integration requires zero changes to the MySQL driver source code or build process.
How libfiber Intercepts MySQL I/O Without Code Changes
libfiber works by hooking standard POSIX networking APIs at runtime. When you initialize the library, system calls such as socket, connect, read, write, select, poll, and epoll are automatically replaced with coroutine-aware implementations.
In c/src/hook/socket.c, libfiber provides hooked versions of socket(), connect(), accept(), and close(). The MySQL driver uses these functions to establish and manage TCP connections to the database server. Similarly, c/src/hook/fiber_read.c and c/src/hook/write.c intercept the read() and write() families of calls that libmysqlclient uses to send queries and retrieve results.
Because these hooks operate at the system call layer, the MySQL driver continues to execute its original logic while libfiber transparently converts blocking operations into non-blocking events. The fiber scheduler in c/src/fiber.c then multiplexes these events across the coroutine pool, enabling thousands of concurrent MySQL connections without thread overhead.
Step-by-Step Integration Guide
Initialize the libfiber Scheduler
Before executing any MySQL functions, initialize the fiber runtime. On Linux, call acl_fiber_schedule_init(0) to prepare the kernel-mode event mechanism (epoll/kqueue). On Windows, you must additionally enable WinAPI hooking via winapi_hook().
#include "fiber/lib_fiber.h"
int main(void) {
/* Initialize kernel-mode event handling (epoll on Linux, IOCP on Windows) */
acl_fiber_schedule_init(0);
/* Windows-specific: enable WinAPI hooking */
/* winapi_hook(); */
return 0;
}
Wrap MySQL Operations in a Fiber
Use acl_fiber_create() to spawn a coroutine that executes your standard MySQL client code. Inside the fiber, blocking calls like mysql_real_connect() and mysql_query() become non-blocking yield points. The scheduler automatically switches to other ready fibers while waiting for network events.
static void mysql_fiber(ACL_FIBER *fb, void *ctx) {
MYSQL *conn = mysql_init(NULL);
/* This connect operation will be hooked and yield control */
if (!mysql_real_connect(conn, "127.0.0.1", "user", "pass",
"db", 3306, NULL, 0)) {
/* handle error */
}
/* Query execution also becomes non-blocking */
mysql_query(conn, "SELECT NOW()");
/* process results... */
mysql_close(conn);
}
Start the Event Loop
After creating all fibers, invoke acl_fiber_schedule_with(event_mode) to run the event loop. This function drives the scheduler until all fibers complete.
int main(void) {
acl_fiber_schedule_init(0);
/* Create fiber with 128KB stack */
acl_fiber_create(mysql_fiber, NULL, 128 * 1024);
/* Start the scheduler - blocks until all fibers exit */
acl_fiber_schedule_with(FIBER_EVENT_KERNEL);
return 0;
}
Control Concurrency with Semaphores
To prevent overwhelming the database server, use fiber-aware semaphores defined in c/src/sync/fiber_sem.c. The acl_fiber_sem_wait() and acl_fiber_sem_signal() functions allow you to limit concurrent connections without blocking the entire thread.
ACL_FIBER_SEM *sem = acl_fiber_sem_create(100); /* Max 100 concurrent */
static void limited_mysql_fiber(ACL_FIBER *fb, void *ctx) {
acl_fiber_sem_wait(sem);
/* MySQL operations here */
acl_fiber_sem_signal(sem);
}
Complete C Integration Example
The following example compiles against the standard MySQL client library without modifications. The fiber wrapper in patch.h (typically provided in libfiber examples) supplies the necessary socket wrappers, though the hooks work automatically once the scheduler initializes.
/* Build: gcc -o mysql_fiber mysql_fiber.c -lfiber -lmysqlclient -lpthread -ldl */
#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>
#include "fiber/lib_fiber.h"
static void mysql_fiber(ACL_FIBER *fb, void *ctx)
{
(void) fb;
(void) ctx;
MYSQL *conn = mysql_init(NULL);
if (!conn) {
fprintf(stderr, "mysql_init failed\n");
return;
}
/* Hooked connect - yields instead of blocking */
if (!mysql_real_connect(conn, "127.0.0.1", "user", "passwd",
"testdb", 3306, NULL, 0)) {
fprintf(stderr, "connect error: %s\n", mysql_error(conn));
mysql_close(conn);
return;
}
/* Hooked send/recv operations */
if (mysql_query(conn, "SELECT NOW()")) {
fprintf(stderr, "query error: %s\n", mysql_error(conn));
mysql_close(conn);
return;
}
MYSQL_RES *res = mysql_store_result(conn);
if (res) {
MYSQL_ROW row = mysql_fetch_row(res);
if (row) printf("Server time: %s\n", row[0]);
mysql_free_result(res);
}
mysql_close(conn);
}
int main(void)
{
int event_mode = FIBER_EVENT_KERNEL;
acl_fiber_schedule_init(0);
const size_t stack_size = 128 * 1024;
acl_fiber_create(mysql_fiber, NULL, stack_size);
acl_fiber_schedule_with(event_mode);
return 0;
}
C++ Integration Using the libfiber Wrapper
For C++ applications, libfiber provides a modern wrapper that simplifies fiber creation. The go_fiber.hpp header enables lambda-based coroutine spawning while maintaining the same transparent hooking of MySQL I/O.
// Build: g++ -std=c++11 -o mysql_fiber mysql_fiber.cpp -lfiber -lmysqlclient -lpthread -ldl
#include <mysql.h>
#include <acl-lib/fiber/libfiber.hpp>
#include <acl-lib/fiber/go_fiber.hpp>
static void mysql_task(int id)
{
MYSQL *conn = mysql_init(nullptr);
if (!conn) return;
if (!mysql_real_connect(conn, "127.0.0.1", "user", "passwd",
"testdb", 3306, nullptr, 0)) {
mysql_close(conn);
return;
}
if (mysql_query(conn, "SELECT NOW()")) {
mysql_close(conn);
return;
}
MYSQL_RES *res = mysql_store_result(conn);
if (res) {
MYSQL_ROW row = mysql_fetch_row(res);
if (row) printf("Task %d: Server time: %s\n", id, row[0]);
mysql_free_result(res);
}
mysql_close(conn);
}
int main()
{
int event_mode = FIBER_EVENT_KERNEL;
acl::fiber::schedule_init();
/* Launch multiple MySQL coroutines */
for (int i = 0; i < 10; ++i) {
go[=] { mysql_task(i); };
}
acl::fiber::schedule(event_mode);
return 0;
}
Key Source Files Behind the Hook Mechanism
Understanding the following files in the iqiyi/libfiber repository helps diagnose integration issues and optimize performance:
-
c/src/hook/socket.c– Implements hooked versions ofsocket(),connect(),accept(), andclose(). These are the primary entry points the MySQL driver uses for TCP connection management. -
c/src/hook/fiber_read.candc/src/hook/write.c– Provide fiber-aware implementations ofread(),write(),recv(), andsend(). MySQL's protocol layer depends on these for query transmission and result retrieval. -
c/src/hook/poll.c– Hookspoll(),select(), andepoll_wait()so the MySQL driver's readiness checks integrate with the fiber scheduler's event loop. -
c/src/hook/getaddrinfo.c– Intercepts DNS resolution calls to prevent blocking name lookups from freezing the fiber scheduler. -
c/src/fiber.c– Contains the core scheduler implementation includingacl_fiber_schedule_init()andacl_fiber_schedule_with(). -
c/src/sync/fiber_sem.c– Implements the semaphore API (acl_fiber_sem_create(),acl_fiber_sem_wait(),acl_fiber_sem_signal()) for limiting concurrent database connections.
Summary
- libfiber hooks POSIX socket APIs at runtime, making the MySQL driver's blocking calls yield control to the fiber scheduler automatically.
- No driver modifications required – compile against standard
libmysqlclientand link with-lfiber. - Initialize before use – call
acl_fiber_schedule_init()before creating fibers, thenacl_fiber_schedule_with()to start the event loop. - Wrap MySQL logic in fibers using
acl_fiber_create()(C) or thegolambda wrapper (C++). - Control resource usage with fiber-aware semaphores from
c/src/sync/fiber_sem.cto limit concurrent connections.
Frequently Asked Questions
Does libfiber require recompiling libmysqlclient?
No. libfiber operates through API hooking at the system call layer. The MySQL client library continues to use standard socket(), connect(), and read() calls, but libfiber intercepts these in c/src/hook/socket.c and related files, converting them into non-blocking operations. Link your application with -lfiber alongside -lmysqlclient without changing the MySQL build.
Which system calls does libfiber hook for MySQL compatibility?
According to the source in c/src/hook/, libfiber hooks socket(), connect(), accept(), close(), read(), write(), poll(), select(), epoll_wait(), and getaddrinfo(). These cover all network I/O paths used by libmysqlclient for connection establishment, query execution, and result fetching.
How does libfiber handle DNS resolution in MySQL connections?
The file c/src/hook/getaddrinfo.c provides a hooked implementation of getaddrinfo() and related name resolution functions. When mysql_real_connect() performs a DNS lookup, the hooked version registers the resolution request with the fiber scheduler, yielding control until the name lookup completes, preventing the entire thread from blocking.
Can I limit concurrent MySQL connections when using libfiber?
Yes. Use the semaphore API implemented in c/src/sync/fiber_sem.c. Create a semaphore with acl_fiber_sem_create(max_connections), then wrap your MySQL connection logic with acl_fiber_sem_wait() before connecting and acl_fiber_sem_signal() after disconnecting. This limits simultaneous database connections while keeping the fiber scheduler responsive.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →