diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4fc6339b78..463dbf0a1e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -43,14 +43,21 @@ jobs: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) || (github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true') + strategy: + matrix: + select_impl: ['select', 'poll'] steps: - name: checkout uses: actions/checkout@v4 - name: install libraries run: sudo apt-get update && sudo apt-get install -y libbrotli-dev libcurl4-openssl-dev - name: build and run tests + env: + SELECT_IMPL: ${{ matrix.select_impl }} run: cd test && make - name: run fuzz test target + env: + SELECT_IMPL: ${{ matrix.select_impl }} run: cd test && make fuzz_test macos: @@ -60,12 +67,19 @@ jobs: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) || (github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true') + strategy: + matrix: + select_impl: ['select', 'poll'] steps: - name: checkout uses: actions/checkout@v4 - name: build and run tests + env: + SELECT_IMPL: ${{ matrix.select_impl }} run: cd test && make - name: run fuzz test target + env: + SELECT_IMPL: ${{ matrix.select_impl }} run: cd test && make fuzz_test windows: @@ -75,6 +89,9 @@ jobs: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) || (github.event_name == 'workflow_dispatch' && github.event.inputs.test_windows == 'true') + strategy: + matrix: + select_impl: ['select', 'poll'] steps: - name: Prepare Git for Checkout on Windows run: | @@ -96,16 +113,33 @@ jobs: choco install openssl - name: Configure CMake with SSL - run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DHTTPLIB_TEST=ON -DHTTPLIB_REQUIRE_OPENSSL=ON -DHTTPLIB_REQUIRE_ZLIB=ON -DHTTPLIB_REQUIRE_BROTLI=ON + run: > + cmake -B build -S . + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake + -DHTTPLIB_TEST=ON + -DHTTPLIB_REQUIRE_OPENSSL=ON + -DHTTPLIB_REQUIRE_ZLIB=ON + -DHTTPLIB_REQUIRE_BROTLI=ON + -DHTTPLIB_USE_SELECT=${{ matrix.select_impl == 'select' && 'ON' || 'OFF' }} - name: Build with with SSL - run: cmake --build build --config Release + run: cmake --build build --config Release -- /v:m /clp:ShowCommandLine /nologo - name: Run tests with SSL run: ctest --output-on-failure --test-dir build -C Release - name: Configure CMake without SSL - run: cmake -B build-no-ssl -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DHTTPLIB_TEST=ON -DHTTPLIB_REQUIRE_OPENSSL=OFF -DHTTPLIB_REQUIRE_ZLIB=ON -DHTTPLIB_REQUIRE_BROTLI=ON + run: > + cmake -B build-no-ssl -S . + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + -DHTTPLIB_TEST=ON + -DHTTPLIB_REQUIRE_OPENSSL=OFF + -DHTTPLIB_REQUIRE_ZLIB=ON + -DHTTPLIB_REQUIRE_BROTLI=ON + -DHTTPLIB_USE_SELECT=${{ matrix.select_impl == 'select' && 'ON' || 'OFF' }} - name: Build without SSL - run: cmake --build build-no-ssl --config Release + run: cmake --build build-no-ssl --config Release -- /v:m /clp:ShowCommandLine /nologo - name: Run tests without SSL run: ctest --output-on-failure --test-dir build-no-ssl -C Release env: diff --git a/CMakeLists.txt b/CMakeLists.txt index 61419c63a8..4ffa31f2c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ * HTTPLIB_REQUIRE_ZLIB (default off) * HTTPLIB_REQUIRE_BROTLI (default off) * HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on) + * HTTPLIB_USE_SELECT (default off) choose between select() and poll() * HTTPLIB_COMPILE (default off) * HTTPLIB_INSTALL (default on) * HTTPLIB_TEST (default off) @@ -46,6 +47,7 @@ * HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled. * HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled. * HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled. + * HTTPLIB_IS_USING_SELECT - a bool for if select() is used instead of poll(). * HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only. * HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include). * HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so). @@ -101,6 +103,7 @@ option(HTTPLIB_TEST "Enables testing and builds tests" OFF) option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF) option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON) option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON) +option(HTTPLIB_USE_SELECT "Uses select() instead of poll()." OFF) # Defaults to static library option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF) if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE) @@ -112,6 +115,7 @@ endif() # Set some variables that are used in-tree and while building based on our options set(HTTPLIB_IS_COMPILED ${HTTPLIB_COMPILE}) set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN ${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN}) +set(HTTPLIB_IS_USING_SELECT ${HTTPLIB_USE_SELECT}) # Threads needed for on some systems, and for on Linux set(THREADS_PREFER_PTHREAD_FLAG TRUE) @@ -238,6 +242,7 @@ target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC} $<$:CPPHTTPLIB_ZLIB_SUPPORT> $<$:CPPHTTPLIB_OPENSSL_SUPPORT> $<$,$,$>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN> + $<$:CPPHTTPLIB_USE_SELECT> ) # CMake configuration files installation directory diff --git a/Dockerfile b/Dockerfile index 654845b2ac..4abae1793e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM yhirose4dockerhub/ubuntu-builder AS builder WORKDIR /build COPY httplib.h . COPY docker/main.cc . -RUN g++ -std=c++23 -static -o server -O2 -I. -DCPPHTTPLIB_USE_POLL main.cc && strip server +RUN g++ -std=c++23 -static -o server -O2 -I. main.cc && strip server FROM scratch COPY --from=builder /build/server /server diff --git a/README.md b/README.md index fc4b537f94..2a6cbfab6d 100644 --- a/README.md +++ b/README.md @@ -872,10 +872,10 @@ res->body; // Compressed data ``` -Use `poll` instead of `select` ------------------------------- +Use `select()` instead of `poll()` +---------------------------------- -`select` system call is used as default since it's more widely supported. If you want to let cpp-httplib use `poll` instead, you can do so with `CPPHTTPLIB_USE_POLL`. +cpp-httplib defaults to the widely supported `poll()` system call. If your OS lacks support for `poll()`, define `CPPHTTPLIB_USE_SELECT` to use `select()` instead. Unix Domain Socket Support -------------------------- diff --git a/httplib.h b/httplib.h index 742455a8b3..632dc35851 100644 --- a/httplib.h +++ b/httplib.h @@ -145,6 +145,12 @@ #define CPPHTTPLIB_LISTEN_BACKLOG 5 #endif +#if !defined(CPPHTTPLIB_USE_POLL) && !defined(CPPHTTPLIB_USE_SELECT) +#define CPPHTTPLIB_USE_POLL +#elif defined(CPPHTTPLIB_USE_POLL) && defined(CPPHTTPLIB_USE_SELECT) +#error "CPPHTTPLIB_USE_POLL and CPPHTTPLIB_USE_SELECT are mutually exclusive" +#endif + /* * Headers */ diff --git a/test/Makefile b/test/Makefile index 348bfa2bb8..1089dc6e7e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,10 @@ CXX = clang++ CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow # -fno-exceptions -DCPPHTTPLIB_NO_EXCEPTIONS -fsanitize=address +ifeq ($(SELECT_IMPL),select) + CXXFLAGS += -DCPPHTTPLIB_USE_SELECT +endif + PREFIX ?= $(shell brew --prefix) OPENSSL_DIR = $(PREFIX)/opt/openssl@3