Merge branch 'release-2.1.12-stable-pull' into patches-2.1

PR: https://github.com/libevent/libevent/pull/1045

* release-2.1.12-stable-pull:
  Update ChangeLog
  ci/linux: create dist artifact only if dist archive was built
  Merge branch 'fix-signal-leak'
  test: fix leak in dns/getaddrinfo_cancel_stress
  test: fix UB in evbuffer/empty_reference_prepend_buffer
  ci: set build type to debug with sanitizers
  test: really disable bufferevent_pair_release_lock under ASAN (and fix gcc)
  test-closed: fix leak
  test-export: adjust libevent version
  cmake: set rpath for libraries on linux
  test-export: compatible with all versions of visual studio
  Bump version to 2.1.12-stable (w/o ABI breakage)
  ci: run ABI for release-*-pull branches too
  Purge travis-ci config
  Purge appveyor config
  Bump ChangeLog for 2.1.12
  Update AUTHORS for 2.1.12
  Backport github actions to 2.1
  test: add getaddrinfo(AI_ADDRCONFIG) test (off by default)
  build: remove duplicate -Wredundant-decls
  test: fix memory leaks for https (add BEV_OPT_CLOSE_ON_FREE)
  test: "fix" (with a quirk) leak in ssl/bufferevent_wm (w/o defer callbacks)
  test: disable bufferevent/bufferevent_pair_release_lock under ASAN (too tricky)
  test: detect test failures if atexit handler calls _exit(!0) (sanitizers)
  Make all classes Entry, Struct, etc) new-style classes
  buffer: do not pass NULL to memcpy() from evbuffer_pullup()
  test: do not pass NULL to memcmp() in evbuffer_datacmp() helper
  http: fix undefined-shift in EVUTIL_IS*_ helpers
  Check error code of evhttp_add_header_internal() in evhttp_parse_query_impl()
  cmake: avoid problems from use of CMAKE_USE_PTHREADS_INIT
  test/regress_testutils: use inet_addr()
  remove FindGit.cmake, improve `git describe` command
  checkpatch.sh: fix clang-format-diff usage
  checkpatch.sh: fix usage
  Fix clang-format-diff usage
  variable redefinition in win32_dispatch
  test: http/autofree_connection cleanup
  http: fix EVHTTP_CON_AUTOFREE in case of timeout (and some else)
  test: cleanup http/autofree_connection
  test: fix http/autofree_connection
  evdns: Add additional validation for values of dns options
  test: Fix test_simpleclose for Windows platform
  abi-check: abi-monitor 1.10 does not support -make -j8 (1.12 supports though)
  Add API/ABI checker (using LVC)
  Update list of cmake files for autotools dist archive
  Pass --quiet to the event_rcpgen.py (autotools already does this)
  There is typo in GetAdaptersAddresses windows library. It should be iphlpapi.dll
  Support EV_CLOSED on linux for poll(2)
  Fix EV_CLOSED detection/reporting (epoll only)
  Merge branch 'EV_CLOSED-and-EV_ET-fixes'
  bufferevent: allow setting priority on socket and openssl type
  cmake: set a default value for LIBEVENT_STATIC_LINK
  evutil_time: improve evutil_gettimeofday on Windows
  bench: Allow backend method selection
  cmake: missing test-closed binary
  Merge branch 'event_rpcgen.py-cleanup'
  cmake: replace CheckFunctionExists with CheckSymbolExists
  LibeventConfig.cmake: restore CMAKE_FIND_LIBRARY_SUFFIXES and LIBEVENT_STATIC_LINK default
  cmake: fix getaddrinfo checking error
  cmake: remove CheckFunctionExistsEx
  autoconf: fix getaddrinfo checking errors on mingw
  test-time: do not use deprecated API
  test-time: enable debug mode if EVENT_DEBUG_LOGGING_ALL env set
  increase segment refcnt only if evbuffer_add_file_segment() succeeds
  evdns: fix a crash when evdns_base with waiting requests is freed
  event_base_once: fix potential null pointer threat
  test-ratelim: add missing free
  Do not use shared global structures on CYGWIN
  test: move thread into realtime class even on EVENT__DISABLE_THREAD_SUPPORT
  test: fix compilation without thread support (EVENT__DISABLE_THREAD_SUPPORT=ON)
  test: fix bufferevent/bufferevent_connect_fail_eventcb* under osx/freebsd
  test: fix dst thread in move_pthread_to_realtime_scheduling_class (osx)
  test: fix compilation under win32 (rearrange thread_setup() code)
  test: use THREAD_* wrappers over pthread* in del_notify
  Merge branch 'osx-clock'
  cmake: do not print used method (EVENT_SHOW_METHOD) while running tests
  cmake: run regress test quietly like autotools (makes CI logs cleaner)
  Merge branch 'http-connect'
  http: do not assume body for CONNECT
  Added uninstall target check to cmakelists
  Fix compilation without OPENSSL_API_COMPAT
  evutil_time: Implements usleep() using wait funtion on Windows
  Initialize variable to 0 replace use memset function in sample/hello-world.c
  cmake: set CMAKE_{RUNTIME,LIBRARY,ARCHIVE}_OUTPUT_DIRECTORY they are not defined
  cmake: use CMAKE_LIBRARY_OUTPUT_DIRECTORY for the final shared library symlink
  test-ratelim: calculate timers bias (for slow CPUs) to avoid false-positive
  mailmap: add name/email aliases for yuangongji (name and email)
  cmake: test for find_package()
  cmake: improve package config file
  Link with iphlpapi only on windows
  Parse IPv6 scope IDs.
  Relax bufferevent_connect_hostname_emfile
  autotools: fails build when need but can not find openssl
  cmake: eliminate duplicate installation of public headers
  append to CMAKE_MODULE_PATH
  Do not use sysctl.h on linux (it had been deprecated)
  sample/https-client: link crypt32 explicitly when build with mingw-w64
  Fix compat with NetBSD >= 10
  Avoid transforming base C_FLAGS set deliberately
  tinytest: support timeout on Windows
  Merge branch 'upstream/pr/899' (evbuffer_freeze testcase enhancements)
  evbuffer_add_file: fix freeing of segment in the error path
  evutil_time: detect and use _gmtime64_s()/_gmtime64()
  http: rename bind_socket_ai() to create_bind_socket_nonblock()
  https-client: load certificates from the system cert store on Windows
  Fix checking return value of the evdns_base_resolv_conf_parse()
  cmake: fix getrandom() detection
  arc4random: replace sysctl() with getrandom (on linux)
  Upgrade autoconf (after upgrading minimum required to 2.67)
  Revert "Warn if forked from the event loop during event_reinit()"
  eliminate some C4267 warnings in Windows
  autotools: attach doxygen target into all target
  cmake: attach doxygen target into all target
  Fix memory corruption in EV_CLOSURE_EVENT_FINALIZE with debug enabled
  test: prevent duplicate event_enable_debug_mode() for TT_ENABLE_DEBUG_MODE
  test: introduce TT_ENABLE_DEBUG_MODE flag
  sample/http-server: fix parameter parsing
  sample/signal-test: fix use of uninitialized variable
  Fix typos in comments (sample/test/event-internal.h)
  sample/signal-test: add NULL checks
  Change the minimum version of automake to 1.13 and autoconf to 2.67
  Add Uninstall.cmake.in into dist archive
This commit is contained in:
Azat Khuzhin 2020-07-05 15:01:34 +03:00
commit 5df3037d10
91 changed files with 5172 additions and 2015 deletions

42
.github/workflows/abi.yml vendored Normal file
View File

@ -0,0 +1,42 @@
---
name: abi
on:
push:
branches:
- patches-2.1
- release-*-pull
tags:
- release-*
jobs:
abi:
runs-on: ubuntu-18.04
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2.0.0
- name: Install Dependencies
run:
sudo apt install
abi-tracker
abi-monitor
abi-dumper
abi-compliance-checker
pkgdiff
vtable-dumper
- name: Generate
shell: bash
run: |
./extra/abi-check/abi_check.sh
env:
ABI_CHECK_ROOT: /tmp/le-abi-root
- uses: actions/upload-artifact@v1
with:
name: build
path: /tmp/le-abi-root/work/abi-check

210
.github/workflows/linux.yml vendored Normal file
View File

@ -0,0 +1,210 @@
---
name: linux
on:
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
push:
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
jobs:
cmake:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
EVENT_MATRIX:
- DIST
- NONE
- DISABLE_OPENSSL
- DISABLE_THREAD_SUPPORT
- DISABLE_DEBUG_MODE
- DISABLE_MM_REPLACEMENT
- COMPILER_CLANG
- TEST_EXPORT_STATIC
- TEST_EXPORT_SHARED
- ASAN
- TSAN
- UBSAN
steps:
- uses: actions/checkout@v2.0.0
- name: Cache Build
uses: actions/cache@v1.1.0
with:
path: build
key: ${{ matrix.os }}-cmake-${{ matrix.EVENT_MATRIX }}-v2
- name: Cache Dist Build
uses: actions/cache@v1.1.0
with:
path: dist
key: ${{ matrix.os }}-cmake-dist-${{ matrix.EVENT_MATRIX }}-v2
- name: Build And Test
shell: bash
run: |
if [ "${{ matrix.EVENT_MATRIX }}" == "DIST" ]; then
./autogen.sh
mkdir -p dist
cd dist
../configure
rm -fr *.tar.gz
make dist
archive=$(echo *.tar.gz)
tar -vxf $archive
cd $(basename $archive .tar.gz)
fi
export TSAN_OPTIONS=suppressions=$PWD/extra/tsan.supp
export LSAN_OPTIONS=suppressions=$PWD/extra/lsan.supp
if [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_OPENSSL" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_THREAD_SUPPORT" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_DEBUG_MODE" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_DEBUG_MODE=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_MM_REPLACEMENT" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_MM_REPLACEMENT=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "COMPILER_CLANG" ]; then
EVENT_CMAKE_OPTIONS=""
export CC=clang
elif [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_STATIC" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_SHARED" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=SHARED -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "ASAN" ]; then
EVENT_CMAKE_OPTIONS="-DCMAKE_C_FLAGS=-fsanitize=address -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=debug"
elif [ "${{ matrix.EVENT_MATRIX }}" == "TSAN" ]; then
EVENT_CMAKE_OPTIONS="-DCMAKE_C_FLAGS=-fsanitize=thread -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=debug"
elif [ "${{ matrix.EVENT_MATRIX }}" == "UBSAN" ]; then
EVENT_CMAKE_OPTIONS="-DCMAKE_C_FLAGS=-fsanitize=undefined -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=debug"
else
EVENT_CMAKE_OPTIONS=""
fi
#run build and test
JOBS=20
export CTEST_PARALLEL_LEVEL=$JOBS
export CTEST_OUTPUT_ON_FAILURE=1
mkdir -p build
cd build
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
cmake --build .
if [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_STATIC" ]; then
sudo python3 ../test-export/test-export.py static
elif [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_SHARED" ]; then
sudo python3 ../test-export/test-export.py shared
else
cmake --build . --target verify
fi
- uses: actions/upload-artifact@v1
if: failure()
with:
name: ${{ matrix.os }}-cmake-${{ matrix.EVENT_MATRIX }}-build
path: build
- uses: actions/upload-artifact@v1
if: failure() && matrix.EVENT_MATRIX == 'DIST'
with:
name: ${{ matrix.os }}-cmake-${{ matrix.EVENT_MATRIX }}-dist
path: dist
autotools:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
EVENT_MATRIX:
- DIST
- NONE
- DISABLE_OPENSSL
- DISABLE_THREAD_SUPPORT
- DISABLE_DEBUG_MODE
- DISABLE_MM_REPLACEMENT
- COMPILER_CLANG
steps:
- uses: actions/checkout@v2.0.0
- name: Cache Build
uses: actions/cache@v1.1.0
with:
path: build
key: ${{ matrix.os }}-autotools-${{ matrix.EVENT_MATRIX }}-v2
- name: Cache Dist Build
uses: actions/cache@v1.1.0
with:
path: dist
key: ${{ matrix.os }}-autotools-dist-${{ matrix.EVENT_MATRIX }}-v2
- name: Build And Test
shell: bash
run: |
if [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_OPENSSL" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-openssl"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_THREAD_SUPPORT" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-thread-support"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_DEBUG_MODE" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-debug-mode"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_MM_REPLACEMENT" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-malloc-replacement"
elif [ "${{ matrix.EVENT_MATRIX }}" == "COMPILER_CLANG" ]; then
EVENT_CONFIGURE_OPTIONS=""
export CC=clang
else
EVENT_CONFIGURE_OPTIONS=""
fi
#run build and test
JOBS=20
./autogen.sh
if [ "${{ matrix.EVENT_MATRIX }}" == "DIST" ]; then
mkdir -p dist
cd dist
rm -fr *.tar.gz
../configure $EVENT_CONFIGURE_OPTIONS
make dist
archive=$(echo *.tar.gz)
tar -vxf $archive
cd $(basename $archive .tar.gz)
fi
mkdir -p build
cd build
echo [configure]: ../configure $EVENT_CONFIGURE_OPTIONS
../configure $EVENT_CONFIGURE_OPTIONS
make
make -j $JOBS verify
- uses: actions/upload-artifact@v1
if: failure()
with:
name: ${{ matrix.os }}-autotools-${{ matrix.EVENT_MATRIX }}-build
path: build
- uses: actions/upload-artifact@v1
if: failure() && matrix.EVENT_MATRIX == 'DIST'
with:
name: ${{ matrix.os }}-autotools-${{ matrix.EVENT_MATRIX }}-dist
path: dist

168
.github/workflows/macos.yml vendored Normal file
View File

@ -0,0 +1,168 @@
---
name: macos
on:
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
push:
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
jobs:
cmake:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
os: [macos-latest]
EVENT_MATRIX:
- NONE
- DISABLE_OPENSSL
- DISABLE_THREAD_SUPPORT
- DISABLE_DEBUG_MODE
- DISABLE_MM_REPLACEMENT
- TEST_EXPORT_STATIC
- TEST_EXPORT_SHARED
- OPENSSL_1_1
steps:
- uses: actions/checkout@v2.0.0
- name: Cache Build
uses: actions/cache@v1.1.0
with:
path: build
key: macos-10.15-cmake-${{ matrix.EVENT_MATRIX }}-v2
- name: Build And Test
shell: bash
run: |
if [ "${{ matrix.EVENT_MATRIX }}" == "OPENSSL_1_1" ]; then
export OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1
else
export OPENSSL_ROOT_DIR=/usr/local/opt/openssl
fi
if [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_OPENSSL" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_THREAD_SUPPORT" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_DEBUG_MODE" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_DEBUG_MODE=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_MM_REPLACEMENT" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_MM_REPLACEMENT=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_STATIC" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
elif [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_SHARED" ]; then
EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=SHARED -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
else
EVENT_CMAKE_OPTIONS=""
fi
#run build and test
JOBS=1
export CTEST_PARALLEL_LEVEL=$JOBS
export CTEST_OUTPUT_ON_FAILURE=1
mkdir -p build
cd build
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
cmake --build .
if [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_STATIC" ]; then
sudo python3 ../test-export/test-export.py static
elif [ "${{ matrix.EVENT_MATRIX }}" == "TEST_EXPORT_SHARED" ]; then
sudo python3 ../test-export/test-export.py shared
else
cmake --build . --target verify
fi
- uses: actions/upload-artifact@v1
if: failure()
with:
name: ${{ matrix.os }}-cmake-${{ matrix.EVENT_MATRIX }}-build
path: build
autotools:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
os: [macos-latest]
EVENT_MATRIX:
- NONE
- DISABLE_OPENSSL
- DISABLE_THREAD_SUPPORT
- DISABLE_DEBUG_MODE
- DISABLE_MM_REPLACEMENT
- OPENSSL_1_1
steps:
- uses: actions/checkout@v2.0.0
- name: Cache Build
uses: actions/cache@v1.1.0
with:
path: build
key: ${{ matrix.os }}-autotools-${{ matrix.EVENT_MATRIX }}-v2
- name: Install Depends
run: brew install autoconf automake libtool pkg-config
- name: Build And Test
shell: bash
run: |
if [ "${{ matrix.EVENT_MATRIX }}" == "OPENSSL_1_1" ]; then
export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig:$PKG_CONFIG_PATH"
else
export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
if [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_OPENSSL" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-openssl"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_THREAD_SUPPORT" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-thread-support"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_DEBUG_MODE" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-debug-mode"
elif [ "${{ matrix.EVENT_MATRIX }}" == "DISABLE_MM_REPLACEMENT" ]; then
EVENT_CONFIGURE_OPTIONS="--disable-malloc-replacement"
else
EVENT_CONFIGURE_OPTIONS=""
fi
#run build and test
JOBS=1
./autogen.sh
mkdir -p build
cd build
echo [configure]: ../configure $EVENT_CONFIGURE_OPTIONS
../configure $EVENT_CONFIGURE_OPTIONS
make
make -j $JOBS verify
- uses: actions/upload-artifact@v1
if: failure()
with:
name: ${{ matrix.os }}-autotools-${{ matrix.EVENT_MATRIX }}-build
path: build

170
.github/workflows/mingw.yml vendored Normal file
View File

@ -0,0 +1,170 @@
---
name: mingw
on:
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
push:
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
jobs:
autotools:
runs-on: windows-2019
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
EVENT_MATRIX:
- none
- disable-openssl
- disable-thread-support
- disable-debug-mode
- disable-malloc-replacement
steps:
- uses: actions/checkout@v2.0.0
- name: Cache MinGW
id: cache-mingw
uses: actions/cache@v1.1.2
with:
path: D:\a\_temp\msys
key: windows-mingw
- name: Cache Build
uses: actions/cache@v1.1.2
with:
path: build
key: mingw-autotools-${{ matrix.EVENT_MATRIX }}-v2
- uses: numworks/setup-msys2@v1
if: steps.cache-mingw.outputs.cache-hit != 'true'
with:
msystem: MINGW64
- name: Install Dependes
if: steps.cache-mingw.outputs.cache-hit != 'true'
run: |
msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc autoconf automake libtool mingw-w64-x86_64-openssl
- name: Build And Test
shell: powershell
run: |
$env:EVENT_CONFIGURE_OPTIONS=""
if ( "${{ matrix.EVENT_MATRIX }}" -ne "none" ) {
$env:EVENT_CONFIGURE_OPTIONS="--${{ matrix.EVENT_MATRIX }}"
}
$env:EVENT_TESTS_PARALLEL=1
$env:EVENT_BUILD_PARALLEL=10
$script='
export PATH="/mingw64/bin:/usr/bin:/bin:/usr/local/bin:/opt/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:$PATH"
./autogen.sh 2>&1 3>&1
[[ $? -ne 0 ]] && exit 1
mkdir -p build
cd build
[[ $? -ne 0 ]] && exit 1
LDFLAGS="-L/mingw64/lib" CFLAGS="-I/mingw64/include" ../configure $EVENT_CONFIGURE_OPTIONS 2>&1
[[ $? -ne 0 ]] && exit 1
make -j $EVENT_BUILD_PARALLEL 2>&1
[[ $? -ne 0 ]] && exit 1
make verify -j $EVENT_TESTS_PARALLEL 2>&1 '
D:\a\_temp\msys\msys64\usr\bin\bash.exe -c $script
- uses: actions/upload-artifact@v1
if: failure()
with:
name: mingw-${{ matrix.EVENT_MATRIX }}-build
path: build
cmake:
runs-on: windows-2019
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
EVENT_MATRIX:
- NONE
- DISABLE_OPENSSL
- DISABLE_THREAD_SUPPORT
- DISABLE_DEBUG_MODE
- DISABLE_MM_REPLACEMENT
steps:
- uses: actions/checkout@v2.0.0
- name: Cache MinGW
id: cache-mingw-cmake
uses: actions/cache@v1.1.2
with:
path: D:\a\_temp\msys
key: windows-mingw-cmake
- name: Cache Build
uses: actions/cache@v1.1.2
with:
path: build
key: mingw-cmake-${{ matrix.EVENT_MATRIX }}-v2
- uses: numworks/setup-msys2@v1
if: steps.cache-mingw-cmake.outputs.cache-hit != 'true'
with:
msystem: MINGW64
- name: Install Dependes
if: steps.cache-mingw-cmake.outputs.cache-hit != 'true'
run: |
msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-openssl
- name: Build And Test
shell: powershell
run: |
$EVENT_CONFIGURE_OPTIONS=""
if ( "${{ matrix.EVENT_MATRIX }}" -ne "NONE" ) {
$EVENT_CONFIGURE_OPTIONS="-DEVENT__${{ matrix.EVENT_MATRIX }}=ON"
}
$env:PATH="D:\a\_temp\msys\msys64\mingw64\bin;D:\a\_temp\msys\msys64\usr\bin;$env:PATH"
mkdir build -ea 0
cd build
function cmake_configure($retry)
{
$errcode=0
try {
cmake .. -G "MSYS Makefiles" $EVENT_CONFIGURE_OPTIONS -DCMAKE_C_FLAGS=-w
$errcode=$LastExitCode
}
catch {
$errcode=1
}
finally {
if ($errcode -ne 0) {
if ($retry -eq 0) {
$host.SetShouldExit($LastExitCode)
} else {
echo "Remove all entries in build directory"
rm -r -fo *
cmake_configure 0
}
}
}
}
cmake_configure 1
cmake --build .
ctest -V
- uses: actions/upload-artifact@v1
if: failure()
with:
name: mingw-${{ matrix.EVENT_MATRIX }}-build
path: build

256
.github/workflows/windows.yml vendored Normal file
View File

@ -0,0 +1,256 @@
---
name: windows
on:
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
push:
paths-ignore:
- '**.md'
- '.mailmap'
- 'ChangeLog*'
- 'whatsnew*'
- 'LICENSE'
jobs:
vs2017:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
os: [windows-2016]
EVENT_MATRIX: [NONE]
steps:
- uses: actions/checkout@v2.0.0
- name: Cache Depends
id: cache-depends
uses: actions/cache@v1.0.3
with:
path: C:\vcpkg\installed
key: ${{ matrix.os }}-vcpkg
- name: Cache Build
uses: actions/cache@v1.0.3
with:
path: build
key: ${{ matrix.os }}-${{ matrix.EVENT_MATRIX }}-v3
- name: Install Depends
if: steps.cache-depends.outputs.cache-hit != 'true'
shell: powershell
run: |
vcpkg install openssl:x64-windows
vcpkg install zlib:x64-windows
- name: Build And Test
shell: powershell
run: |
$OPENSSL_ROOT_DIR="C:\vcpkg\installed\x64-windows"
$EVENT_BUILD_PARALLEL=10
$EVENT_TESTS_PARALLEL=1
$env:PATH="$OPENSSL_ROOT_DIR/bin;$env:PATH"
mkdir build -ea 0
cd build
$CMAKE_CMD="cmake -G 'Visual Studio 15 2017 Win64' .."
function cmake_configure($retry)
{
$errcode=0
try {
if ($retry -eq 0) {
echo "[cmake configure retry] $CMAKE_CMD"
} else {
echo "[cmake configure] $CMAKE_CMD"
}
Invoke-Expression $CMAKE_CMD
$errcode=$LastExitCode
}
catch {
$errcode=1
}
finally {
if ($errcode -ne 0) {
if ($retry -eq 0) {
$host.SetShouldExit($LastExitCode)
} else {
echo "Remove all entries in build directory"
rm -r -fo *
cmake_configure 0
}
}
}
}
cmake_configure 1
try {
cmake --build . -j $EVENT_BUILD_PARALLEL -- /nologo /verbosity:minimal
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
if ("${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_STATIC") {
python ../test-export/test-export.py static
}
elseif ("${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_SHARED") {
python ../test-export/test-export.py shared
}
else {
ctest --output-on-failure -j $EVENT_TESTS_PARALLEL
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
}
} catch {
$host.SetShouldExit($LastExitCode)
}
- uses: actions/upload-artifact@v1
if: failure()
with:
name: ${{ matrix.os }}-${{ matrix.EVENT_MATRIX }}-build
path: build
vs2019:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
os: [windows-2019]
EVENT_MATRIX:
- NONE
- LIBRARY_TYPE_STATIC
- DISABLE_OPENSSL
- DISABLE_THREAD_SUPPORT
- DISABLE_DEBUG_MODE
- DISABLE_MM_REPLACEMENT
- DUNICODE
- TEST_EXPORT_SHARED
- TEST_EXPORT_STATIC
steps:
- uses: actions/checkout@v2.0.0
- name: Cache Depends
id: cache-depends
uses: actions/cache@v1.1.0
with:
path: C:\vcpkg\installed
key: ${{ matrix.os }}-vcpkg
- name: Cache Build
uses: actions/cache@v1.1.0
with:
path: build
key: ${{ matrix.os }}-${{ matrix.EVENT_MATRIX }}-v3
- name: Install Depends
if: steps.cache-depends.outputs.cache-hit != 'true'
shell: powershell
run: |
vcpkg install openssl:x64-windows
vcpkg install zlib:x64-windows
- name: Build And Test
shell: powershell
run: |
$OPENSSL_ROOT_DIR="C:\vcpkg\installed\x64-windows"
$EVENT_BUILD_PARALLEL=10
$EVENT_TESTS_PARALLEL=1
$env:PATH="$OPENSSL_ROOT_DIR/bin;$env:PATH"
if ( "${{ matrix.EVENT_MATRIX }}" -eq "LIBRARY_TYPE_STATIC" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "DISABLE_OPENSSL" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "DISABLE_THREAD_SUPPORT" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "DISABLE_DEBUG_MODE" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_DEBUG_MODE=ON"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "DISABLE_MM_REPLACEMENT" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_MM_REPLACEMENT=ON"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "UNICODE" ) {
$EVENT_CMAKE_OPTIONS="-DCMAKE_C_FLAGS='-DUNICODE -D_UNICODE'"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_SHARED" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
}
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_STATIC" ) {
$EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
}
else {
$EVENT_CMAKE_OPTIONS=""
}
mkdir build -ea 0
cd build
if ("${{ matrix.os }}" -eq "windows-2016") {
$CMAKE_CMD="cmake -G 'Visual Studio 15 2017 Win64' .."
}
else { # windows-2019
$CMAKE_CMD="cmake -G 'Visual Studio 16 2019' -A x64 .. $EVENT_CMAKE_OPTIONS"
}
function cmake_configure($retry)
{
$errcode=0
try {
if ($retry -eq 0) {
echo "[cmake configure retry] $CMAKE_CMD"
} else {
echo "[cmake configure] $CMAKE_CMD"
}
Invoke-Expression $CMAKE_CMD
$errcode=$LastExitCode
}
catch {
$errcode=1
}
finally {
if ($errcode -ne 0) {
if ($retry -eq 0) {
$host.SetShouldExit($LastExitCode)
} else {
echo "Remove all entries in build directory"
rm -r -fo *
cmake_configure 0
}
}
}
}
cmake_configure 1
try {
cmake --build . -j $EVENT_BUILD_PARALLEL -- /nologo /verbosity:minimal
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
if ("${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_STATIC") {
python ../test-export/test-export.py static
}
elseif ("${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_SHARED") {
python ../test-export/test-export.py shared
}
else {
ctest --output-on-failure -j $EVENT_TESTS_PARALLEL
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
}
} catch {
$host.SetShouldExit($LastExitCode)
}
- uses: actions/upload-artifact@v1
if: failure()
with:
name: ${{ matrix.os }}-${{ matrix.EVENT_MATRIX }}-build
path: build

10
.gitignore vendored
View File

@ -66,7 +66,6 @@ cscope*
/aclocal.m4
/compile
/doxygen
/config.cache
/config.guess
/config.log
@ -84,6 +83,12 @@ cscope*
/stamp-h1
/stamp-h2
# files generated by doxygen
doxygen
CMakeDoxyfile.in
CMakeDoxygenDefaults.cmake
Doxyfile.doxygen
/sample/dns-example
/sample/event-read-fifo
/sample/hello-world
@ -126,7 +131,7 @@ CTestTestfile.cmake
DartConfiguration.tcl
LibeventConfig.cmake
LibeventConfigVersion.cmake
LibeventTargets.cmake
LibeventTargets*.cmake
bin/
cmake_install.cmake
Uninstall.cmake
@ -141,6 +146,7 @@ event_extra.dir
*.sln
*.filters
install_manifest.txt
test-export/build
# ninja
build.ninja

View File

@ -1,5 +1,7 @@
# name -> email
Azat Khuzhin <azat@libevent.org>
yuangongji <yuangongji@foxmail.com>
# email -> email
<azat@libevent.org> <a3at.mail@gmail.com>
# primary email -> alias
<azat@libevent.org> <a3at.mail@gmail.com>
yuangongji <yuangongji@foxmail.com> <82787816@qq.com>

View File

@ -1,123 +0,0 @@
os:
- linux
- osx
sudo: false
dist: trusty
osx_image: xcode10.1
branches:
except:
- /.*appveyor.*/
- /.*win.*/
- /.*mingw.*/
- /.*freebsd.*/
- /.*bitrise.*/
git:
quiet: true
env:
matrix:
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__COVERAGE=ON -DCMAKE_BUILD_TYPE=debug" COVERALLS=yes
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS=""
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_DEBUG_MODE=ON"
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_MM_REPLACEMENT=ON"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS=""
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-openssl"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-thread-support"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-debug-mode"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-malloc-replacement"
matrix:
exclude:
- os: osx
env: EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__COVERAGE=ON -DCMAKE_BUILD_TYPE=debug" COVERALLS=yes
allow_failures:
- os: osx
fast_finish: true
language: c
compiler:
- gcc
- clang
before_install:
# do not run with clang, since it fails (SIGSEGV)
- if [ "$CC" = "clang" ]; then
unset COVERALLS;
fi
- if [ -n "$COVERALLS" ]; then
pip install --user cpp-coveralls;
fi
- export JOBS=20
- export TIMEOUT=50
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
if [ "$CC" == "gcc" ]; then
export CC=$(ls /usr/local/Cellar/gcc/*/bin/gcc-?);
fi
export OPENSSL_ROOT=$(echo /usr/local/Cellar/openssl/*);
export
CMAKE_INCLUDE_PATH=$OPENSSL_ROOT/include
CMAKE_LIBRARY_PATH=$OPENSSL_ROOT/lib;
export
CFLAGS=-I$CMAKE_INCLUDE_PATH
LDFLAGS=-L$CMAKE_LIBRARY_PATH;
export JOBS=1;
fi
addons:
apt:
sources:
- xenial
- sourceline: 'deb http://archive.ubuntu.com/ubuntu xenial main'
packages:
- zlib1g-dev
- libssl-dev
- build-essential
- automake
- autoconf
- cmake
- lcov
homebrew:
packages:
- openssl
- lcov
- libtool
- gcc
script:
- if [ "$EVENT_BUILD_METHOD" = "autotools" ]; then
./autogen.sh &&
./configure $EVENT_CONFIGURE_OPTIONS &&
make &&
travis_wait $TIMEOUT make -j $JOBS verify;
fi
- if [ "$EVENT_BUILD_METHOD" = "cmake" ]; then
export
CTEST_PARALLEL_LEVEL=$JOBS
CTEST_OUTPUT_ON_FAILURE=1;
mkdir build &&
cd build &&
cmake .. $EVENT_CMAKE_OPTIONS &&
travis_wait $TIMEOUT
cmake --build . --target verify;
fi
after_script:
- if [ -n "$COVERALLS" ]; then
coveralls
--build-root .
--root ..
--exclude test
--exclude sample
--exclude cmake
--exclude build/CMakeFiles/CheckTypeSize
--exclude build/CMakeFiles/CompilerIdC
--gcov-options '\-lp';
fi

View File

@ -46,16 +46,13 @@ set(EVENT__LIBRARY_TYPE DEFAULT CACHE STRING
project(libevent C)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
string(REGEX MATCH "SunOS" SOLARIS "${CMAKE_SYSTEM_NAME}")
include(CheckTypeSize)
include(CheckFunctionExistsEx)
include(CheckFileOffsetBits)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(Macros)
include(CheckVariableExists)
include(CheckSymbolExists)
include(CheckStructHasMember)
@ -84,10 +81,10 @@ set(EVENT_ABI_LIBVERSION
set(EVENT_PACKAGE_VERSION
"${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}")
set(EVENT_NUMERIC_VERSION 0x02010b00)
set(EVENT_NUMERIC_VERSION 0x02010c00)
# equals to VERSION_INFO in Makefile.am
set(EVENT_ABI_LIBVERSION_CURRENT 7)
set(EVENT_ABI_LIBVERSION_REVISION 0)
set(EVENT_ABI_LIBVERSION_REVISION 1)
set(EVENT_ABI_LIBVERSION_AGE 0)
# equals to RELEASE in Makefile.am
@ -158,9 +155,18 @@ option(EVENT__COVERAGE
# Put the libaries and binaries that get built into directories at the
# top of the build tree rather than in hard-to-find leaf directories.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
#
# But only if this variables are not defined yet
# (i.e. libevent is used via add_subdirectory())
if (NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
endif()
if (NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
endif()
if (NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
endif()
if (EVENT__ENABLE_VERBOSE_DEBUG)
add_definitions(-DUSE_DEBUG=1)
@ -243,7 +249,6 @@ if (${MSVC})
if (EVENT__MSVC_STATIC_RUNTIME)
foreach (flag_var
CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
@ -326,11 +331,14 @@ if (APPLE)
)
endif()
if (MINGW OR CYGWIN)
set(WIN32 TRUE)
endif()
# Winsock.
if(WIN32)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h ws2tcpip.h)
set(CMAKE_REQUIRED_LIBRARIES ws2_32.lib shell32.lib advapi32.lib)
set(CMAKE_REQUIRED_DEFINITIONS -FIwinsock2.h -FIws2tcpip.h)
set(CMAKE_REQUIRED_LIBRARIES ws2_32 shell32 advapi32)
set(CMAKE_REQUIRED_DEFINITIONS -FIwinsock2.h -FIws2tcpip.h -D_WIN32_WINNT=0x0600)
endif()
if (SOLARIS)
set(CMAKE_REQUIRED_LIBRARIES socket nsl)
@ -352,145 +360,161 @@ endif()
if (_GNU_SOURCE)
add_definitions(-D_GNU_SOURCE=1)
set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
endif()
CHECK_INCLUDE_FILE(sys/types.h EVENT__HAVE_SYS_TYPES_H)
if(EVENT__HAVE_SYS_TYPES_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES sys/types.h)
# Check if header files exist
list(APPEND FILES_TO_CHECK
fcntl.h
inttypes.h
memory.h
signal.h
stdarg.h
stddef.h
stdint.h
stdlib.h
string.h
errno.h
unistd.h
time.h
sys/types.h
sys/stat.h
sys/time.h
sys/param.h
)
if (WIN32)
list(APPEND FILES_TO_CHECK
io.h
winsock2.h
ws2tcpip.h
afunix.h
)
else()
list(APPEND FILES_TO_CHECK
netdb.h
dlfcn.h
arpa/inet.h
poll.h
port.h
sys/socket.h
sys/random.h
sys/un.h
sys/devpoll.h
sys/epoll.h
sys/eventfd.h
sys/event.h
sys/ioctl.h
sys/mman.h
sys/queue.h
sys/select.h
sys/sendfile.h
sys/uio.h
sys/wait.h
sys/resource.h
sys/timerfd.h
netinet/in.h
netinet/in6.h
netinet/tcp.h
ifaddrs.h
)
endif()
CHECK_INCLUDE_FILE(sys/socket.h EVENT__HAVE_SYS_SOCKET_H)
if(EVENT__HAVE_SYS_SOCKET_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
if (NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux")
list(APPEND FILES_TO_CHECK sys/sysctl.h)
endif()
CHECK_INCLUDE_FILE(netinet/in.h EVENT__HAVE_NETINET_IN_H)
if(EVENT__HAVE_NETINET_IN_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES netinet/in.h)
if (APPLE)
list(APPEND FILES_TO_CHECK
mach/mach_time.h
mach/mach.h
)
endif()
CHECK_INCLUDE_FILE(sys/un.h EVENT__HAVE_SYS_UN_H)
if(EVENT__HAVE_SYS_UN_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES sys/un.h)
foreach(FILE ${FILES_TO_CHECK})
CHECK_INCLUDE_FILE_CONCAT(${FILE} "EVENT")
endforeach()
unset(FILES_TO_CHECK)
# Check if functions exist
list(APPEND SYMBOLS_TO_CHECK
getaddrinfo
getnameinfo
getprotobynumber
getservbyname
gethostbyname
inet_ntop
inet_pton
gettimeofday
signal
strtoll
splice
strlcpy
strsep
strtok_r
vasprintf
timerclear
timercmp
timerisset
timeradd
nanosleep
putenv
umask
)
if (NOT EVENT__DISABLE_CLOCK_GETTIME)
list(APPEND SYMBOLS_TO_CHECK clock_gettime)
endif()
if(WIN32)
CHECK_INCLUDE_FILE(afunix.h EVENT__HAVE_AFUNIX_H)
if(EVENT__HAVE_AFUNIX_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES afunix.h)
if (WIN32)
list(APPEND SYMBOLS_TO_CHECK
_gmtime64_s
_gmtime64
)
else()
list(APPEND SYMBOLS_TO_CHECK
getifaddrs
select
epoll_create
epoll_create1
epoll_ctl
eventfd
poll
port_create
kqueue
fcntl
mmap
pipe
pipe2
sendfile
sigaction
strsignal
sysctl
accept4
arc4random
arc4random_buf
arc4random_addrandom
getrandom
getegid
geteuid
issetugid
usleep
timerfd_create
setenv
unsetenv
setrlimit
gethostbyname_r
)
if (APPLE)
list(APPEND SYMBOLS_TO_CHECK mach_absolute_time)
endif()
endif()
CHECK_TYPE_SIZE("struct sockaddr_un" EVENT__HAVE_STRUCT_SOCKADDR_UN)
CHECK_INCLUDE_FILE(netinet/in6.h EVENT__HAVE_NETINET_IN6_H)
if(EVENT__HAVE_NETINET_IN6_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES netinet/in6.h)
endif()
CHECK_INCLUDE_FILE(unistd.h EVENT__HAVE_UNISTD_H)
CHECK_INCLUDE_FILE(netdb.h EVENT__HAVE_NETDB_H)
CHECK_INCLUDE_FILE(dlfcn.h EVENT__HAVE_DLFCN_H)
CHECK_INCLUDE_FILE(arpa/inet.h EVENT__HAVE_ARPA_INET_H)
CHECK_INCLUDE_FILE(fcntl.h EVENT__HAVE_FCNTL_H)
if(EVENT__HAVE_FCNTL_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES fcntl.h)
endif()
CHECK_INCLUDE_FILE(inttypes.h EVENT__HAVE_INTTYPES_H)
CHECK_INCLUDE_FILE(memory.h EVENT__HAVE_MEMORY_H)
CHECK_INCLUDE_FILE(poll.h EVENT__HAVE_POLL_H)
CHECK_INCLUDE_FILE(port.h EVENT__HAVE_PORT_H)
if(EVENT__HAVE_PORT_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES port.h)
endif()
CHECK_INCLUDE_FILE(signal.h EVENT__HAVE_SIGNAL_H)
CHECK_INCLUDE_FILE(stdarg.h EVENT__HAVE_STDARG_H)
CHECK_INCLUDE_FILE(stddef.h EVENT__HAVE_STDDEF_H)
CHECK_INCLUDE_FILE(stdint.h EVENT__HAVE_STDINT_H)
CHECK_INCLUDE_FILE(stdlib.h EVENT__HAVE_STDLIB_H)
CHECK_INCLUDE_FILE(strings.h EVENT__HAVE_STRINGS_H)
CHECK_INCLUDE_FILE(string.h EVENT__HAVE_STRING_H)
CHECK_INCLUDE_FILE(sys/devpoll.h EVENT__HAVE_DEVPOLL)
CHECK_INCLUDE_FILE(sys/epoll.h EVENT__HAVE_SYS_EPOLL_H)
CHECK_INCLUDE_FILE(sys/eventfd.h EVENT__HAVE_SYS_EVENTFD_H)
CHECK_INCLUDE_FILE(sys/event.h EVENT__HAVE_SYS_EVENT_H)
CHECK_INCLUDE_FILE(sys/ioctl.h EVENT__HAVE_SYS_IOCTL_H)
CHECK_INCLUDE_FILE(sys/mman.h EVENT__HAVE_SYS_MMAN_H)
CHECK_INCLUDE_FILE(sys/param.h EVENT__HAVE_SYS_PARAM_H)
CHECK_INCLUDE_FILE(sys/queue.h EVENT__HAVE_SYS_QUEUE_H)
CHECK_INCLUDE_FILE(sys/select.h EVENT__HAVE_SYS_SELECT_H)
CHECK_INCLUDE_FILE(sys/sendfile.h EVENT__HAVE_SYS_SENDFILE_H)
CHECK_INCLUDE_FILE(sys/stat.h EVENT__HAVE_SYS_STAT_H)
CHECK_INCLUDE_FILE(sys/time.h EVENT__HAVE_SYS_TIME_H)
if(EVENT__HAVE_SYS_TIME_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES sys/time.h)
endif()
CHECK_INCLUDE_FILE(sys/uio.h EVENT__HAVE_SYS_UIO_H)
CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" EVENT__HAVE_IFADDRS_H)
CHECK_INCLUDE_FILE(mach/mach_time.h EVENT__HAVE_MACH_MACH_TIME_H)
CHECK_INCLUDE_FILE(netinet/tcp.h EVENT__HAVE_NETINET_TCP_H)
CHECK_INCLUDE_FILE(sys/wait.h EVENT__HAVE_SYS_WAIT_H)
CHECK_INCLUDE_FILE(sys/resource.h EVENT__HAVE_SYS_RESOURCE_H)
CHECK_INCLUDE_FILE(sys/sysctl.h EVENT__HAVE_SYS_SYSCTL_H)
CHECK_INCLUDE_FILE(sys/timerfd.h EVENT__HAVE_SYS_TIMERFD_H)
CHECK_INCLUDE_FILE(errno.h EVENT__HAVE_ERRNO_H)
CHECK_FUNCTION_EXISTS_EX(epoll_create EVENT__HAVE_EPOLL)
CHECK_FUNCTION_EXISTS_EX(epoll_ctl EVENT__HAVE_EPOLL_CTL)
CHECK_FUNCTION_EXISTS_EX(eventfd EVENT__HAVE_EVENTFD)
if(NOT EVENT__DISABLE_CLOCK_GETTIME)
CHECK_FUNCTION_EXISTS_EX(clock_gettime EVENT__HAVE_CLOCK_GETTIME)
endif()
CHECK_FUNCTION_EXISTS_EX(fcntl EVENT__HAVE_FCNTL)
CHECK_FUNCTION_EXISTS_EX(getaddrinfo EVENT__HAVE_GETADDRINFO)
CHECK_FUNCTION_EXISTS_EX(getnameinfo EVENT__HAVE_GETNAMEINFO)
CHECK_FUNCTION_EXISTS_EX(gettimeofday EVENT__HAVE_GETTIMEOFDAY)
CHECK_FUNCTION_EXISTS_EX(getprotobynumber EVENT__HAVE_GETPROTOBYNUMBER)
CHECK_FUNCTION_EXISTS_EX(getservbyname EVENT__HAVE_GETSERVBYNAME)
CHECK_FUNCTION_EXISTS_EX(inet_ntop EVENT__HAVE_INET_NTOP)
CHECK_FUNCTION_EXISTS_EX(inet_pton EVENT__HAVE_INET_PTON)
CHECK_FUNCTION_EXISTS_EX(kqueue EVENT__HAVE_KQUEUE)
CHECK_FUNCTION_EXISTS_EX(mmap EVENT__HAVE_MMAP)
CHECK_FUNCTION_EXISTS_EX(pipe EVENT__HAVE_PIPE)
CHECK_FUNCTION_EXISTS_EX(pipe2 EVENT__HAVE_PIPE2)
CHECK_FUNCTION_EXISTS_EX(poll EVENT__HAVE_POLL)
CHECK_FUNCTION_EXISTS_EX(port_create EVENT__HAVE_PORT_CREATE)
CHECK_FUNCTION_EXISTS_EX(sendfile EVENT__HAVE_SENDFILE)
CHECK_FUNCTION_EXISTS_EX(sigaction EVENT__HAVE_SIGACTION)
CHECK_FUNCTION_EXISTS_EX(signal EVENT__HAVE_SIGNAL)
CHECK_FUNCTION_EXISTS_EX(splice EVENT__HAVE_SPLICE)
CHECK_FUNCTION_EXISTS_EX(strlcpy EVENT__HAVE_STRLCPY)
CHECK_FUNCTION_EXISTS_EX(strsep EVENT__HAVE_STRSEP)
CHECK_FUNCTION_EXISTS_EX(strtok_r EVENT__HAVE_STRTOK_R)
CHECK_FUNCTION_EXISTS_EX(strtoll EVENT__HAVE_STRTOLL)
CHECK_FUNCTION_EXISTS_EX(vasprintf EVENT__HAVE_VASPRINTF)
CHECK_FUNCTION_EXISTS_EX(sysctl EVENT__HAVE_SYSCTL)
CHECK_FUNCTION_EXISTS_EX(accept4 EVENT__HAVE_ACCEPT4)
CHECK_FUNCTION_EXISTS_EX(arc4random EVENT__HAVE_ARC4RANDOM)
CHECK_FUNCTION_EXISTS_EX(arc4random_buf EVENT__HAVE_ARC4RANDOM_BUF)
CHECK_FUNCTION_EXISTS_EX(arc4random_addrandom EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
CHECK_FUNCTION_EXISTS_EX(epoll_create1 EVENT__HAVE_EPOLL_CREATE1)
CHECK_FUNCTION_EXISTS_EX(getegid EVENT__HAVE_GETEGID)
CHECK_FUNCTION_EXISTS_EX(geteuid EVENT__HAVE_GETEUID)
CHECK_FUNCTION_EXISTS_EX(getifaddrs EVENT__HAVE_GETIFADDRS)
CHECK_FUNCTION_EXISTS_EX(issetugid EVENT__HAVE_ISSETUGID)
CHECK_FUNCTION_EXISTS_EX(mach_absolute_time EVENT__HAVE_MACH_ABSOLUTE_TIME)
CHECK_FUNCTION_EXISTS_EX(nanosleep EVENT__HAVE_NANOSLEEP)
CHECK_FUNCTION_EXISTS_EX(usleep EVENT__HAVE_USLEEP)
CHECK_FUNCTION_EXISTS_EX(timeradd EVENT__HAVE_TIMERADD)
CHECK_FUNCTION_EXISTS_EX(timerclear EVENT__HAVE_TIMERCLEAR)
CHECK_FUNCTION_EXISTS_EX(timercmp EVENT__HAVE_TIMERCMP)
CHECK_FUNCTION_EXISTS_EX(timerfd_create EVENT__HAVE_TIMERFD_CREATE)
CHECK_FUNCTION_EXISTS_EX(timerisset EVENT__HAVE_TIMERISSET)
CHECK_FUNCTION_EXISTS_EX(putenv EVENT__HAVE_PUTENV)
CHECK_FUNCTION_EXISTS_EX(setenv EVENT__HAVE_SETENV)
CHECK_FUNCTION_EXISTS_EX(setrlimit EVENT__HAVE_SETRLIMIT)
CHECK_FUNCTION_EXISTS_EX(umask EVENT__HAVE_UMASK)
CHECK_FUNCTION_EXISTS_EX(unsetenv EVENT__HAVE_UNSETENV)
# Add stdio.h for vasprintf
set(EVENT_INCLUDES ${EVENT_INCLUDES} stdio.h)
CHECK_SYMBOLS_EXIST("${SYMBOLS_TO_CHECK}" "${EVENT_INCLUDES}" "EVENT")
unset(SYMBOLS_TO_CHECK)
set(EVENT__HAVE_EPOLL ${EVENT__HAVE_EPOLL_CREATE})
# Get the gethostbyname_r prototype.
CHECK_FUNCTION_EXISTS_EX(gethostbyname_r EVENT__HAVE_GETHOSTBYNAME_R)
if(EVENT__HAVE_GETHOSTBYNAME_R)
CHECK_PROTOTYPE_DEFINITION(gethostbyname_r
"int gethostbyname_r(const char *name, struct hostent *hp, struct hostent_data *hdata)"
@ -515,10 +539,10 @@ if(HAVE_PORT_H AND HAVE_PORT_CREATE)
set(EVENT__HAVE_EVENT_PORTS 1)
endif()
if(NOT WIN32)
CHECK_FUNCTION_EXISTS_EX(select EVENT__HAVE_SELECT)
endif()
# Only `CHECK_TYPE_SIZE()' will use `CMAKE_EXTRA_INCLUDE_FILES'
set(CMAKE_EXTRA_INCLUDE_FILES ${EVENT_INCLUDES})
CHECK_TYPE_SIZE("struct sockaddr_un" EVENT__HAVE_STRUCT_SOCKADDR_UN)
CHECK_TYPE_SIZE("uint8_t" EVENT__HAVE_UINT8_T)
CHECK_TYPE_SIZE("uint16_t" EVENT__HAVE_UINT16_T)
CHECK_TYPE_SIZE("uint32_t" EVENT__HAVE_UINT32_T)
@ -557,8 +581,6 @@ CHECK_SYMBOL_EXISTS("__FUNCTION__" "" EVENT__HAVE___FUNCTION__)
CHECK_SYMBOL_EXISTS(TAILQ_FOREACH sys/queue.h EVENT__HAVE_TAILQFOREACH)
CHECK_CONST_EXISTS(CTL_KERN sys/sysctl.h EVENT__HAVE_DECL_CTL_KERN)
CHECK_CONST_EXISTS(KERN_ARND sys/sysctl.h EVENT__HAVE_DECL_KERN_ARND)
CHECK_CONST_EXISTS(KERN_RANDOM sys/sysctl.h EVENT__HAVE_DECL_KERN_RANDOM)
CHECK_CONST_EXISTS(RANDOM_UUID sys/sysctl.h EVENT__HAVE_DECL_RANDOM_UUID)
CHECK_SYMBOL_EXISTS(F_SETFD fcntl.h EVENT__HAVE_SETFD)
CHECK_TYPE_SIZE(fd_mask EVENT__HAVE_FD_MASK)
@ -927,19 +949,21 @@ configure_file(
include(AddEventLibrary)
add_event_library(event_core SOURCES ${SRC_CORE})
add_event_library(event_extra
LIBRARIES event_core_shared
INNER_LIBRARIES event_core
SOURCES ${SRC_EXTRA})
if (NOT EVENT__DISABLE_OPENSSL)
add_event_library(event_openssl
LIBRARIES event_core_shared ${OPENSSL_LIBRARIES}
INNER_LIBRARIES event_core
OUTER_INCLUDES ${OPENSSL_INCLUDE_DIR}
LIBRARIES ${OPENSSL_LIBRARIES}
SOURCES ${SRC_OPENSSL})
endif()
if (CMAKE_USE_PTHREADS_INIT)
if (EVENT__HAVE_PTHREADS)
set(SRC_PTHREADS evthread_pthread.c)
add_event_library(event_pthreads
LIBRARIES event_core_shared
INNER_LIBRARIES event_core
SOURCES ${SRC_PTHREADS})
endif()
@ -950,6 +974,18 @@ add_event_library(event SOURCES ${SRC_CORE} ${SRC_EXTRA})
set(WIN32_GETOPT)
if (WIN32)
set(_TMPLIBS)
if (${EVENT_LIBRARY_STATIC})
list(APPEND _TMPLIBS event_core_static event_static)
endif()
if (${EVENT_LIBRARY_SHARED})
list(APPEND _TMPLIBS event_core_shared event_shared)
endif()
foreach(lib ${_TMPLIBS})
target_link_libraries(${lib} iphlpapi)
endforeach()
unset(_TMPLIBS)
list(APPEND WIN32_GETOPT
WIN32-Code/getopt.c
WIN32-Code/getopt_long.c)
@ -969,6 +1005,9 @@ macro(add_sample_prog ssl name)
if (${ssl})
target_link_libraries(${name} event_openssl)
if(WIN32)
target_link_libraries(${name} crypt32)
endif()
endif()
endmacro()
if (NOT EVENT__DISABLE_SAMPLES)
@ -1064,7 +1103,7 @@ if (NOT EVENT__DISABLE_TESTS)
DEPENDS
event_rpcgen.py
test/regress.rpc
COMMAND ${PYTHON_EXECUTABLE} ../event_rpcgen.py regress.rpc
COMMAND ${PYTHON_EXECUTABLE} ../event_rpcgen.py --quiet regress.rpc
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test)
list(APPEND SRC_REGRESS
@ -1091,7 +1130,7 @@ if (NOT EVENT__DISABLE_TESTS)
if (NOT EVENT__DISABLE_THREAD_SUPPORT)
list(APPEND SRC_REGRESS test/regress_thread.c)
endif()
elseif (CMAKE_USE_PTHREADS_INIT)
elseif (EVENT__HAVE_PTHREADS)
list(APPEND SRC_REGRESS test/regress_thread.c)
endif()
@ -1140,6 +1179,7 @@ if (NOT EVENT__DISABLE_TESTS)
# - ellzey
set(TESTPROGS test-changelist
test-eof
test-closed
test-fdleak
test-init
test-time
@ -1198,7 +1238,7 @@ if (NOT EVENT__DISABLE_TESTS)
# Default environment variables turns off all event systems,
# then we enable each one, one at a time when creating the tests.
set(DEFAULT_TEST_ENV_VARS "EVENT_SHOW_METHOD=1;")
set(DEFAULT_TEST_ENV_VARS)
foreach(BACKEND ${BACKENDS})
set(BACKEND_ENV_VAR "EVENT_NO${BACKEND}=1")
list(APPEND DEFAULT_TEST_ENV_VARS "${BACKEND_ENV_VAR}")
@ -1247,13 +1287,13 @@ if (NOT EVENT__DISABLE_TESTS)
set(TEST_NAME regress__${BACKEND_TEST_NAME})
add_test(${TEST_NAME}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress)
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress --quiet)
set_tests_properties(${TEST_NAME}
PROPERTIES ENVIRONMENT "${ENV_VARS}")
add_test(${TEST_NAME}_debug
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress)
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress --quiet)
set_tests_properties(${TEST_NAME}_debug
PROPERTIES ENVIRONMENT "${ENV_VARS};EVENT_DEBUG_MODE=1")
@ -1412,18 +1452,24 @@ endif()
# Installation preparation.
#
if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKE_DIR cmake)
else()
set(DEF_INSTALL_CMAKE_DIR lib/cmake/libevent)
endif()
set(EVENT_INSTALL_CMAKE_DIR
"${CMAKE_INSTALL_PREFIX}/${DEF_INSTALL_CMAKE_DIR}"
CACHE PATH "Installation directory for CMake files")
"${CMAKE_INSTALL_PREFIX}/lib/cmake/libevent")
export(PACKAGE libevent)
function(gen_package_config forinstall)
if(${forinstall})
set(CONFIG_FOR_INSTALL_TREE 1)
set(dir "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}")
else()
set(CONFIG_FOR_INSTALL_TREE 0)
set(dir "${PROJECT_BINARY_DIR}")
endif()
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfig.cmake.in
"${dir}/LibeventConfig.cmake"
@ONLY)
endfunction()
# Generate the config file for the build-tree.
set(EVENT__INCLUDE_DIRS
"${PROJECT_SOURCE_DIR}/include"
@ -1433,26 +1479,10 @@ set(LIBEVENT_INCLUDE_DIRS
${EVENT__INCLUDE_DIRS}
CACHE PATH "Libevent include directories")
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigBuildTree.cmake.in
${PROJECT_BINARY_DIR}/LibeventConfig.cmake
@ONLY)
gen_package_config(0)
# Generate the config file for the installation tree.
# Calculate the relative directory from the Cmake dir.
file(RELATIVE_PATH
REL_INCLUDE_DIR
"${EVENT_INSTALL_CMAKE_DIR}"
"${CMAKE_INSTALL_PREFIX}/include")
# Note the LIBEVENT_CMAKE_DIR is defined in LibeventConfig.cmake.in,
# we escape it here so it's evaluated when it is included instead
# so that the include dirs are given relative to where the
# config file is located.
set(EVENT_INSTALL_INCLUDE_DIR "\${LIBEVENT_CMAKE_DIR}/${REL_INCLUDE_DIR}")
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfig.cmake.in
${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
@ONLY)
gen_package_config(1)
# Generate version info for both build-tree and install-tree.
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigVersion.cmake.in
@ -1464,6 +1494,11 @@ install(FILES ${HDR_COMPAT}
DESTINATION "include"
COMPONENT dev)
# Install public headers
install(FILES ${HDR_PUBLIC}
DESTINATION "include/event2"
COMPONENT dev)
# Install the configs.
install(FILES
${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
@ -1472,9 +1507,19 @@ install(FILES
COMPONENT dev)
# Install exports for the install-tree.
install(EXPORT LibeventTargets
DESTINATION "${DEF_INSTALL_CMAKE_DIR}"
macro(install_export type)
install(EXPORT LibeventTargets-${type}
NAMESPACE ${PROJECT_NAME}::
DESTINATION "${EVENT_INSTALL_CMAKE_DIR}"
COMPONENT dev)
endmacro()
if (${EVENT_LIBRARY_STATIC})
install_export(static)
endif()
if (${EVENT_LIBRARY_SHARED})
install_export(shared)
endif()
# Install the scripts.
install(PROGRAMS
@ -1483,25 +1528,24 @@ install(PROGRAMS
COMPONENT runtime)
# Create documents with doxygen.
find_program(DOXYGEN doxygen)
if (DOXYGEN)
add_custom_target(doxygen
COMMAND ${DOXYGEN} Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
else()
message(WARNING "The doxygen target will not support since doxygen command was not found!")
option(EVENT__DOXYGEN
"Enables doxygen documentation" OFF)
if (EVENT__DOXYGEN)
include(UseDoxygen)
UseDoxygen()
endif()
# Create the uninstall target.
# https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake
configure_file(${PROJECT_SOURCE_DIR}/cmake/Uninstall.cmake.in
${PROJECT_BINARY_DIR}/Uninstall.cmake
@ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/Uninstall.cmake)
if (NOT TARGET uninstall)
# Create the uninstall target.
# https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake
configure_file(${PROJECT_SOURCE_DIR}/cmake/Uninstall.cmake.in
${PROJECT_BINARY_DIR}/Uninstall.cmake
@ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/Uninstall.cmake)
endif()
message(STATUS "")
message(STATUS " ---( Libevent " ${EVENT_VERSION} " )---")

View File

@ -1,3 +1,84 @@
Changes in version 2.1.12-stable (05 Jul 2020)
This release contains mostly bug fixes (I decided not to port some features
that can be ported even without ABI breakage, if you cannot find feature that
you are interested in, please give us a note!)
Since 2.1.12 libevent will use github actions as main CI, since
it recommends itself better then travis/appveyor (and had been removed from
upstream).
Look carefully at "slightly touches the behaviour" section.
Below you will find some of changes (this list has been cleaned up from the
patches that touches only tests and similar):
CI:
o Backport github actions to 2.1 (be3acd7c Azat Khuzhin)
o Merge branch 'event_rpcgen.py-cleanup' (f0ded5f3, 48e04887 Enji Cooper)
o Add API/ABI checker (using LVC) (709210d4, 2af1f6cc yuangongji)
test:
o tinytest: support timeout on Windows (794e8f75 yuangongji)
o Merge branch 'osx-clock' (e85afbe3 Azat Khuzhin)
o test-ratelim: calculate timers bias (for slow CPUs) to avoid false-positive (8ad26d0b Azat Khuzhin)
fixes:
o buffer: do not pass NULL to memcpy() from evbuffer_pullup() (5b063049 Azat Khuzhin)
o http: fix undefined-shift in EVUTIL_IS*_ helpers (6b8d02a7 Azat Khuzhin)
o Check error code of evhttp_add_header_internal() in evhttp_parse_query_impl() (97e28f09 Azat Khuzhin)
o http: fix EVHTTP_CON_AUTOFREE in case of timeout (and some else) (1be25938 Azat Khuzhin)
o evdns: Add additional validation for values of dns options (c2972453 ayuseleznev)
o There is typo in GetAdaptersAddresses windows library. It should be iphlpapi.dll (891adda9 Aleksandr-Melnikov)
o Merge branch 'EV_CLOSED-and-EV_ET-fixes' (db2efdf5 Azat Khuzhin)
o Fix memory corruption in EV_CLOSURE_EVENT_FINALIZE with debug enabled (8ccd8f56 Jan Kasiak)
o increase segment refcnt only if evbuffer_add_file_segment() succeeds (30662a3c yuangongji)
o evdns: fix a crash when evdns_base with waiting requests is freed (6f8e0e97 ayuseleznev)
o event_base_once: fix potential null pointer threat (2e9ceb16 chenguolong)
o http: do not assume body for CONNECT (1b42270b Azat Khuzhin)
o evbuffer_add_file: fix freeing of segment in the error path (5f017bde Azat Khuzhin)
o Fix checking return value of the evdns_base_resolv_conf_parse() (fc51bf2c Azat Khuzhin)
o Merge branch 'fix-signal-leak' (poll/select now needs reinit) (1c9cc07b Azat Khuzhin)
improvements:
o evutil_time: improve evutil_gettimeofday on Windows (a8219143 Nick Grifka)
o Support EV_CLOSED on linux for poll(2) (2530e7c6 Azat Khuzhin)
o Parse IPv6 scope IDs. (f602211f Philip Homburg)
o evutil_time: Implements usleep() using wait funtion on Windows (d42240d1 yuangongji)
o evutil_time: detect and use _gmtime64_s()/_gmtime64() (f4a6152c yuangongji)
slightly touches the behaviour:
o bufferevent: allow setting priority on socket and openssl type (4dd3acdd Nicolas J. Bouliane)
o Fix EV_CLOSED detection/reporting (epoll only) (1df324d4 Azat Khuzhin) (XXX)
o Revert "Warn if forked from the event loop during event_reinit()" (71f5c0d3 Azat Khuzhin)
samples:
o https-client: load certificates from the system cert store on Windows (e9478640 yuangongji)
build fixes:
o Do not use sysctl.h on linux (it had been deprecated) (d2871a37 Azat Khuzhin)
o cmake: avoid problems from use of CMAKE_USE_PTHREADS_INIT (a62ec765 Paul Osborne)
o Update list of cmake files for autotools dist archive (2016f017 Azat Khuzhin)
o LibeventConfig.cmake: restore CMAKE_FIND_LIBRARY_SUFFIXES and LIBEVENT_STATIC_LINK default (640f9cf6 Mario Emmenlauer)
o cmake: fix getaddrinfo checking error (dea51c2e yuangongji)
o autoconf: fix getaddrinfo checking errors on mingw (b9bf7fa7 yuangongji)
o Do not use shared global structures on CYGWIN (8a9b5655 Azat Khuzhin)
o Added uninstall target check to cmakelists (3f1fb1f9 Dimo Markov)
o Fix compilation without OPENSSL_API_COMPAT (921bdcdd Azat Khuzhin)
o cmake: improve package config file (1c047618, baec84f2 yuangongji)
o Link with iphlpapi only on windows (976f7d34 Azat Khuzhin)
o autotools: fails build when need but can not find openssl (93174bb5 yuangongji)
o Merge branch 'http-connect' (e2424229 Azat Khuzhin)
o Fix compat with NetBSD >= 10 (5febb4e1 Kamil Rytarowski)
o cmake: fix getrandom() detection (e0e5f3bd Azat Khuzhin)
o arc4random: replace sysctl() with getrandom (on linux) (66ec78fd Azat Khuzhin)
o Upgrade autoconf (after upgrading minimum required to 2.67) (45da7d9d yuangongji)
o eliminate some C4267 warnings in Windows (9e468c77 yuangongji)
o autotools: attach doxygen target into all target (5d1e8570 yuangongji)
o cmake: attach doxygen target into all target (7a85300a yuangongji)
o Change the minimum version of automake to 1.13 and autoconf to 2.67 (fdb8fb66 ygj6)
o Add Uninstall.cmake.in into dist archive (877f2355 Azat Khuzhin)
Changes in version 2.1.11-stable (01 Aug 2019)
This release contains one ABI breakage fix (that had been introduced in

View File

@ -17,11 +17,11 @@
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = libevent
PROJECT_NAME = $(PROJECT)-$(VERSION)
# Place all output under 'doxygen/'
OUTPUT_DIRECTORY = doxygen/
OUTPUT_DIRECTORY = $(DOCDIR)
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
@ -64,24 +64,24 @@ STRIP_FROM_PATH = include/
# with spaces.
INPUT = \
include/event2/buffer.h \
include/event2/buffer_compat.h \
include/event2/bufferevent.h \
include/event2/bufferevent_compat.h \
include/event2/bufferevent_ssl.h \
include/event2/dns.h \
include/event2/dns_compat.h \
include/event2/event.h \
include/event2/event_compat.h \
include/event2/http.h \
include/event2/http_compat.h \
include/event2/listener.h \
include/event2/rpc.h \
include/event2/rpc_compat.h \
include/event2/tag.h \
include/event2/tag_compat.h \
include/event2/thread.h \
include/event2/util.h
$(SRCDIR)/include/event2/buffer.h \
$(SRCDIR)/include/event2/buffer_compat.h \
$(SRCDIR)/include/event2/bufferevent.h \
$(SRCDIR)/include/event2/bufferevent_compat.h \
$(SRCDIR)/include/event2/bufferevent_ssl.h \
$(SRCDIR)/include/event2/dns.h \
$(SRCDIR)/include/event2/dns_compat.h \
$(SRCDIR)/include/event2/event.h \
$(SRCDIR)/include/event2/event_compat.h \
$(SRCDIR)/include/event2/http.h \
$(SRCDIR)/include/event2/http_compat.h \
$(SRCDIR)/include/event2/listener.h \
$(SRCDIR)/include/event2/rpc.h \
$(SRCDIR)/include/event2/rpc_compat.h \
$(SRCDIR)/include/event2/tag.h \
$(SRCDIR)/include/event2/tag_compat.h \
$(SRCDIR)/include/event2/thread.h \
$(SRCDIR)/include/event2/util.h
#---------------------------------------------------------------------------
# configuration options related to the HTML output
@ -90,7 +90,7 @@ INPUT = \
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
GENERATE_HTML = $(GENERATE_HTML)
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
@ -99,7 +99,7 @@ GENERATE_HTML = YES
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
GENERATE_LATEX = $(GENERATE_LATEX)
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@ -175,7 +175,7 @@ LATEX_HIDE_INDICES = NO
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
GENERATE_MAN = $(GENERATE_MAN)
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)

View File

@ -5,8 +5,8 @@
# See LICENSE for copying information.
# 'foreign' means that we're not enforcing GNU package rules strictly.
# '1.11.2' means that we need automake 1.11.2 or later (and we do).
AUTOMAKE_OPTIONS = foreign 1.11.2 subdir-objects
# '1.13' means that we need automake 1.13 or later (and we do).
AUTOMAKE_OPTIONS = foreign 1.13 subdir-objects
ACLOCAL_AMFLAGS = -I m4
@ -38,7 +38,7 @@ RELEASE = -release 2.1
#
# Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES
# UNLESS YOU REALLY REALLY HAVE TO.
VERSION_INFO = 7:0:0
VERSION_INFO = 7:1:0
# History: RELEASE VERSION_INFO
# 2.0.1-alpha -- 2.0 1:0:0
@ -75,6 +75,7 @@ VERSION_INFO = 7:0:0
# 2.1.9-beta-- 2.1 6:3:0 (No ABI change)
# 2.1.10-stable-- 2.1 6:4:0 (No ABI change, WRONG)
# 2.1.11-stable-- 2.1 7:0:0 (ABI changed)
# 2.1.12-stable-- 2.1 7:1:0 (No ABI change)
# ABI version history for this package effectively restarts every time
# we change RELEASE. Version 1.4.x had RELEASE of 1.4.
@ -113,8 +114,6 @@ CMAKE_FILES = \
cmake/CheckConstExists.cmake \
cmake/CheckFileOffsetBits.c \
cmake/CheckFileOffsetBits.cmake \
cmake/CheckFunctionExistsEx.c \
cmake/CheckFunctionExistsEx.cmake \
cmake/CheckFunctionKeywords.cmake \
cmake/CheckPrototypeDefinition.c.in \
cmake/CheckPrototypeDefinition.cmake \
@ -122,10 +121,11 @@ CMAKE_FILES = \
cmake/CodeCoverage.cmake \
cmake/COPYING-CMAKE-SCRIPTS \
cmake/Copyright.txt \
cmake/FindGit.cmake \
cmake/LibeventConfigBuildTree.cmake.in \
cmake/LibeventConfig.cmake.in \
cmake/LibeventConfigVersion.cmake.in \
cmake/Macros.cmake \
cmake/Uninstall.cmake.in \
cmake/UseDoxygen.cmake \
cmake/VersionViaGit.cmake \
event-config.h.cmake \
evconfig-private.h.cmake \
@ -177,6 +177,7 @@ include test/include.am
if BUILD_WIN32
SYS_CORE_LIBS = -liphlpapi
SYS_LIBS = -lws2_32 -lshell32 -ladvapi32
SYS_SRC = win32select.c buffer_iocp.c event_iocp.c \
bufferevent_async.c
@ -188,6 +189,7 @@ endif
else
SYS_CORE_LIBS =
SYS_LIBS =
SYS_SRC =
SYS_INCLUDES =
@ -264,11 +266,11 @@ AM_LDFLAGS = $(LIBEVENT_LDFLAGS)
GENERIC_LDFLAGS = -version-info $(VERSION_INFO) $(RELEASE) $(NO_UNDEFINED) $(AM_LDFLAGS)
libevent_la_SOURCES = $(CORE_SRC) $(EXTRAS_SRC)
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) $(SYS_CORE_LIBS)
libevent_la_LDFLAGS = $(GENERIC_LDFLAGS)
libevent_core_la_SOURCES = $(CORE_SRC)
libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) $(SYS_CORE_LIBS)
libevent_core_la_LDFLAGS = $(GENERIC_LDFLAGS)
if PTHREADS
@ -336,9 +338,7 @@ endif
verify: check
doxygen: FORCE
doxygen $(srcdir)/Doxyfile
FORCE:
include doxygen.am
DISTCLEANFILES += *~ libevent.pc libevent_core.pc libevent_extra.pc ./include/event2/event-config.h

View File

@ -464,6 +464,24 @@ fixing bugs:
* jeremyerb
* Fabrice Fontaine
* wenyg
* Aleksandr-Melnikov
* ayuseleznev
* chenguolong
* Dimo Markov
* dota17
* fanquake
* Jan Kasiak
* Kamil Rytarowski
* Mario Emmenlauer
* Michael Davidsaver
* mohuang
* Nick Grifka
* Nicolas J. Bouliane
* Paul Osborne
* Philip Homburg
* Wataru Ashihara
* William A Rowe Jr
* yangyongsheng
If we have forgotten your name, please contact us.

View File

@ -271,7 +271,7 @@
/* #undef EVENT__HAVE_WORKING_KQUEUE */
/* Numeric representation of the version */
#define EVENT__NUMERIC_VERSION 0x02010b00
#define EVENT__NUMERIC_VERSION 0x02010c00
/* Name of package */
#define EVENT__PACKAGE "libevent"
@ -332,7 +332,7 @@
#define EVENT__TIME_WITH_SYS_TIME 1
/* Version number of package */
#define EVENT__VERSION "2.1.11-stable"
#define EVENT__VERSION "2.1.12-stable"
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */

View File

@ -1,112 +0,0 @@
version: 2.1.11.{build}
os: Visual Studio 2017
platform:
- x64
branches:
except:
- /.*travis.*/
- /.*linux.*/
- /.*freebsd.*/
- /.*osx.*/
- /.*bitrise.*/
skip_commits:
message: /travis/
files:
- .travis.yml
environment:
global:
APPVEYOR_SAVE_CACHE_ON_ERROR: true
MINGW_ROOT: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1
OPENSSL_ROOT: C:/OpenSSL-Win64
MPATH: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/bin;C:/msys64/bin;C:/cygwin64/bin
EVENT_TESTS_PARALLEL: 20
EVENT_BUILD_PARALLEL: 10
matrix:
# !EVENT_ALLOW_FAILURE
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: ""
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__LIBRARY_TYPE=STATIC"
# EVENT_ALLOW_FAILURE
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: ""
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-openssl"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-thread-support"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-debug-mode"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-malloc-replacement"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_OPENSSL=ON"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_THREAD_SUPPORT=ON"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_DEBUG_MODE=ON"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_MM_REPLACEMENT=ON"
EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DCMAKE_C_FLAGS='-DUNICODE -D_UNICODE'"
EVENT_ALLOW_FAILURE: 1
matrix:
allow_failures:
- EVENT_ALLOW_FAILURE: 1
fast_finish: true
init:
- 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
- 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
- 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
- 'echo PATH is: %PATH%'
build_script:
- ps: |
if ($env:EVENT_BUILD_METHOD -eq 'autotools') {
$env:PATH="$env:MPATH;$env:OPENSSL_ROOT/bin;$env:PATH"
$env:LDFLAGS="-L$($env:OPENSSL_ROOT)/lib -L$($env:OPENSSL_ROOT)"
$env:CFLAGS="-I$($env:OPENSSL_ROOT)/include"
bash ./autogen.sh 2>&1 3>&1
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
md build-autotools 2> $null
cd build-autotools
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
bash ../configure $env:EVENT_CONFIGURE_OPTIONS 2>&1
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
make -j $env:EVENT_BUILD_PARALLEL 2>&1
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
make verify -j $env:EVENT_TESTS_PARALLEL 2>&1
} else {
md build-cmake 2> $null
cd build-cmake
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
cmake -G "Visual Studio 15 2017 Win64" .. $env:EVENT_CMAKE_OPTIONS
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
cmake --build . -j $env:EVENT_BUILD_PARALLEL -- /nologo /verbosity:minimal
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
ctest --output-on-failure -j $env:EVENT_TESTS_PARALLEL
}
cache:
- build-cmake
- build-autotools
on_failure:
- 7z a libevent.zip .
- appveyor PushArtifact libevent.zip

View File

@ -63,6 +63,9 @@
#ifdef EVENT__HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#ifdef EVENT__HAVE_SYS_RANDOM_H
#include <sys/random.h>
#endif
#endif
#include <limits.h>
#include <stdlib.h>
@ -167,17 +170,11 @@ arc4_seed_win32(void)
}
#endif
#if defined(EVENT__HAVE_SYS_SYSCTL_H) && defined(EVENT__HAVE_SYSCTL)
#if EVENT__HAVE_DECL_CTL_KERN && EVENT__HAVE_DECL_KERN_RANDOM && EVENT__HAVE_DECL_RANDOM_UUID
#define TRY_SEED_SYSCTL_LINUX
#if defined(EVENT__HAVE_GETRANDOM)
#define TRY_SEED_GETRANDOM
static int
arc4_seed_sysctl_linux(void)
arc4_seed_getrandom(void)
{
/* Based on code by William Ahern, this function tries to use the
* RANDOM_UUID sysctl to get entropy from the kernel. This can work
* even if /dev/urandom is inaccessible for some reason (e.g., we're
* running in a chroot). */
int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
unsigned char buf[ADD_ENTROPY];
size_t len, n;
unsigned i;
@ -188,7 +185,7 @@ arc4_seed_sysctl_linux(void)
for (len = 0; len < sizeof(buf); len += n) {
n = sizeof(buf) - len;
if (0 != sysctl(mib, 3, &buf[len], &n, NULL, 0))
if (0 == getrandom(&buf[len], n, 0))
return -1;
}
/* make sure that the buffer actually got set. */
@ -202,8 +199,9 @@ arc4_seed_sysctl_linux(void)
evutil_memclear_(buf, sizeof(buf));
return 0;
}
#endif
#endif /* EVENT__HAVE_GETRANDOM */
#if defined(EVENT__HAVE_SYS_SYSCTL_H) && defined(EVENT__HAVE_SYSCTL)
#if EVENT__HAVE_DECL_CTL_KERN && EVENT__HAVE_DECL_KERN_ARND
#define TRY_SEED_SYSCTL_BSD
static int
@ -342,6 +340,10 @@ arc4_seed(void)
if (0 == arc4_seed_win32())
ok = 1;
#endif
#ifdef TRY_SEED_GETRANDOM
if (0 == arc4_seed_getrandom())
ok = 1;
#endif
#ifdef TRY_SEED_URANDOM
if (0 == arc4_seed_urandom())
ok = 1;
@ -351,12 +353,6 @@ arc4_seed(void)
0 == arc4_seed_proc_sys_kernel_random_uuid())
ok = 1;
#endif
#ifdef TRY_SEED_SYSCTL_LINUX
/* Apparently Linux is deprecating sysctl, and spewing warning
* messages when you try to use it. */
if (!ok && 0 == arc4_seed_sysctl_linux())
ok = 1;
#endif
#ifdef TRY_SEED_SYSCTL_BSD
if (0 == arc4_seed_sysctl_bsd())
ok = 1;

View File

@ -1421,9 +1421,11 @@ evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size)
for (; chain != NULL && (size_t)size >= chain->off; chain = next) {
next = chain->next;
memcpy(buffer, chain->buffer + chain->misalign, chain->off);
size -= chain->off;
buffer += chain->off;
if (chain->buffer) {
memcpy(buffer, chain->buffer + chain->misalign, chain->off);
size -= chain->off;
buffer += chain->off;
}
if (chain == last_with_data)
removed_last_with_data = 1;
if (&chain->next == buf->last_with_datap)
@ -3209,7 +3211,6 @@ evbuffer_add_file_segment(struct evbuffer *buf,
}
}
}
++seg->refcnt;
EVLOCK_UNLOCK(seg->lock, 0);
if (buf->freeze_end)
@ -3273,6 +3274,9 @@ evbuffer_add_file_segment(struct evbuffer *buf,
chain->off = length;
}
EVLOCK_LOCK(seg->lock, 0);
++seg->refcnt;
EVLOCK_UNLOCK(seg->lock, 0);
extra->segment = seg;
buf->n_add_for_cb += length;
evbuffer_chain_insert(buf, chain);

View File

@ -650,7 +650,7 @@ bufferevent_priority_set(struct bufferevent *bufev, int priority)
struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (!BEV_IS_SOCKET(bufev))
if (BEV_IS_ASYNC(bufev) || BEV_IS_FILTER(bufev) || BEV_IS_PAIR(bufev))
goto done;
if (event_priority_set(&bufev->ev_read, priority) == -1)

View File

@ -35,7 +35,7 @@ Example:
OPTS:
-p - treat as patch
-f - treat as regular file
-f - treat as regular file and print diff
-d - treat as regular file and print diff
-r - treat as git revision (default)
-C - check using clang-format (default)
-U - check with uncrustify
@ -164,8 +164,8 @@ function clang_style()
local c="${options[cfg]}"
echo "{ $(sed -e 's/#.*//' -e '/---/d' -e '/\.\.\./d' "$c" | tr $'\n' ,) }"
}
function clang_format() { clang-format --style="$(clang_style)" "$@"; }
function clang_format_diff() { clang-format-diff --style="$(clang_style)" "$@"; }
function clang_format() { clang-format -style="$(clang_style)" "$@"; }
function clang_format_diff() { cat "$@" | clang-format-diff -p1 -style="$(clang_style)"; }
# for non-bare repo will work
function clang_format_git()
{ git format-patch --stdout "$@" -1 | clang_format_diff; }

View File

@ -35,6 +35,45 @@ macro(generate_pkgconfig LIB_NAME)
)
endmacro()
# LIB_NAME maybe event_core, event_extra, event_openssl, event_pthreads or event.
# Targets whose LIB_NAME is not 'event' should be exported and installed.
macro(export_install_target TYPE LIB_NAME OUTER_INCLUDES)
if("${LIB_NAME}" STREQUAL "event")
install(TARGETS "${LIB_NAME}_${TYPE}"
LIBRARY DESTINATION "lib" COMPONENT lib
ARCHIVE DESTINATION "lib" COMPONENT lib
RUNTIME DESTINATION "lib" COMPONENT lib
COMPONENT dev
)
else()
string(REPLACE "event_" "" PURE_NAME ${LIB_NAME})
string(TOUPPER ${TYPE} UPPER_TYPE)
list(APPEND LIBEVENT_${UPPER_TYPE}_LIBRARIES "${PURE_NAME}")
set(OUTER_INCS)
if (NOT "${OUTER_INCLUDES}" STREQUAL "NONE")
set(OUTER_INCS ${OUTER_INCLUDES})
endif()
target_include_directories("${LIB_NAME}_${TYPE}"
PUBLIC "$<INSTALL_INTERFACE:include>"
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
${OUTER_INCS}
)
set_target_properties("${LIB_NAME}_${TYPE}" PROPERTIES EXPORT_NAME ${PURE_NAME})
export(TARGETS "${LIB_NAME}_${TYPE}"
NAMESPACE ${PROJECT_NAME}::
FILE "${PROJECT_BINARY_DIR}/LibeventTargets-${TYPE}.cmake"
APPEND
)
install(TARGETS "${LIB_NAME}_${TYPE}"
EXPORT LibeventTargets-${TYPE}
LIBRARY DESTINATION "lib" COMPONENT lib
ARCHIVE DESTINATION "lib" COMPONENT lib
RUNTIME DESTINATION "lib" COMPONENT lib
COMPONENT dev
)
endif()
endmacro()
# Global variables that it uses:
# - EVENT_ABI_LIBVERSION
@ -44,8 +83,6 @@ endmacro()
# - EVENT_PACKAGE_RELEASE
# - CMAKE_THREAD_LIBS_INIT LIB_PLATFORM
# - OPENSSL_LIBRARIES
# - HDR_PUBLIC
# - EVENT_INSTALL_INCLUDE_DIR
# - EVENT_SHARED_FLAGS
# - EVENT_LIBRARY_STATIC
# - EVENT_LIBRARY_SHARED
@ -57,11 +94,13 @@ macro(add_event_library LIB_NAME)
cmake_parse_arguments(LIB
"" # Options
"VERSION" # One val
"SOURCES;LIBRARIES" # Multi val
"SOURCES;LIBRARIES;INNER_LIBRARIES;OUTER_INCLUDES" # Multi val
${ARGN}
)
set(ADD_EVENT_LIBRARY_TARGETS)
if ("${LIB_OUTER_INCLUDES}" STREQUAL "")
set(LIB_OUTER_INCLUDES NONE)
endif()
set(ADD_EVENT_LIBRARY_INTERFACE)
if (${EVENT_LIBRARY_STATIC})
@ -69,12 +108,17 @@ macro(add_event_library LIB_NAME)
set_target_properties("${LIB_NAME}_static" PROPERTIES
OUTPUT_NAME "${LIB_NAME}"
CLEAN_DIRECT_OUTPUT 1)
set_target_properties(
"${LIB_NAME}_static" PROPERTIES
PUBLIC_HEADER "${HDR_PUBLIC}")
list(APPEND LIBEVENT_STATIC_LIBRARIES "${LIB_NAME}_static")
list(APPEND ADD_EVENT_LIBRARY_TARGETS "${LIB_NAME}_static")
if(LIB_INNER_LIBRARIES)
set(INNER_LIBRARIES "${LIB_INNER_LIBRARIES}_static")
endif()
target_link_libraries("${LIB_NAME}_static"
${CMAKE_THREAD_LIBS_INIT}
${LIB_PLATFORM}
${INNER_LIBRARIES}
${LIB_LIBRARIES})
export_install_target(static "${LIB_NAME}" "${LIB_OUTER_INCLUDES}")
set(ADD_EVENT_LIBRARY_INTERFACE "${LIB_NAME}_static")
endif()
@ -82,9 +126,13 @@ macro(add_event_library LIB_NAME)
if (${EVENT_LIBRARY_SHARED})
add_library("${LIB_NAME}_shared" SHARED ${LIB_SOURCES})
if(LIB_INNER_LIBRARIES)
set(INNER_LIBRARIES "${LIB_INNER_LIBRARIES}_shared")
endif()
target_link_libraries("${LIB_NAME}_shared"
${CMAKE_THREAD_LIBS_INIT}
${LIB_PLATFORM}
${INNER_LIBRARIES}
${LIB_LIBRARIES})
if (EVENT_SHARED_FLAGS)
@ -110,14 +158,10 @@ macro(add_event_library LIB_NAME)
"${LIB_NAME}_shared" PROPERTIES
OUTPUT_NAME "${LIB_NAME}-${EVENT_PACKAGE_RELEASE}"
VERSION "${CURRENT_MINUS_AGE}.${EVENT_ABI_LIBVERSION_AGE}.${EVENT_ABI_LIBVERSION_REVISION}"
SOVERSION "${CURRENT_MINUS_AGE}")
SOVERSION "${CURRENT_MINUS_AGE}"
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif()
set_target_properties(
"${LIB_NAME}_shared" PROPERTIES
PUBLIC_HEADER "${HDR_PUBLIC}"
CLEAN_DIRECT_OUTPUT 1)
if (NOT WIN32)
set(LIB_LINK_NAME
"${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}")
@ -127,33 +171,19 @@ macro(add_event_library LIB_NAME)
COMMAND ${CMAKE_COMMAND} -E create_symlink
"$<TARGET_FILE_NAME:${LIB_NAME}_shared>"
"${LIB_LINK_NAME}"
WORKING_DIRECTORY "lib")
WORKING_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
endif()
list(APPEND LIBEVENT_SHARED_LIBRARIES "${LIB_NAME}_shared")
list(APPEND ADD_EVENT_LIBRARY_TARGETS "${LIB_NAME}_shared")
export_install_target(shared "${LIB_NAME}" "${LIB_OUTER_INCLUDES}")
set(ADD_EVENT_LIBRARY_INTERFACE "${LIB_NAME}_shared")
endif()
export(TARGETS ${ADD_EVENT_LIBRARY_TARGETS}
FILE "${PROJECT_BINARY_DIR}/LibeventTargets.cmake"
APPEND
)
install(TARGETS ${ADD_EVENT_LIBRARY_TARGETS}
EXPORT LibeventTargets
LIBRARY DESTINATION "lib" COMPONENT lib
ARCHIVE DESTINATION "lib" COMPONENT lib
RUNTIME DESTINATION "lib" COMPONENT lib
PUBLIC_HEADER DESTINATION "include/event2"
COMPONENT dev
)
if (NOT WIN32 AND ${EVENT_LIBRARY_SHARED})
install(FILES
"$<TARGET_FILE_DIR:${LIB_NAME}_shared>/${LIB_LINK_NAME}"
DESTINATION "lib"
COMPONENT lib)
if (NOT WIN32)
install(FILES
"$<TARGET_FILE_DIR:${LIB_NAME}_shared>/${LIB_LINK_NAME}"
DESTINATION "lib"
COMPONENT lib)
endif()
endif()
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,28 +0,0 @@
#ifdef CHECK_FUNCTION_EXISTS
#ifdef __cplusplus
extern "C"
#endif
char
CHECK_FUNCTION_EXISTS(void);
#ifdef __CLASSIC_C__
int main()
{
int ac;
char* av[];
#else
int main(int ac, char* av[])
{
#endif
CHECK_FUNCTION_EXISTS();
if (ac > 1000) {
return *av[0];
}
return 0;
}
#else /* CHECK_FUNCTION_EXISTS */
#error "CHECK_FUNCTION_EXISTS has to specify the function"
#endif /* CHECK_FUNCTION_EXISTS */

View File

@ -1,69 +0,0 @@
# - Check if a C function can be linked
# CHECK_FUNCTION_EXISTS(<function> <variable>)
#
# Check that the <function> is provided by libraries on the system and
# store the result in a <variable>. This does not verify that any
# system header file declares the function, only that it can be found
# at link time (considure using CheckSymbolExists).
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
#=============================================================================
# Copyright 2002-2011 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
MACRO(CHECK_FUNCTION_EXISTS_EX FUNCTION VARIABLE)
IF(${VARIABLE} MATCHES "^${VARIABLE}$")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"-DCHECK_FUNCTION_EXISTS=${FUNCTION} ${CMAKE_REQUIRED_FLAGS}")
MESSAGE(STATUS "Looking for ${FUNCTION}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ELSE(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES)
ENDIF(CMAKE_REQUIRED_LIBRARIES)
IF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_FUNCTION_EXISTS_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
ELSE(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_FUNCTION_EXISTS_ADD_INCLUDES)
ENDIF(CMAKE_REQUIRED_INCLUDES)
TRY_COMPILE(${VARIABLE}
${CMAKE_BINARY_DIR}
${PROJECT_SOURCE_DIR}/cmake/CheckFunctionExistsEx.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}"
"${CHECK_FUNCTION_EXISTS_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
IF(${VARIABLE})
SET(${VARIABLE} 1 CACHE INTERNAL "Have function ${FUNCTION}")
MESSAGE(STATUS "Looking for ${FUNCTION} - found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if the function ${FUNCTION} exists passed with the following output:\n"
"${OUTPUT}\n\n")
ELSE(${VARIABLE})
MESSAGE(STATUS "Looking for ${FUNCTION} - not found")
SET(${VARIABLE} "" CACHE INTERNAL "Have function ${FUNCTION}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the function ${FUNCTION} exists failed with the following output:\n"
"${OUTPUT}\n\n")
ENDIF(${VARIABLE})
ENDIF()
ENDMACRO(CHECK_FUNCTION_EXISTS_EX)

View File

@ -1,45 +0,0 @@
# The module defines the following variables:
# GIT_EXECUTABLE - path to git command line client
# GIT_FOUND - true if the command line client was found
# Example usage:
# find_package(Git)
# if(GIT_FOUND)
# message("git found: ${GIT_EXECUTABLE}")
# endif()
#=============================================================================
# Copyright 2010 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distributed this file outside of CMake, substitute the full
# License text for the above reference.)
# Look for 'git' or 'eg' (easy git)
set(git_names git eg)
# Prefer .cmd variants on Windows unless running in a Makefile
# in the MSYS shell.
if(WIN32)
if(NOT CMAKE_GENERATOR MATCHES "MSYS")
set(git_names git.cmd git eg.cmd eg)
endif()
endif()
find_program(GIT_EXECUTABLE
NAMES ${git_names}
DOC "git command line client")
mark_as_advanced(GIT_EXECUTABLE)
# Handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE)

View File

@ -1,18 +1,183 @@
# - Config file for the Libevent package
# It defines the following variables
# LIBEVENT_INCLUDE_DIRS - include directories
# LIBEVENT_FOUND - true if libevent and all required components found on the system
# LIBEVENT_xxx_FOUND - true if component xxx(see available components) found on the system
# LIBEVENT_VERSION - libevent version in format Major.Minor.Patch
# LIBEVENT_INCLUDE_DIRS - directories where libevent header is located.
# LIBEVENT_INCLUDE_DIR - same as DIRS
# LIBEVENT_LIBRARIES - libevent library to link against.
# LIBEVENT_LIBRARY - same as LIBRARIES
#
# These variables are deprecated, don't use them.
# LIBEVENT_STATIC_LIBRARIES - libraries to link against (archive/static)
# LIBEVENT_SHARED_LIBRARIES - libraries to link against (shared)
#
# When you try to locate the libevent libraries, you should specify which components you want to use.
# The following table lists all available components. If none is given, all imported targets will used.
# core - the core functons of libevent
# extra - extra functions, contains http, dns and rpc
# pthreads - multiple threads for libevent, not exists on Windows
# openssl - openssl support for libevent
#
# By default, the shared libraries of libevent will be found. To find the static ones instead,
# you must set the LIBEVENT_STATIC_LINK variable to TRUE before calling find_package(Libevent ...).
# If no component provided, all components will be used.
# example:
# set(LIBEVENT_STATIC_LINK TRUE)
# find_package(Libevent 2.2 REQUIRED COMPONENTS core)
# include_directories(${LIBEVENT_INCLUDE_DIRS}) # Can be omitted
# target_link_libraries(myapp ${LIBEVENT_LIBRARIES})
# or target_link_libraries(myapp libevent::core)
#
# find_package() can handle dependencies automatically. For example, given the 'openssl' component,
# all dependencies (libevent_core, libssl, libcrypto and openssl include directories) will be found.
# Get the path of the current file.
get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(CONFIG_FOR_INSTALL_TREE @CONFIG_FOR_INSTALL_TREE@)
# Set the include directories.
set(LIBEVENT_INCLUDE_DIRS "@EVENT_INSTALL_INCLUDE_DIR@")
# Include the project Targets file, this contains definitions for IMPORTED targets.
include(${LIBEVENT_CMAKE_DIR}/LibeventTargets.cmake)
set(LIBEVENT_VERSION @EVENT_PACKAGE_VERSION@)
# IMPORTED targets from LibeventTargets.cmake
set(LIBEVENT_STATIC_LIBRARIES "@LIBEVENT_STATIC_LIBRARIES@")
set(LIBEVENT_SHARED_LIBRARIES "@LIBEVENT_SHARED_LIBRARIES@")
# Default to the same type as libevent was built:
if(NOT DEFINED LIBEVENT_STATIC_LINK)
set(LIBEVENT_STATIC_LINK NOT @EVENT_LIBRARY_SHARED@)
endif()
set(CMAKE_FIND_LIBRARY_SUFFIXES_SAVE "${CMAKE_FIND_LIBRARY_SUFFIXES}")
if(${LIBEVENT_STATIC_LINK})
set(_LIB_TYPE static)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
set(_AVAILABLE_LIBS "${LIBEVENT_STATIC_LIBRARIES}")
else()
set(_LIB_TYPE shared)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
set(_AVAILABLE_LIBS "${LIBEVENT_SHARED_LIBRARIES}")
endif()
# Get the path of the current file.
get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_INSTALL_PREFIX "${LIBEVENT_CMAKE_DIR}/../../.." ABSOLUTE)
macro(message_if_needed _flag _msg)
if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
message(${_flag} "${_msg}")
endif()
endmacro()
macro(no_component_msg _comp)
if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_${_comp})
set(pthreadlib)
if(NOT WIN32)
set(pthreadlib ", pthreads")
endif()
message(FATAL_ERROR "Your libevent library does not contain a ${_comp} component!\n"
"The valid components are core, extra${pthreadlib} and openssl.")
else()
message_if_needed(WARNING "Your libevent library does not contain a ${_comp} component!")
endif()
endmacro()
set(_EVENT_COMPONENTS)
if(${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS)
list(REMOVE_DUPLICATES ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS)
foreach(_comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS})
list(FIND _AVAILABLE_LIBS ${_comp} _INDEX)
if(_INDEX GREATER -1)
list(APPEND _EVENT_COMPONENTS ${_comp})
else()
no_component_msg(${_comp})
endif()
endforeach()
else()
set(_EVENT_COMPONENTS ${_AVAILABLE_LIBS})
endif()
set(_POSSIBLE_PKG_NAMES)
list(APPEND _POSSIBLE_PKG_NAMES ${CMAKE_FIND_PACKAGE_NAME} LIBEVENT Libevent libevent)
list(REMOVE_DUPLICATES _POSSIBLE_PKG_NAMES)
macro(set_case_insensitive_found _comp)
foreach(name ${_POSSIBLE_PKG_NAMES})
if("${_comp}" STREQUAL "")
set(${name}_FOUND TRUE)
set(${name}_NOTFOUND FALSE)
else()
set(${name}_${_comp}_FOUND TRUE)
set(${name}_${_comp}_NOTFOUND FALSE)
endif()
endforeach()
endmacro()
if(CONFIG_FOR_INSTALL_TREE)
## Config for install tree ----------------------------------------
# Find includes
unset(_event_h CACHE)
find_path(_event_h
NAMES event2/event.h
PATHS "${_INSTALL_PREFIX}/include"
NO_DEFAULT_PATH)
if(_event_h)
set(LIBEVENT_INCLUDE_DIRS "${_event_h}")
message_if_needed(STATUS "Found libevent include directory: ${_event_h}")
else()
message_if_needed(WARNING "Your libevent library does not contain header files!")
endif()
# Find libraries
macro(find_event_lib _comp)
unset(_event_lib CACHE)
find_library(_event_lib
NAMES "event_${_comp}"
PATHS "${_INSTALL_PREFIX}/lib"
NO_DEFAULT_PATH)
if(_event_lib)
list(APPEND LIBEVENT_LIBRARIES "libevent::${_comp}")
set_case_insensitive_found(${_comp})
message_if_needed(STATUS "Found libevent component: ${_event_lib}")
else()
no_component_msg(${_comp})
endif()
endmacro()
foreach(comp ${_EVENT_COMPONENTS})
find_event_lib(${comp})
endforeach()
else()
## Config for build tree ----------------------------------------
set(LIBEVENT_INCLUDE_DIRS "@EVENT__INCLUDE_DIRS@")
foreach(_comp ${_EVENT_COMPONENTS})
list(APPEND LIBEVENT_LIBRARIES "libevent::${_comp}")
set_case_insensitive_found(${_comp})
endforeach()
endif()
set(LIBEVENT_INCLUDE_DIR ${LIBEVENT_INCLUDE_DIRS})
if(LIBEVENT_LIBRARIES)
set(LIBEVENT_LIBRARY ${LIBEVENT_LIBRARIES})
if(CONFIG_FOR_INSTALL_TREE)
message_if_needed(STATUS "Found libevent ${LIBEVENT_VERSION} in ${_INSTALL_PREFIX}")
else()
message_if_needed(STATUS "Found libevent ${LIBEVENT_VERSION} in ${LIBEVENT_CMAKE_DIR}")
endif()
# Avoid including targets more than one times
if(NOT TARGET event_core_${_LIB_TYPE})
# Include the project Targets file, this contains definitions for IMPORTED targets.
include(${LIBEVENT_CMAKE_DIR}/LibeventTargets-${_LIB_TYPE}.cmake)
endif()
else()
if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "Can not find any libraries for libevent.")
else()
message_if_needed(WARNING "Can not find any libraries for libevent.")
endif()
endif()
set(CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES_SAVE}")
unset(_LIB_TYPE)
unset(_AVAILABLE_LIBS)
unset(_EVENT_COMPONENTS)
unset(_POSSIBLE_PKG_NAMES)
unset(_INSTALL_PREFIX)

View File

@ -1,17 +0,0 @@
# - Config file for the Libevent package
# It defines the following variables
# LIBEVENT_INCLUDE_DIRS - include directories for FooBar
# LIBEVENT_LIBRARIES - libraries to link against
# Get the path of the current file.
get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
# Set the include directories.
set(LIBEVENT_INCLUDE_DIRS "@EVENT__INCLUDE_DIRS@")
# Include the project Targets file, this contains definitions for IMPORTED targets.
include(${LIBEVENT_CMAKE_DIR}/LibeventTargets.cmake)
# IMPORTED targets from LibeventTargets.cmake
set(LIBEVENT_LIBRARIES event event_core event_extra)

36
cmake/Macros.cmake Normal file
View File

@ -0,0 +1,36 @@
include(CheckSymbolExists)
include(CheckIncludeFiles)
# Check if each symbol in the symbol list exists,
# and define PREFIX__HAVE_SYMNAME to 1 if yes.
#
# SYMLIST: list of symbols to check
# HEADERS: header files to be included in check code
# PREFIX: the prefix of definition
macro(CHECK_SYMBOLS_EXIST SYMLIST HEADERS PREFIX)
foreach(SYMNAME ${SYMLIST})
string(TOUPPER "${SYMNAME}" SYMNAME_UPPER)
if ("${PREFIX}" STREQUAL "")
set(HAVE_SYM_DEF "HAVE_${SYMNAME_UPPER}")
else()
set(HAVE_SYM_DEF "${PREFIX}__HAVE_${SYMNAME_UPPER}")
endif()
CHECK_SYMBOL_EXISTS(${SYMNAME} "${HEADERS}" ${HAVE_SYM_DEF})
endforeach()
endmacro()
# Check if file exists, define PREFIX__HAVE_FILE to 1 if yes,
# and collect file to EVENT_INCLUDES
macro(CHECK_INCLUDE_FILE_CONCAT FILE PREFIX)
string(REGEX REPLACE "[./]" "_" FILE_UL ${FILE})
string(TOUPPER "${FILE_UL}" FILE_UL_UPPER)
if ("${PREFIX}" STREQUAL "")
set(HAVE_FILE_DEF "HAVE_${FILE_UL_UPPER}")
else()
set(HAVE_FILE_DEF "${PREFIX}__HAVE_${FILE_UL_UPPER}")
endif()
CHECK_INCLUDE_FILES("${EVENT_INCLUDES};${FILE}" ${HAVE_FILE_DEF})
if(${HAVE_FILE_DEF})
set(EVENT_INCLUDES ${EVENT_INCLUDES} ${FILE})
endif()
endmacro()

111
cmake/UseDoxygen.cmake Normal file
View File

@ -0,0 +1,111 @@
# Use FindDoxygen.cmake to generate documentation.
option(DOXYGEN_GENERATE_HTML "Generate HTML" ON)
option(DOXYGEN_GENERATE_MAN "Generate man pages" OFF)
option(DOXYGEN_MAN_LINKS "Generate man links" ON)
option(DOXYGEN_GENERATE_LATEX "Generate LaTeX" OFF)
# If the case-insensitive value of the cmake option is one of
# "off, no, false" or 0, it is equal to false, otherwise true.
# And the values of the doxygen config does not exactly match it.
# So we need to convert the cmake option to a doxygen config.
macro(_convert_to_dx_cfg CMK_OPTION)
if (${CMK_OPTION})
set(${CMK_OPTION} YES)
else()
set(${CMK_OPTION} NO)
endif()
endmacro()
macro(UseDoxygen)
if (${CMAKE_VERSION} VERSION_LESS "3.9")
# Old versions of cmake have poor support for Doxygen generation.
message(FATAL_ERROR "Doxygen generation only enabled for cmake 3.9 and higher")
else()
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME})
set(DOXYGEN_PROJECT_NUMBER ${EVENT_PACKAGE_VERSION})
set(DOXYGEN_PROJECT_BRIEF "Event notification library")
set(DOXYGEN_OUTPUT_DIRECTORY doxygen)
set(DOXYGEN_STRIP_FROM_PATH include)
set(DOXYGEN_JAVADOC_AUTOBRIEF YES)
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
set(DOXYGEN_SORT_BRIEF_DOCS YES)
set(DOXYGEN_RECURSIVE NO)
_convert_to_dx_cfg(DOXYGEN_GENERATE_HTML)
_convert_to_dx_cfg(DOXYGEN_GENERATE_MAN)
_convert_to_dx_cfg(DOXYGEN_MAN_LINKS)
_convert_to_dx_cfg(DOXYGEN_GENERATE_LATEX)
set(DOXYGEN_LATEX_CMD_NAME latex)
set(DOXYGEN_PAPER_TYPE a4wide)
set(DOXYGEN_PDF_HYPERLINKS NO)
set(DOXYGEN_GENERATE_RTF NO)
set(DOXYGEN_GENERATE_XML NO)
set(DOXYGEN_GENERATE_CHI NO)
set(DOXYGEN_PREDEFINED TAILQ_ENTRY
RB_ENTRY
EVENT_DEFINED_TQENTRY_
EVENT_IN_DOXYGEN_
)
set(DOX_INPUT include/event2/buffer.h
include/event2/buffer_compat.h
include/event2/bufferevent.h
include/event2/bufferevent_compat.h
include/event2/bufferevent_ssl.h
include/event2/dns.h
include/event2/dns_compat.h
include/event2/event.h
include/event2/event_compat.h
include/event2/http.h
include/event2/http_compat.h
include/event2/listener.h
include/event2/rpc.h
include/event2/rpc_compat.h
include/event2/tag.h
include/event2/tag_compat.h
include/event2/thread.h
include/event2/util.h
)
# Add 'doxygen' target
doxygen_add_docs(doxygen
${DOX_INPUT}
ALL
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating doxygen documentation for ${PROJECT_NAME}..."
)
# Use 'make clean' to remove the generated directory
set_property(DIRECTORY
PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${PROJECT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY}"
)
# Install html into <prefix>/share/doc/<project>
if ("${DOXYGEN_GENERATE_HTML}" STREQUAL "YES")
install(DIRECTORY
${PROJECT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY}/html
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}
COMPONENT doc
)
endif()
# Install manual into <prefix>/share/man/man3
if ("${DOXYGEN_GENERATE_MAN}" STREQUAL "YES")
install(DIRECTORY
${PROJECT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY}/man/man3
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man
COMPONENT doc
)
endif()
else(DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen command not found, set EVENT__DOXYGEN to disable")
endif (DOXYGEN_FOUND)
endif()
endmacro()

View File

@ -23,7 +23,7 @@ macro(event_fuzzy_version_from_git)
# set our defaults.
set(EVENT_GIT___VERSION_MAJOR 2)
set(EVENT_GIT___VERSION_MINOR 1)
set(EVENT_GIT___VERSION_PATCH 11)
set(EVENT_GIT___VERSION_PATCH 12)
set(EVENT_GIT___VERSION_STAGE "stable")
find_package(Git)
@ -31,7 +31,7 @@ macro(event_fuzzy_version_from_git)
if (GIT_FOUND)
execute_process(
COMMAND
${GIT_EXECUTABLE} describe --abbrev=0
${GIT_EXECUTABLE} describe --abbrev=0 --always
WORKING_DIRECTORY
${PROJECT_SOURCE_DIR}
RESULT_VARIABLE
@ -42,7 +42,9 @@ macro(event_fuzzy_version_from_git)
)
string(REGEX REPLACE "[\\._-]" ";" VERSION_LIST "${GITVERSION}")
list(LENGTH VERSION_LIST VERSION_LIST_LENGTH)
if(VERSION_LIST)
list(LENGTH VERSION_LIST VERSION_LIST_LENGTH)
endif()
if ((GITRET EQUAL 0) AND (VERSION_LIST_LENGTH EQUAL 5))
list(GET VERSION_LIST 1 _MAJOR)

View File

@ -5,30 +5,23 @@ dnl See LICENSE for copying information.
dnl
dnl Original version Dug Song <dugsong@monkey.org>
AC_INIT(libevent,2.1.11-stable)
AC_PREREQ(2.62)
AC_INIT(libevent,2.1.12-stable)
AC_PREREQ(2.67)
AC_CONFIG_SRCDIR(event.c)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE
dnl AM_SILENT_RULES req. automake 1.11. [no] defaults V=1
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS(config.h evconfig-private.h:evconfig-private.h.in)
AC_DEFINE(NUMERIC_VERSION, 0x02010b00, [Numeric representation of the version])
AC_DEFINE(NUMERIC_VERSION, 0x02010c00, [Numeric representation of the version])
dnl Initialize prefix.
if test "$prefix" = "NONE"; then
prefix="/usr/local"
fi
AC_PREFIX_DEFAULT([/usr/local])
dnl Try and get a full POSIX environment on obscure systems
ifdef([AC_USE_SYSTEM_EXTENSIONS], [
AC_USE_SYSTEM_EXTENSIONS
], [
AC_AIX
AC_GNU_SOURCE
AC_MINIX
])
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
@ -48,11 +41,7 @@ AC_PROG_INSTALL
AC_PROG_LN_S
# AC_PROG_MKDIR_P - $(MKDIR_P) should be defined by AM_INIT_AUTOMAKE
# AC_PROG_SED is only available in Autoconf >= 2.59b; workaround for older
# versions
ifdef([AC_PROG_SED], [AC_PROG_SED], [
AC_CHECK_PROGS(SED, [gsed sed])
])
AC_PROG_SED
AC_PROG_GCC_TRADITIONAL
@ -126,7 +115,8 @@ AC_ARG_ENABLE([clock-gettime],
[], [enable_clock_gettime=yes])
AC_PROG_LIBTOOL
LT_PREREQ([2.4.2])
LT_INIT
dnl Uncomment "AC_DISABLE_SHARED" to make shared libraries not get
dnl built by default. You can also turn shared libs on and off from
@ -150,40 +140,46 @@ AC_SEARCH_LIBS([sendfile], [sendfile])
dnl - check if the macro _WIN32 is defined on this compiler.
dnl - (this is how we check for a windows compiler)
AC_MSG_CHECKING(for WIN32)
AC_TRY_COMPILE(,
[
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],
[
#ifndef _WIN32
die horribly
#endif
],
bwin32=true; AC_MSG_RESULT(yes),
bwin32=false; AC_MSG_RESULT(no),
]
)],
[bwin32=true; AC_MSG_RESULT(yes)],
[bwin32=false; AC_MSG_RESULT(no)]
)
dnl - check if the macro __midipix__ is defined on this compiler.
dnl - (this is how we check for a midipix version of GCC)
AC_MSG_CHECKING(for MIDIPIX)
AC_TRY_COMPILE(,
[
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],
[
#ifndef __midipix__
die horribly
#endif
],
midipix=true; AC_MSG_RESULT(yes),
midipix=false; AC_MSG_RESULT(no),
]
)],
[midipix=true; AC_MSG_RESULT(yes)],
[midipix=false; AC_MSG_RESULT(no)]
)
dnl - check if the macro __CYGWIN__ is defined on this compiler.
dnl - (this is how we check for a cygwin version of GCC)
AC_MSG_CHECKING(for CYGWIN)
AC_TRY_COMPILE(,
[
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],
[
#ifndef __CYGWIN__
die horribly
#endif
],
cygwin=true; AC_MSG_RESULT(yes),
cygwin=false; AC_MSG_RESULT(no),
]
)],
[cygwin=true; AC_MSG_RESULT(yes)],
[cygwin=false; AC_MSG_RESULT(no)]
)
AC_CHECK_HEADERS([zlib.h])
@ -226,6 +222,7 @@ AC_CHECK_HEADERS([ \
fcntl.h \
ifaddrs.h \
mach/mach_time.h \
mach/mach.h \
netdb.h \
netinet/in.h \
netinet/in6.h \
@ -252,14 +249,21 @@ AC_CHECK_HEADERS([ \
sys/timerfd.h \
sys/uio.h \
sys/wait.h \
sys/random.h \
errno.h \
afunix.h \
])
AC_CHECK_HEADERS(sys/sysctl.h, [], [], [
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
])
case "${host_os}" in
linux*) ;;
*)
AC_CHECK_HEADERS(sys/sysctl.h, [], [], [
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
])
esac
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
AC_EGREP_CPP(yes,
@ -332,7 +336,7 @@ if test "x$ac_cv_header_sys_time_h" = "xyes"; then
fi
if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then
AC_CHECK_DECLS([CTL_KERN, KERN_RANDOM, RANDOM_UUID, KERN_ARND], [], [],
AC_CHECK_DECLS([CTL_KERN, KERN_ARND], [], [],
[[#include <sys/types.h>
#include <sys/sysctl.h>]]
)
@ -344,7 +348,7 @@ AM_CONDITIONAL(BUILD_MIDIPIX, test x$midipix = xtrue)
AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue || test x$midipix = xtrue)
if test x$bwin32 = xtrue; then
AC_SEARCH_LIBS([getservbyname],[ws2_32])
AC_HAVE_LIBRARY([ws2_32])
fi
dnl Checks for typedefs, structures, and compiler characteristics.
@ -364,11 +368,7 @@ AC_CHECK_FUNCS([ \
getegid \
geteuid \
getifaddrs \
getnameinfo \
getprotobynumber \
gettimeofday \
inet_ntop \
inet_pton \
issetugid \
mach_absolute_time \
mmap \
@ -392,10 +392,36 @@ AC_CHECK_FUNCS([ \
unsetenv \
usleep \
vasprintf \
getservbyname \
getrandom \
])
AS_IF([test x$bwin32 = xtrue],
AC_CHECK_FUNCS(_gmtime64_s, , [AC_CHECK_FUNCS(_gmtime64)])
)
AM_CONDITIONAL(STRLCPY_IMPL, [test x"$ac_cv_func_strlcpy" = xno])
m4_define([funcstochk],
[getnameinfo
getprotobynumber
getservbyname
inet_ntop
inet_pton]
)
AS_IF([test x$bwin32 = xtrue],
[AX_CHECK_DECLS_EX([funcstochk getaddrinfo],
[#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif])],
[AC_CHECK_FUNCS(m4_normalize(funcstochk))]
)
m4_undefine([funcstochk])
dnl check getaddrinfo and gethostbyname_r for non-windows
AS_IF([test x$bwin32 = xfalse], [
AC_CACHE_CHECK(
[for getaddrinfo],
[libevent_cv_getaddrinfo],
@ -441,27 +467,27 @@ AC_CHECK_FUNC(gethostbyname_r, [
[Define this if gethostbyname_r takes 6 arguments])
AC_MSG_RESULT(6)
], [
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <netdb.h>
], [
char *cp1, *cp2;
struct hostent *h1;
int i1, i2;
(void)gethostbyname_r(cp1,h1,cp2,i1,&i2);
], [
])], [
AC_DEFINE(HAVE_GETHOSTBYNAME_R)
AC_DEFINE(HAVE_GETHOSTBYNAME_R_5_ARG, 1,
[Define this if gethostbyname_r takes 5 arguments])
AC_MSG_RESULT(5)
], [
AC_TRY_COMPILE([
], [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <netdb.h>
], [
char *cp1;
struct hostent *h1;
struct hostent_data hd;
(void) gethostbyname_r(cp1,h1,&hd);
], [
])], [
AC_DEFINE(HAVE_GETHOSTBYNAME_R)
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3_ARG, 1,
[Define this if gethostbyname_r takes 3 arguments])
@ -475,6 +501,7 @@ AC_CHECK_FUNC(gethostbyname_r, [
])
fi
]) dnl end of checking getaddrinfo and gethostbyname_r
AC_MSG_CHECKING(for F_SETFD in fcntl.h)
AC_EGREP_CPP(yes,
@ -517,7 +544,8 @@ if test "x$ac_cv_header_sys_event_h" = "xyes"; then
AC_CHECK_FUNCS(kqueue, [havekqueue=yes], )
if test "x$havekqueue" = "xyes" ; then
AC_MSG_CHECKING(for working kqueue)
AC_TRY_RUN(
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@ -530,50 +558,50 @@ if test "x$ac_cv_header_sys_event_h" = "xyes"; then
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int
main(int argc, char **argv)
{
], [[
int kq;
int n;
int fd[[2]];
int fd[2];
struct kevent ev;
struct timespec ts;
char buf[[80000]];
char buf[80000];
if (pipe(fd) == -1)
exit(1);
if (fcntl(fd[[1]], F_SETFL, O_NONBLOCK) == -1)
exit(1);
return 1;
if (fcntl(fd[1], F_SETFL, O_NONBLOCK) == -1)
return 1;
while ((n = write(fd[[1]], buf, sizeof(buf))) == sizeof(buf))
while ((n = write(fd[1], buf, sizeof(buf))) == sizeof(buf))
;
if ((kq = kqueue()) == -1)
exit(1);
if ((kq = kqueue()) == -1)
return 1;
memset(&ev, 0, sizeof(ev));
ev.ident = fd[[1]];
ev.ident = fd[1];
ev.filter = EVFILT_WRITE;
ev.flags = EV_ADD | EV_ENABLE;
n = kevent(kq, &ev, 1, NULL, 0, NULL);
if (n == -1)
exit(1);
return 1;
read(fd[[0]], buf, sizeof(buf));
read(fd[0], buf, sizeof(buf));
ts.tv_sec = 0;
ts.tv_nsec = 0;
n = kevent(kq, NULL, 0, &ev, 1, &ts);
if (n == -1 || n == 0)
exit(1);
return 1;
exit(0);
}, [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WORKING_KQUEUE, 1,
[Define if kqueue works correctly with pipes])
havekqueue=yes
], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
return 0;
]]
)],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WORKING_KQUEUE, 1,
[Define if kqueue works correctly with pipes])
havekqueue=yes
], [AC_MSG_RESULT(no)], [AC_MSG_RESULT(no)]
)
fi
fi
AM_CONDITIONAL(KQUEUE_BACKEND, [test "x$havekqueue" = "xyes"])
@ -589,7 +617,8 @@ fi
if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then
if test "x$haveepoll" = "xno" ; then
AC_MSG_CHECKING(for epoll system call)
AC_TRY_RUN(
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdint.h>
#include <sys/param.h>
#include <sys/types.h>
@ -602,21 +631,21 @@ epoll_create(int size)
{
return (syscall(__NR_epoll_create, size));
}
int
main(int argc, char **argv)
{
]],[[
int epfd;
epfd = epoll_create(256);
exit (epfd == -1 ? 1 : 0);
}, [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EPOLL, 1,
[Define if your system supports the epoll system calls])
needsignal=yes
have_epoll=yes
AC_LIBOBJ(epoll_sub)
], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
return (epfd == -1 ? 1 : 0);
]]
)],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EPOLL, 1,
[Define if your system supports the epoll system calls])
needsignal=yes
have_epoll=yes
AC_LIBOBJ(epoll_sub)
], [AC_MSG_RESULT(no)], [AC_MSG_RESULT(no)]
)
fi
fi
AM_CONDITIONAL(EPOLL_BACKEND, [test "x$haveepoll" = "xyes"])
@ -726,39 +755,48 @@ AC_CHECK_TYPES([struct linger],,,
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef _WIN32
#include <winsock2.h>
#endif
])
AC_MSG_CHECKING([for socklen_t])
AC_TRY_COMPILE([
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([
#include <sys/types.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif],
[socklen_t x;],
AC_MSG_RESULT([yes]),
#endif
],[socklen_t x;]
)],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_DEFINE(socklen_t, unsigned int,
[Define to unsigned int if you dont have it])]
[Define to unsigned int if you dont have it])]
)
# __func__/__FUNCTION__ is not a macros in general
AC_MSG_CHECKING([whether our compiler supports __func__])
AC_TRY_COMPILE([],
[ const char *cp = __func__; ],
[ AC_DEFINE(HAVE___func__, 1, [Define to 1 if compiler have __func__])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],
[ const char *cp = __func__; ]
)],
[ AC_DEFINE(HAVE___func__, 1, [Define to 1 if compiler have __func__])
AC_MSG_RESULT([yes])
],
AC_MSG_RESULT([no])
[AC_MSG_RESULT([no])]
)
AC_MSG_CHECKING([whether our compiler supports __FUNCTION__])
AC_TRY_COMPILE([],
[ const char *cp = __FUNCTION__; ],
[ AC_DEFINE(HAVE___FUNCTION__, 1, [Define to 1 if compiler have __FUNCTION__])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],
[ const char *cp = __FUNCTION__; ]
)],
[ AC_DEFINE(HAVE___FUNCTION__, 1, [Define to 1 if compiler have __FUNCTION__])
AC_MSG_RESULT([yes])
],
AC_MSG_RESULT([no])
[AC_MSG_RESULT([no])]
)
# check if we can compile with pthreads
@ -828,7 +866,7 @@ if test x$enable_gcc_warnings != xno && test "$GCC" = "yes"; then
#endif])], have_clang=yes, have_clang=no)
# -W is the same as -Wextra
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast"
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wmissing-declarations -Wnested-externs -Wbad-function-cast"
if test x$enable_gcc_warnings = xyes; then
CFLAGS="$CFLAGS -Werror"
fi
@ -951,5 +989,19 @@ AC_SUBST([LIBEVENT_GC_SECTIONS])
AM_CONDITIONAL([INSTALL_LIBEVENT], [test "$enable_libevent_install" = "yes"])
# Doxygen support
DX_HTML_FEATURE(ON)
DX_MAN_FEATURE(OFF)
DX_RTF_FEATURE(OFF)
DX_XML_FEATURE(OFF)
DX_PDF_FEATURE(OFF)
DX_PS_FEATURE(OFF)
DX_CHM_FEATURE(OFF)
DX_CHI_FEATURE(OFF)
DX_INIT_DOXYGEN([libevent], [${top_srcdir}/Doxyfile], [doxygen])
AM_CONDITIONAL([ENABLE_DOXYGEN], [test "$DX_FLAG_doc" = "1"])
AM_CONDITIONAL([ENABLE_DOXYGEN_MAN], [test "$DX_FLAG_man" = "1"])
AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] )
AC_OUTPUT(Makefile)

55
doxygen.am Normal file
View File

@ -0,0 +1,55 @@
# Doxygen documentation will not be generated with default configuration,
# unless '--enable-doxygen-doc' is configured.
# The following targets are all about doxygen:
# make # 'make doxygen' would be auto executed
# make doxygen # generating doxygen documentation
# make doxygen-doc # same as 'make doxygen'
# make clean # clean docs generated by doxygen
# make install # install doxygen documentation
# make uninstall # uninstall doxygen documentation
if ENABLE_DOXYGEN
# Add all needed rules defined in ax_prog_doxygen.m4
@DX_RULES@
# Use 'make clean' to clean docs generated by doxygen.
clean-local:
-rm -rf $(DX_CLEANFILES)
# integrate doxygen with automake targets
man3_MANS = @DX_DOCDIR@/man/man3/*
$(man3_MANS): doxygen-doc
# Docs will be installed. It may be one or more docs supported
# by doxygen, but does not include 'man'.
docdirs = $(DX_INSTALL_DOCS)
# Rules for installing docs generated by doxygen into $(htmldir),
# The typical value of $(htmldir) is '/usr/local/share/doc/$(PACKAGE)'
install-data-local:
@if ! test -d "$(DESTDIR)$(htmldir)"; then \
echo "$(mkinstalldirs) '$(DESTDIR)$(htmldir)'"; \
$(mkinstalldirs) '$(DESTDIR)$(htmldir)'; \
fi
@for d in $(docdirs); do \
echo "cp -pR $$d '$(DESTDIR)$(htmldir)/'"; \
cp -pR $$d '$(DESTDIR)$(htmldir)/'; \
done
# Rules for uninstalling docs generated by doxygen from $(htmldir)
uninstall-local:
@for d in $(docdirs); do \
d=`basename $$d`; \
echo "test ! -d '$(DESTDIR)$(htmldir)/'$$d || \
{ find '$(DESTDIR)$(htmldir)/'$$d -type d ! -perm -200 -exec chmod u+w '{}' ';' && \
rm -rf '$(DESTDIR)$(htmldir)/'$$d; }"; \
test ! -d '$(DESTDIR)$(htmldir)/'$$d || \
{ find '$(DESTDIR)$(htmldir)/'$$d -type d ! -perm -200 -exec chmod u+w '{}' ';' && \
rm -rf '$(DESTDIR)$(htmldir)/'$$d; }; \
done
rmdir "$(DESTDIR)$(htmldir)/" || true
doxygen: doxygen-doc
endif ENABLE_DOXYGEN

View File

@ -281,7 +281,7 @@ epoll_apply_one_change(struct event_base *base,
return 0;
}
if ((ch->read_change|ch->write_change) & EV_CHANGE_ET)
if ((ch->read_change|ch->write_change|ch->close_change) & EV_CHANGE_ET)
events |= EPOLLET;
memset(&epev, 0, sizeof(epev));
@ -486,7 +486,9 @@ epoll_dispatch(struct event_base *base, struct timeval *tv)
continue;
#endif
if (what & (EPOLLHUP|EPOLLERR)) {
if (what & EPOLLERR) {
ev = EV_READ | EV_WRITE;
} else if ((what & EPOLLHUP) && !(what & EPOLLRDHUP)) {
ev = EV_READ | EV_WRITE;
} else {
if (what & EPOLLIN)

15
evdns.c
View File

@ -3531,6 +3531,7 @@ evdns_base_set_option_impl(struct evdns_base *base,
base->global_max_retransmits = retries;
} else if (str_matches_option(option, "randomize-case:")) {
int randcase = strtoint(val);
if (randcase == -1) return -1;
if (!(flags & DNS_OPTION_MISC)) return 0;
base->global_randomize_case = randcase;
} else if (str_matches_option(option, "bind-to:")) {
@ -3554,11 +3555,13 @@ evdns_base_set_option_impl(struct evdns_base *base,
sizeof(tv));
} else if (str_matches_option(option, "so-rcvbuf:")) {
int buf = strtoint(val);
if (buf == -1) return -1;
if (!(flags & DNS_OPTION_MISC)) return 0;
log(EVDNS_LOG_DEBUG, "Setting SO_RCVBUF to %s", val);
base->so_rcvbuf = buf;
} else if (str_matches_option(option, "so-sndbuf:")) {
int buf = strtoint(val);
if (buf == -1) return -1;
if (!(flags & DNS_OPTION_MISC)) return 0;
log(EVDNS_LOG_DEBUG, "Setting SO_SNDBUF to %s", val);
base->so_sndbuf = buf;
@ -4032,7 +4035,7 @@ evdns_base_new(struct event_base *event_base, int flags)
#else
r = evdns_base_resolv_conf_parse(base, opts, "/etc/resolv.conf");
#endif
if (r == -1) {
if (r) {
evdns_base_free_and_unlock(base, 0);
return NULL;
}
@ -4106,6 +4109,11 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
/* TODO(nickm) we might need to refcount here. */
while (base->req_waiting_head) {
if (fail_requests)
reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL);
request_finished(base->req_waiting_head, &base->req_waiting_head, 1);
}
for (i = 0; i < base->n_req_heads; ++i) {
while (base->req_heads[i]) {
if (fail_requests)
@ -4113,11 +4121,6 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
request_finished(base->req_heads[i], &REQ_HEAD(base, base->req_heads[i]->trans_id), 1);
}
}
while (base->req_waiting_head) {
if (fail_requests)
reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL);
request_finished(base->req_waiting_head, &base->req_waiting_head, 1);
}
base->global_requests_inflight = base->global_requests_waiting = 0;
for (server = base->server_head; server; server = server_next) {

View File

@ -75,11 +75,8 @@
/* Define to 1 if you have the declaration of `KERN_ARND'. */
#define EVENT__HAVE_DECL_KERN_ARND @EVENT__HAVE_DECL_KERN_ARND@
/* Define to 1 if you have the declaration of `KERN_RANDOM'. */
#define EVENT__HAVE_DECL_KERN_RANDOM @EVENT__HAVE_DECL_KERN_RANDOM@
/* Define to 1 if you have the declaration of `RANDOM_UUID'. */
#define EVENT__HAVE_DECL_RANDOM_UUID @EVENT__HAVE_DECL_RANDOM_UUID@
/* Define to 1 if you have `getrandom' function. */
#cmakedefine EVENT__HAVE_GETRANDOM 1
/* Define if /dev/poll is available */
#cmakedefine EVENT__HAVE_DEVPOLL 1
@ -181,6 +178,9 @@
/* Define to 1 if you have the <mach/mach_time.h> header file. */
#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H 1
/* Define to 1 if you have the <mach/mach.h> header file. */
#cmakedefine EVENT__HAVE_MACH_MACH_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine EVENT__HAVE_MEMORY_H 1
@ -274,9 +274,6 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine EVENT__HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine EVENT__HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine EVENT__HAVE_STRING_H 1
@ -292,6 +289,12 @@
/* Define to 1 if you have the `strtoll' function. */
#cmakedefine EVENT__HAVE_STRTOLL 1
/* Define to 1 if you have the `_gmtime64_s' function. */
#cmakedefine EVENT__HAVE__GMTIME64_S 1
/* Define to 1 if you have the `_gmtime64' function. */
#cmakedefine EVENT__HAVE__GMTIME64 1
/* Define to 1 if the system has the type `struct addrinfo'. */
#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO 1
@ -367,6 +370,9 @@
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine EVENT__HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/random.h> header file. */
#cmakedefine EVENT__HAVE_SYS_RANDOM_H 1
/* Define to 1 if you have the <sys/sysctl.h> header file. */
#cmakedefine EVENT__HAVE_SYS_SYSCTL_H 1

View File

@ -418,7 +418,7 @@ int event_add_nolock_(struct event *ev,
* if it is running in another thread and it doesn't have EV_FINALIZE set.
*/
#define EVENT_DEL_AUTOBLOCK 2
/** Argument for event_del_nolock_. Tells event_del to procede even if the
/** Argument for event_del_nolock_. Tells event_del to proceed even if the
* event is set up for finalization rather for regular use.*/
#define EVENT_DEL_EVEN_IF_FINALIZING 3
int event_del_nolock_(struct event *ev, int blocking);

11
event.c
View File

@ -987,12 +987,6 @@ event_reinit(struct event_base *base)
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
if (base->running_loop) {
event_warnx("%s: forked from the event_loop.", __func__);
res = -1;
goto done;
}
evsel = base->evsel;
/* check if this event mechanism requires reinit on the backend */
@ -1712,8 +1706,8 @@ event_process_active_single_queue(struct event_base *base,
evcb_evfinalize = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize;
EVUTIL_ASSERT((evcb->evcb_flags & EVLIST_FINALIZING));
EVBASE_RELEASE_LOCK(base, th_base_lock);
evcb_evfinalize(ev, ev->ev_arg);
event_debug_note_teardown_(ev);
evcb_evfinalize(ev, ev->ev_arg);
if (evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
mm_free(ev);
}
@ -2062,6 +2056,9 @@ event_base_once(struct event_base *base, evutil_socket_t fd, short events,
int res = 0;
int activate = 0;
if (!base)
return (-1);
/* We cannot support signals that just fire once, or persistent
* events. */
if (events & (EV_SIGNAL|EV_PERSIST))

File diff suppressed because it is too large Load Diff

View File

@ -432,7 +432,7 @@ evmap_io_active_(struct event_base *base, evutil_socket_t fd, short events)
if (NULL == ctx)
return;
LIST_FOREACH(ev, &ctx->events, ev_io_next) {
if (ev->ev_events & events)
if (ev->ev_events & (events & ~EV_ET))
event_active_nolock_(ev, ev->ev_events & events, 1);
}
}

View File

@ -38,7 +38,7 @@ extern "C" {
struct event_base;
#ifndef _WIN32
#if !defined(_WIN32) && !defined(__CYGWIN__)
/* On Windows, the way we currently make DLLs, it's not allowed for us to
* have shared global structures. Thus, we only do the direct-call-to-function
* code path if we know that the local shared library system supports it.

View File

@ -41,6 +41,7 @@
/* For structs needed by GetAdaptersAddresses */
#define _WIN32_WINNT 0x0501
#include <iphlpapi.h>
#include <netioapi.h>
#endif
#include <sys/types.h>
@ -74,6 +75,9 @@
#endif
#include <time.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <net/if.h>
#endif
#ifdef EVENT__HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
@ -694,7 +698,7 @@ evutil_check_ifaddrs(void)
"GetAdaptersInfo", but that's deprecated; let's just try
GetAdaptersAddresses and fall back to connect+getsockname.
*/
HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll"));
HMODULE lib = evutil_load_windows_system_library_(TEXT("iphlpapi.dll"));
GetAdaptersAddresses_fn_t fn;
ULONG size, res;
IP_ADAPTER_ADDRESSES *addresses = NULL, *address;
@ -990,6 +994,7 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum)
{
int port = 0;
unsigned int if_index;
const char *pname;
if (nodename == NULL && servname == NULL)
@ -1063,10 +1068,12 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) {
struct sockaddr_in6 sin6;
memset(&sin6, 0, sizeof(sin6));
if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) {
if (1 == evutil_inet_pton_scope(
AF_INET6, nodename, &sin6.sin6_addr, &if_index)) {
/* Got an ipv6 address. */
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(port);
sin6.sin6_scope_id = if_index;
*res = evutil_new_addrinfo_((struct sockaddr*)&sin6,
sizeof(sin6), hints);
if (!*res)
@ -1981,6 +1988,41 @@ evutil_inet_ntop(int af, const void *src, char *dst, size_t len)
#endif
}
int
evutil_inet_pton_scope(int af, const char *src, void *dst, unsigned *indexp)
{
int r;
unsigned if_index;
char *check, *cp, *tmp_src;
*indexp = 0; /* Reasonable default */
/* Bail out if not IPv6 */
if (af != AF_INET6)
return evutil_inet_pton(af, src, dst);
cp = strchr(src, '%');
/* Bail out if no zone ID */
if (cp == NULL)
return evutil_inet_pton(af, src, dst);
if_index = if_nametoindex(cp + 1);
if (if_index == 0) {
/* Could be numeric */
if_index = strtoul(cp + 1, &check, 10);
if (check[0] != '\0')
return 0;
}
*indexp = if_index;
tmp_src = mm_strdup(src);
cp = strchr(tmp_src, '%');
*cp = '\0';
r = evutil_inet_pton(af, tmp_src, dst);
free(tmp_src);
return r;
}
int
evutil_inet_pton(int af, const char *src, void *dst)
{
@ -2097,6 +2139,7 @@ int
evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen)
{
int port;
unsigned int if_index;
char buf[128];
const char *cp, *addr_part, *port_part;
int is_ipv6;
@ -2166,10 +2209,13 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *
#endif
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(port);
if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr))
if (1 != evutil_inet_pton_scope(
AF_INET6, addr_part, &sin6.sin6_addr, &if_index)) {
return -1;
}
if ((int)sizeof(sin6) > *outlen)
return -1;
sin6.sin6_scope_id = if_index;
memset(out, 0, *outlen);
memcpy(out, &sin6, sizeof(sin6));
*outlen = sizeof(sin6);
@ -2323,7 +2369,7 @@ static const unsigned char EVUTIL_TOLOWER_TABLE[256] = {
#define IMPL_CTYPE_FN(name) \
int EVUTIL_##name##_(char c) { \
ev_uint8_t u = c; \
return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \
return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1U << (u & 31))); \
}
IMPL_CTYPE_FN(ISALPHA)
IMPL_CTYPE_FN(ISALNUM)

View File

@ -65,6 +65,9 @@
#ifndef EVENT__HAVE_GETTIMEOFDAY
/* No gettimeofday; this must be windows. */
typedef void (WINAPI *GetSystemTimePreciseAsFileTime_fn_t) (LPFILETIME);
int
evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
{
@ -90,7 +93,22 @@ evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
if (tv == NULL)
return -1;
GetSystemTimeAsFileTime(&ft.ft_ft);
static GetSystemTimePreciseAsFileTime_fn_t GetSystemTimePreciseAsFileTime_fn = NULL;
static int check_precise = 1;
if (EVUTIL_UNLIKELY(check_precise)) {
HMODULE h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
if (h != NULL)
GetSystemTimePreciseAsFileTime_fn =
(GetSystemTimePreciseAsFileTime_fn_t)
GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
check_precise = 0;
}
if (GetSystemTimePreciseAsFileTime_fn != NULL)
GetSystemTimePreciseAsFileTime_fn(&ft.ft_ft);
else
GetSystemTimeAsFileTime(&ft.ft_ft);
if (EVUTIL_UNLIKELY(ft.ft_64 < EPOCH_BIAS)) {
/* Time before the unix epoch. */
@ -126,8 +144,22 @@ evutil_usleep_(const struct timeval *tv)
return;
#if defined(_WIN32)
{
long msec = evutil_tv_to_msec_(tv);
Sleep((DWORD)msec);
__int64 usec;
LARGE_INTEGER li;
HANDLE timer;
usec = tv->tv_sec * 1000000LL + tv->tv_usec;
if (!usec)
return;
li.QuadPart = -10LL * usec;
timer = CreateWaitableTimer(NULL, TRUE, NULL);
if (!timer)
return;
SetWaitableTimer(timer, &li, 0, NULL, NULL, 0);
WaitForSingleObject(timer, INFINITE);
CloseHandle(timer);
}
#elif defined(EVENT__HAVE_NANOSLEEP)
{
@ -158,18 +190,28 @@ evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm)
time_t t = time(NULL);
#ifndef _WIN32
#if defined(EVENT__HAVE__GMTIME64_S) || !defined(_WIN32)
struct tm sys;
#endif
/* If `tm` is null, set system's current time. */
if (tm == NULL) {
#ifdef _WIN32
/** TODO: detect _gmtime64()/_gmtime64_s() */
tm = gmtime(&t);
#else
#if !defined(_WIN32)
gmtime_r(&t, &sys);
tm = &sys;
/** detect _gmtime64()/_gmtime64_s() */
#elif defined(EVENT__HAVE__GMTIME64_S)
errno_t err;
err = _gmtime64_s(&sys, &t);
if (err) {
event_errx(1, "Invalid argument to _gmtime64_s");
} else {
tm = &sys;
}
#elif defined(EVENT__HAVE__GMTIME64)
tm = _gmtime64(&t);
#else
tm = gmtime(&t);
#endif
}

35
extra/abi-check/README.md Normal file
View File

@ -0,0 +1,35 @@
## libevent ABI/API changes
This script is used to generate information about changes in libevent ABI/API
between various versions using [LVC tools](https://github.com/lvc). Such an
overview can help developers migrate from one version to another.
Here is the `abi_check.sh`, which is used to generate ABI/API timeline for
libevent.
You can limit the number of included libevent versions via a number given
as a parameter to the script. For example
```shell
$ ./abi_check.sh 3
```
generates overview for the last 3 versions and the current version.
If no parameter given, it will generate overview for the last 2 versions and
the current version by default.
But this script requires some tools that are available in the following docker image:
```
docker.pkg.github.com/azat/docker-images/lvc-debian
```
And the full command looks like:
```shell
docker run --rm -it -v $PWD:/src:ro -w /src -v tmp/le-abi-check-root:/abi-root -e ABI_CHECK_ROOT=/abi-root docker.pkg.github.com/azat/docker-images/lvc-debian /src/extra/abi-check/abi_check.sh
```
'timeline/libevent/index.html' is the final result and can be viewed
[here](https://libevent.org/abi)

53
extra/abi-check/abi_check.sh Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Requirements:
# - wdiff
# - rfcdiff
# - universal-ctags
# - abi-tracker
# - abi-monitor
# - git
#
# All of this are included in:
# docker.pkg.github.com/azat/docker-images/lvc-debian:latest
#
# TODO:
# - move image into libevent namespace
# verify backward compatibility of API/ABI changes
set -e
LIMIT=${1:-2}
EVENT_SOURCE_DIR=${EVENT_SOURCE_DIR:-"$(cd "$(dirname "$0")"/../.. && pwd)"}
ABI_CHECK_ROOT=${ABI_CHECK_ROOT:-$EVENT_SOURCE_DIR/.abi-check}
ABI_CHECK_WORKSPACE=${ABI_CHECK_WORKSPACE:-"work/abi-check"}
mkdir -p "$ABI_CHECK_ROOT/$ABI_CHECK_WORKSPACE"
cd "$ABI_CHECK_ROOT/$ABI_CHECK_WORKSPACE"
# copy current source code and profile into workspace
mkdir -p src/libevent/current
mkdir -p installed/libevent/current
( # to avoid cd back
cd "$EVENT_SOURCE_DIR"
# XXX: not `git archive` since it will not copy changes that are not in index,
# and maybe some issues on CI (since it does not contain full clone)
find . -maxdepth 1 -mindepth 1 | {
git check-ignore --no-index --verbose --non-matching --stdin
} | fgrep :: | cut -f2 | grep -v /.git/ | tee /dev/stderr | {
xargs cp -r -t "$ABI_CHECK_ROOT/$ABI_CHECK_WORKSPACE/src/libevent/current/"
}
cp extra/abi-check/libevent.json "$ABI_CHECK_ROOT/$ABI_CHECK_WORKSPACE/"
)
# run LVC tools
abi-monitor -get -limit "$LIMIT" libevent.json
# XXX: abi-monitor 1.12 supports "-make -j8", but 1.10 does not
# (we can detect which version we have, and add this options)
abi-monitor -v current -build libevent.json
abi-monitor -build libevent.json
abi-tracker -build libevent.json
# remove useless files
rm -rf src installed build_logs libevent.json

View File

@ -0,0 +1,12 @@
{
"Name": "libevent",
"Title": "Libevent",
"SourceUrl": "https://github.com/libevent/libevent/tags",
"Git": "https://github.com/libevent/libevent.git",
"Maintainer": "Nick Mathewson, Azat Khuzhin and Niels Provos",
"MaintainerUrl": "https://libevent.org",
"BuildSystem": "Autotools",
"HeadersDiff": "On",
"Package": "release-",
"ReleasePattern": "\A([\d\-\.\_]+)(|\-beta|\-rc|\-stable)\Z",
}

3
extra/lsan.supp Normal file
View File

@ -0,0 +1,3 @@
# TODO: temporary, until tests itself will be fixed
leak:libcrypto.so
leak:libssl.so

2
extra/tsan.supp Normal file
View File

@ -0,0 +1,2 @@
# https://github.com/libevent/libevent/issues/777
race:event_debug_mode_too_late

23
http.c
View File

@ -177,7 +177,7 @@ fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
extern int debug;
static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
static evutil_socket_t create_bind_socket_nonblock(struct evutil_addrinfo *, int reuse);
static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri);
@ -358,6 +358,7 @@ evhttp_response_needs_body(struct evhttp_request *req)
return (req->response_code != HTTP_NOCONTENT &&
req->response_code != HTTP_NOTMODIFIED &&
(req->response_code < 100 || req->response_code >= 200) &&
req->type != EVHTTP_REQ_CONNECT &&
req->type != EVHTTP_REQ_HEAD);
}
@ -478,6 +479,9 @@ evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
static int
evhttp_is_request_connection_close(struct evhttp_request *req)
{
if (req->type == EVHTTP_REQ_CONNECT)
return 0;
return
evhttp_is_connection_close(req->flags, req->input_headers) ||
evhttp_is_connection_close(req->flags, req->output_headers);
@ -778,6 +782,11 @@ evhttp_connection_fail_(struct evhttp_connection *evcon,
/* We are trying the next request that was queued on us */
if (TAILQ_FIRST(&evcon->requests) != NULL)
evhttp_connection_connect_(evcon);
else
if ((evcon->flags & EVHTTP_CON_OUTGOING) &&
(evcon->flags & EVHTTP_CON_AUTOFREE)) {
evhttp_connection_free(evcon);
}
/* The call to evhttp_connection_reset_ overwrote errno.
* Let's restore the original errno, so that the user's
@ -3277,6 +3286,7 @@ evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
p = argument = line;
while (p != NULL && *p != '\0') {
char *key, *value, *decoded_value;
int err;
argument = strsep(&p, "&");
value = argument;
@ -3292,8 +3302,10 @@ evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
evhttp_decode_uri_internal(value, strlen(value),
decoded_value, 1 /*always_decode_plus*/);
event_debug(("Query Param: %s -> %s\n", key, decoded_value));
evhttp_add_header_internal(headers, key, decoded_value);
err = evhttp_add_header_internal(headers, key, decoded_value);
mm_free(decoded_value);
if (err)
goto error;
}
result = 0;
@ -4376,9 +4388,8 @@ name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
}
/* Create a non-blocking socket and bind it */
/* todo: rename this function */
static evutil_socket_t
bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
create_bind_socket_nonblock(struct evutil_addrinfo *ai, int reuse)
{
evutil_socket_t fd;
@ -4452,14 +4463,14 @@ bind_socket(const char *address, ev_uint16_t port, int reuse)
/* just create an unbound socket */
if (address == NULL && port == 0)
return bind_socket_ai(NULL, 0);
return create_bind_socket_nonblock(NULL, 0);
aitop = make_addrinfo(address, port);
if (aitop == NULL)
return (-1);
fd = bind_socket_ai(aitop, reuse);
fd = create_bind_socket_nonblock(aitop, reuse);
evutil_freeaddrinfo(aitop);

View File

@ -726,7 +726,8 @@ int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
@param buffer the evbuffer to store the result
@param fd the file descriptor to read from
@param howmuch the number of bytes to be read
@param howmuch the number of bytes to be read. If the given number is negative
or out of maximum bytes per one read, as many bytes as we can will be read.
@return the number of bytes read, or -1 if an error occurred
@see evbuffer_write()
*/

View File

@ -612,6 +612,12 @@ int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
/** Replacement for inet_ntop for platforms which lack it. */
EVENT2_EXPORT_SYMBOL
const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len);
/** Variation of inet_pton that also parses IPv6 scopes. Public for
unit tests. No reason to call this directly.
*/
EVENT2_EXPORT_SYMBOL
int evutil_inet_pton_scope(int af, const char *src, void *dst,
unsigned *indexp);
/** Replacement for inet_pton for platforms which lack it. */
EVENT2_EXPORT_SYMBOL
int evutil_inet_pton(int af, const char *src, void *dst);

View File

@ -51,7 +51,10 @@
/* Some platforms apparently define the udata field of struct kevent as
* intptr_t, whereas others define it as void*. There doesn't seem to be an
* easy way to tell them apart via autoconf, so we need to use OS macros. */
#if defined(EVENT__HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) && !defined(__CloudABI__)
#if defined(__NetBSD__)
#define PTR_TO_UDATA(x) ((typeof(((struct kevent *)0)->udata))(x))
#define INT_TO_UDATA(x) ((typeof(((struct kevent *)0)->udata))(intptr_t)(x))
#elif defined(EVENT__HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) && !defined(__CloudABI__)
#define PTR_TO_UDATA(x) ((intptr_t)(x))
#define INT_TO_UDATA(x) ((intptr_t)(x))
#else

22
m4/ax_check_funcs_ex.m4 Normal file
View File

@ -0,0 +1,22 @@
# Check if the function is available.
# HAVE_XXX will be defined if yes.
# $1: the name of function
# $2: the headers in where the function declared
AC_DEFUN([AX_CHECK_DECL_EX], [dnl
AS_IF([test "x$2" = "x"], [AC_MSG_ERROR([header not privided])])
AS_VAR_PUSHDEF([have_func_var], [HAVE_[]m4_toupper($1)])
AC_CHECK_DECL([$1],dnl
[AC_DEFINE([have_func_var], [1], [Define to 1 if you have the `$1' function.])],,dnl
[$2]dnl
)
AS_VAR_POPDEF([have_func_var])dnl
])
AC_DEFUN([AX_CHECK_DECLS_EX], [dnl
AS_IF([test "x$2" = "x"], [AC_MSG_ERROR([header not privided])])
m4_foreach([decl],dnl
m4_split(m4_normalize($1)),dnl
[AX_CHECK_DECL_EX([decl], [$2])]dnl
)
])

600
m4/ax_prog_doxygen.m4 Normal file
View File

@ -0,0 +1,600 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
# ===========================================================================
#
# SYNOPSIS
#
# DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...)
# DX_DOXYGEN_FEATURE(ON|OFF)
# DX_DOT_FEATURE(ON|OFF)
# DX_HTML_FEATURE(ON|OFF)
# DX_CHM_FEATURE(ON|OFF)
# DX_CHI_FEATURE(ON|OFF)
# DX_MAN_FEATURE(ON|OFF)
# DX_RTF_FEATURE(ON|OFF)
# DX_XML_FEATURE(ON|OFF)
# DX_PDF_FEATURE(ON|OFF)
# DX_PS_FEATURE(ON|OFF)
#
# DESCRIPTION
#
# The DX_*_FEATURE macros control the default setting for the given
# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
# help (for MS users), 'CHI' for generating a separate .chi file by the
# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
# specified to override the default 'a4wide' paper size.
#
# By default, HTML, PDF and PS documentation is generated as this seems to
# be the most popular and portable combination. MAN pages created by
# Doxygen are usually problematic, though by picking an appropriate subset
# and doing some massaging they might be better than nothing. CHM and RTF
# are specific for MS (note that you can't generate both HTML and CHM at
# the same time). The XML is rather useless unless you apply specialized
# post-processing to it.
#
# The macros mainly control the default state of the feature. The use can
# override the default by specifying --enable or --disable. The macros
# ensure that contradictory flags are not given (e.g.,
# --enable-doxygen-html and --enable-doxygen-chm,
# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
# feature will be automatically disabled (with a warning) if the required
# programs are missing.
#
# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
# with the following parameters: a one-word name for the project for use
# as a filename base etc., an optional configuration file name (the
# default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an
# optional output directory name (the default is 'doxygen-doc'). To run
# doxygen multiple times for different configuration files and output
# directories provide more parameters: the second, forth, sixth, etc
# parameter are configuration file names and the third, fifth, seventh,
# etc parameter are output directories. No checking is done to catch
# duplicates.
#
# Automake Support
#
# The DX_RULES substitution can be used to add all needed rules to the
# Makefile. Note that this is a substitution without being a variable:
# only the @DX_RULES@ syntax will work.
#
# The provided targets are:
#
# doxygen-doc: Generate all doxygen documentation.
#
# doxygen-run: Run doxygen, which will generate some of the
# documentation (HTML, CHM, CHI, MAN, RTF, XML)
# but will not do the post processing required
# for the rest of it (PS, PDF).
#
# doxygen-ps: Generate doxygen PostScript documentation.
#
# doxygen-pdf: Generate doxygen PDF documentation.
#
# Note that by default these are not integrated into the automake targets.
# If doxygen is used to generate man pages, you can achieve this
# integration by setting man3_MANS to the list of man pages generated and
# then adding the dependency:
#
# $(man3_MANS): doxygen-doc
#
# This will cause make to run doxygen and generate all the documentation.
#
# The following variable is intended for use in Makefile.am:
#
# DX_CLEANFILES = everything to clean.
#
# Then add this variable to MOSTLYCLEANFILES.
#
# LICENSE
#
# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
# Copyright (c) 2015 Olaf Mandel <olaf@mandel.name>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 24
## ----------##
## Defaults. ##
## ----------##
DX_ENV=""
AC_DEFUN([DX_FEATURE_doc], OFF)
AC_DEFUN([DX_FEATURE_dot], OFF)
AC_DEFUN([DX_FEATURE_man], OFF)
AC_DEFUN([DX_FEATURE_html], ON)
AC_DEFUN([DX_FEATURE_chm], OFF)
AC_DEFUN([DX_FEATURE_chi], OFF)
AC_DEFUN([DX_FEATURE_rtf], OFF)
AC_DEFUN([DX_FEATURE_xml], OFF)
AC_DEFUN([DX_FEATURE_pdf], ON)
AC_DEFUN([DX_FEATURE_ps], ON)
## --------------- ##
## Private macros. ##
## --------------- ##
# DX_ENV_APPEND(VARIABLE, VALUE)
# ------------------------------
# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it
# as a substitution (but not a Makefile variable). The substitution
# is skipped if the variable name is VERSION.
AC_DEFUN([DX_ENV_APPEND],
[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl
m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl
AM_SUBST_NOTMAKE([$1])])dnl
])
# DX_DIRNAME_EXPR
# ---------------
# Expand into a shell expression prints the directory part of a path.
AC_DEFUN([DX_DIRNAME_EXPR],
[[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
# -------------------------------------
# Expands according to the M4 (static) status of the feature.
AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
# ----------------------------------
# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
AC_DEFUN([DX_REQUIRE_PROG], [
AC_PATH_TOOL([$1], [$2])
if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
if test "x$2" = "xdoxygen"; then
AC_MSG_ERROR([$2 not found - will not DX_CURRENT_DESCRIPTION])
else
AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
fi
AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
fi
])
# DX_TEST_FEATURE(FEATURE)
# ------------------------
# Expand to a shell expression testing whether the feature is active.
AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
# -------------------------------------------------
# Verify that a required features has the right state before trying to turn on
# the DX_CURRENT_FEATURE.
AC_DEFUN([DX_CHECK_DEPEND], [
test "$DX_FLAG_$1" = "$2" \
|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
requires, contradicts) doxygen-$1])
])
# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
# ----------------------------------------------------------
# Turn off the DX_CURRENT_FEATURE if the required feature is off.
AC_DEFUN([DX_CLEAR_DEPEND], [
test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
])
# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
# CHECK_DEPEND, CLEAR_DEPEND,
# REQUIRE, DO-IF-ON, DO-IF-OFF)
# --------------------------------------------
# Parse the command-line option controlling a feature. CHECK_DEPEND is called
# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
# otherwise CLEAR_DEPEND is called to turn off the default state if a required
# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
AC_DEFUN([DX_ARG_ABLE], [
AC_DEFUN([DX_CURRENT_FEATURE], [$1])
AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
AC_ARG_ENABLE(doxygen-$1,
[AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
[--enable-doxygen-$1]),
DX_IF_FEATURE([$1], [don't $2], [$2]))],
[
case "$enableval" in
#(
y|Y|yes|Yes|YES)
AC_SUBST([DX_FLAG_$1], 1)
$3
;; #(
n|N|no|No|NO)
AC_SUBST([DX_FLAG_$1], 0)
;; #(
*)
AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
;;
esac
], [
AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
$4
])
if DX_TEST_FEATURE([$1]); then
$5
:
fi
if DX_TEST_FEATURE([$1]); then
$6
:
else
$7
:
fi
])
## -------------- ##
## Public macros. ##
## -------------- ##
# DX_XXX_FEATURE(DEFAULT_STATE)
# -----------------------------
AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...)
# --------------------------------------------------------------
# PROJECT also serves as the base name for the documentation files.
# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is
# "doxygen-doc".
# More arguments are interpreted as interleaved CONFIG-FILE and
# OUTPUT-DOC-DIR values.
AC_DEFUN([DX_INIT_DOXYGEN], [
# Files:
AC_SUBST([DX_PROJECT], [$1])
AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])'])
AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])'])
m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2,
[AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]),
'm4_default_nblank_quoted(m4_argn(DX_i, $@),
[$(srcdir)/Doxyfile])')])])dnl
m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2,
[AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]),
'm4_default_nblank_quoted(m4_argn(DX_i, $@),
[doxygen-doc])')])])dnl
m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1,
[m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])],
[])))dnl
# Environment variables used inside doxygen.cfg:
DX_ENV_APPEND(SRCDIR, $srcdir)
DX_ENV_APPEND(PROJECT, $DX_PROJECT)
DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
# Doxygen itself:
DX_ARG_ABLE(doc, [generate any doxygen documentation],
[],
[],
[DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
DX_REQUIRE_PROG([DX_PERL], perl)],
[DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
# Dot for graphics:
DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_DOT], dot)],
[DX_ENV_APPEND(HAVE_DOT, YES)
DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
[DX_ENV_APPEND(HAVE_DOT, NO)])
# Man pages generation:
DX_ARG_ABLE(man, [generate doxygen manual pages],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[],
[DX_ENV_APPEND(GENERATE_MAN, YES)],
[DX_ENV_APPEND(GENERATE_MAN, NO)])
# RTF file generation:
DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[],
[DX_ENV_APPEND(GENERATE_RTF, YES)],
[DX_ENV_APPEND(GENERATE_RTF, NO)])
# XML file generation:
DX_ARG_ABLE(xml, [generate doxygen XML documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[],
[DX_ENV_APPEND(GENERATE_XML, YES)],
[DX_ENV_APPEND(GENERATE_XML, NO)])
# (Compressed) HTML help generation:
DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_HHC], hhc)],
[DX_ENV_APPEND(HHC_PATH, $DX_HHC)
DX_ENV_APPEND(GENERATE_HTML, YES)
DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
[DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
# Separate CHI file generation.
DX_ARG_ABLE(chi, [generate doxygen separate compressed HTML help index file],
[DX_CHECK_DEPEND(chm, 1)],
[DX_CLEAR_DEPEND(chm, 1)],
[],
[DX_ENV_APPEND(GENERATE_CHI, YES)],
[DX_ENV_APPEND(GENERATE_CHI, NO)])
# Plain HTML pages generation:
DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
[DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
[DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
[],
[DX_ENV_APPEND(GENERATE_HTML, YES)],
[DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
# PostScript file generation:
DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_LATEX], latex)
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
DX_REQUIRE_PROG([DX_DVIPS], dvips)
DX_REQUIRE_PROG([DX_EGREP], egrep)])
# PDF file generation:
DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
DX_REQUIRE_PROG([DX_EGREP], egrep)])
# LaTeX generation for PS and/or PDF:
if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
DX_ENV_APPEND(GENERATE_LATEX, YES)
else
DX_ENV_APPEND(GENERATE_LATEX, NO)
fi
# Paper size for PS and/or PDF:
AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
[a4wide (default), a4, letter, legal or executive])
case "$DOXYGEN_PAPER_SIZE" in
#(
"")
AC_SUBST(DOXYGEN_PAPER_SIZE, "")
;; #(
a4wide|a4|letter|legal|executive)
DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
;; #(
*)
AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
;;
esac
# Rules:
AS_IF([[test $DX_FLAG_html -eq 1]],
[[DX_SNIPPET_html="## ------------------------------- ##
## Rules specific for HTML output. ##
## ------------------------------- ##
DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/html]])[
"]],
[[DX_SNIPPET_html=""]])
AS_IF([[test $DX_FLAG_chi -eq 1]],
[[DX_SNIPPET_chi="
DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]],
[[DX_SNIPPET_chi=""]])
AS_IF([[test $DX_FLAG_chm -eq 1]],
[[DX_SNIPPET_chm="## ------------------------------ ##
## Rules specific for CHM output. ##
## ------------------------------ ##
DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/chm]])[\
${DX_SNIPPET_chi}
"]],
[[DX_SNIPPET_chm=""]])
AS_IF([[test $DX_FLAG_man -eq 1]],
[[DX_SNIPPET_man="## ------------------------------ ##
## Rules specific for MAN output. ##
## ------------------------------ ##
DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/man]])[
"]],
[[DX_SNIPPET_man=""]])
AS_IF([[test $DX_FLAG_rtf -eq 1]],
[[DX_SNIPPET_rtf="## ------------------------------ ##
## Rules specific for RTF output. ##
## ------------------------------ ##
DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/rtf]])[
"]],
[[DX_SNIPPET_rtf=""]])
AS_IF([[test $DX_FLAG_xml -eq 1]],
[[DX_SNIPPET_xml="## ------------------------------ ##
## Rules specific for XML output. ##
## ------------------------------ ##
DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/xml]])[
"]],
[[DX_SNIPPET_xml=""]])
AS_IF([[test $DX_FLAG_ps -eq 1]],
[[DX_SNIPPET_ps="## ----------------------------- ##
## Rules specific for PS output. ##
## ----------------------------- ##
DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[
DX_PS_GOAL = doxygen-ps
doxygen-ps: \$(DX_CLEAN_PS)
]m4_foreach([DX_i], [DX_loop],
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
\$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
\$(DX_LATEX) refman.tex; \\
\$(DX_MAKEINDEX) refman.idx; \\
\$(DX_LATEX) refman.tex; \\
countdown=5; \\
while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
refman.log > /dev/null 2>&1 \\
&& test \$\$countdown -gt 0; do \\
\$(DX_LATEX) refman.tex; \\
countdown=\`expr \$\$countdown - 1\`; \\
done; \\
\$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi
]])["]],
[[DX_SNIPPET_ps=""]])
AS_IF([[test $DX_FLAG_pdf -eq 1]],
[[DX_SNIPPET_pdf="## ------------------------------ ##
## Rules specific for PDF output. ##
## ------------------------------ ##
DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[
DX_PDF_GOAL = doxygen-pdf
doxygen-pdf: \$(DX_CLEAN_PDF)
]m4_foreach([DX_i], [DX_loop],
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
\$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
\$(DX_PDFLATEX) refman.tex; \\
\$(DX_MAKEINDEX) refman.idx; \\
\$(DX_PDFLATEX) refman.tex; \\
countdown=5; \\
while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
refman.log > /dev/null 2>&1 \\
&& test \$\$countdown -gt 0; do \\
\$(DX_PDFLATEX) refman.tex; \\
countdown=\`expr \$\$countdown - 1\`; \\
done; \\
mv refman.pdf ../\$(PACKAGE).pdf
]])["]],
[[DX_SNIPPET_pdf=""]])
AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]],
[[DX_SNIPPET_latex="## ------------------------------------------------- ##
## Rules specific for LaTeX (shared for PS and PDF). ##
## ------------------------------------------------- ##
DX_V_LATEX = \$(_DX_v_LATEX_\$(V))
_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY))
_DX_v_LATEX_0 = @echo \" LATEX \" \$][@;
DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/latex]])[
"]],
[[DX_SNIPPET_latex=""]])
AS_IF([[test $DX_FLAG_doc -eq 1]],
[[DX_SNIPPET_doc="## --------------------------------- ##
## Format-independent Doxygen rules. ##
## --------------------------------- ##
${DX_SNIPPET_html}\
${DX_SNIPPET_chm}\
${DX_SNIPPET_man}\
${DX_SNIPPET_rtf}\
${DX_SNIPPET_xml}\
${DX_SNIPPET_ps}\
${DX_SNIPPET_pdf}\
${DX_SNIPPET_latex}\
DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V))
_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY))
_DX_v_DXGEN_0 = @echo \" DXGEN \" \$<;
.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
doxygen-run:]m4_foreach([DX_i], [DX_loop],
[[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[
doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
]m4_foreach([DX_i], [DX_loop],
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) \$(pkginclude_HEADERS)
\$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[)
\$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) \$(DX_CONFIG]DX_i[)
\$(A""M_V_at)echo Timestamp >\$][@
]])dnl
[DX_CLEANFILES = \\]
m4_foreach([DX_i], [DX_loop],
[[ \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\
]])dnl
[ -r \\
\$(DX_CLEAN_HTML) \\
\$(DX_CLEAN_CHM) \\
\$(DX_CLEAN_CHI) \\
\$(DX_CLEAN_MAN) \\
\$(DX_CLEAN_RTF) \\
\$(DX_CLEAN_XML) \\
\$(DX_CLEAN_PS) \\
\$(DX_CLEAN_PDF) \\
\$(DX_CLEAN_LATEX)
DX_INSTALL_DOCS = \\
\$(DX_CLEAN_HTML) \\
\$(DX_CLEAN_CHM) \\
\$(DX_CLEAN_CHI) \\
\$(DX_CLEAN_RTF) \\
\$(DX_CLEAN_XML) \\
\$(DX_CLEAN_PS) \\
\$(DX_CLEAN_PDF) \\
\$(DX_CLEAN_LATEX)
"]],
[[DX_SNIPPET_doc=""]])
AC_SUBST([DX_RULES],
["${DX_SNIPPET_doc}"])dnl
AM_SUBST_NOTMAKE([DX_RULES])
#For debugging:
#echo DX_FLAG_doc=$DX_FLAG_doc
#echo DX_FLAG_dot=$DX_FLAG_dot
#echo DX_FLAG_man=$DX_FLAG_man
#echo DX_FLAG_html=$DX_FLAG_html
#echo DX_FLAG_chm=$DX_FLAG_chm
#echo DX_FLAG_chi=$DX_FLAG_chi
#echo DX_FLAG_rtf=$DX_FLAG_rtf
#echo DX_FLAG_xml=$DX_FLAG_xml
#echo DX_FLAG_pdf=$DX_FLAG_pdf
#echo DX_FLAG_ps=$DX_FLAG_ps
#echo DX_ENV=$DX_ENV
])

View File

@ -47,6 +47,11 @@ case "$enable_openssl" in
AC_SUBST(OPENSSL_LIBS)
case "$have_openssl" in
yes) AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl]) ;;
*) AC_MSG_ERROR([openssl is a must but can not be found. You should add the \
directory containing `openssl.pc' to the `PKG_CONFIG_PATH' environment variable, \
or set `CFLAGS' and `LDFLAGS' directly for openssl, or use `--disable-openssl' \
to disable support for openssl encryption])
;;
esac
;;
esac

View File

@ -34,6 +34,9 @@ static inline BIO_METHOD *BIO_meth_new(int type, const char *name)
#define TLS_method SSLv23_method
#define X509_getm_notBefore X509_get_notBefore
#define X509_getm_notAfter X509_get_notAfter
#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) */

25
poll.c
View File

@ -53,6 +53,17 @@
#include "evthread-internal.h"
#include "time-internal.h"
/* Since Linux 2.6.17, poll is able to report about peer half-closed connection
using special POLLRDHUP flag on a read event.
*/
#if !defined(POLLRDHUP)
#define POLLRDHUP 0
#define EARLY_CLOSE_IF_HAVE_RDHUP 0
#else
#define EARLY_CLOSE_IF_HAVE_RDHUP EV_FEATURE_EARLY_CLOSE
#endif
struct pollidx {
int idxplus1;
};
@ -79,8 +90,8 @@ const struct eventop pollops = {
poll_del,
poll_dispatch,
poll_dealloc,
0, /* doesn't need_reinit */
EV_FEATURE_FDS,
1, /* need_reinit */
EV_FEATURE_FDS|EARLY_CLOSE_IF_HAVE_RDHUP,
sizeof(struct pollidx),
};
@ -204,6 +215,8 @@ poll_dispatch(struct event_base *base, struct timeval *tv)
res |= EV_READ;
if (what & POLLOUT)
res |= EV_WRITE;
if (what & POLLRDHUP)
res |= EV_CLOSED;
if (res == 0)
continue;
@ -222,7 +235,7 @@ poll_add(struct event_base *base, int fd, short old, short events, void *idx_)
int i;
EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
if (!(events & (EV_READ|EV_WRITE)))
if (!(events & (EV_READ|EV_WRITE|EV_CLOSED)))
return (0);
poll_check_ok(pop);
@ -265,6 +278,8 @@ poll_add(struct event_base *base, int fd, short old, short events, void *idx_)
pfd->events |= POLLOUT;
if (events & EV_READ)
pfd->events |= POLLIN;
if (events & EV_CLOSED)
pfd->events |= POLLRDHUP;
poll_check_ok(pop);
return (0);
@ -283,7 +298,7 @@ poll_del(struct event_base *base, int fd, short old, short events, void *idx_)
int i;
EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
if (!(events & (EV_READ|EV_WRITE)))
if (!(events & (EV_READ|EV_WRITE|EV_CLOSED)))
return (0);
poll_check_ok(pop);
@ -297,6 +312,8 @@ poll_del(struct event_base *base, int fd, short old, short events, void *idx_)
pfd->events &= ~POLLIN;
if (events & EV_WRITE)
pfd->events &= ~POLLOUT;
if (events & EV_CLOSED)
pfd->events &= ~POLLRDHUP;
poll_check_ok(pop);
if (pfd->events)
/* Another event cares about that fd. */

View File

@ -225,8 +225,8 @@ main(int c, char **v) {
res = evdns_base_resolv_conf_parse(evdns_base,
DNS_OPTION_NAMESERVERS, o.resolv_conf);
if (res < 0) {
fprintf(stderr, "Couldn't configure nameservers");
if (res) {
fprintf(stderr, "Couldn't configure nameservers\n");
return 1;
}
}

View File

@ -129,10 +129,10 @@ main(int argc, char **argv)
fprintf(stderr, "Write data to %s\n", fifo);
#endif
/* Initalize the event library */
/* Initialize the event library */
base = event_base_new();
/* Initalize one event */
/* Initialize one event */
#ifdef _WIN32
evfifo = event_new(base, (evutil_socket_t)socket, EV_READ|EV_PERSIST, fifo_read,
event_self_cbarg());

View File

@ -42,7 +42,7 @@ main(int argc, char **argv)
struct evconnlistener *listener;
struct event *signal_event;
struct sockaddr_in sin;
struct sockaddr_in sin = {0};
#ifdef _WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
@ -54,7 +54,6 @@ main(int argc, char **argv)
return 1;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);

View File

@ -23,15 +23,44 @@ struct connect_base
struct evhttp_uri *location;
};
static struct evhttp_uri* uri_parse(const char *str)
{
struct evhttp_uri *uri;
VERIFY(uri = evhttp_uri_parse(str));
VERIFY(evhttp_uri_get_host(uri));
VERIFY(evhttp_uri_get_port(uri) > 0);
return uri;
}
static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX])
{
struct evhttp_uri *path;
VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
path = evhttp_uri_parse(buffer);
evhttp_uri_set_scheme(path, NULL);
evhttp_uri_set_userinfo(path, 0);
evhttp_uri_set_host(path, NULL);
evhttp_uri_set_port(path, -1);
VERIFY(evhttp_uri_join(path, buffer, URL_MAX));
return buffer;
}
static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX])
{
VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
VERIFY(evhttp_uri_get_host(uri));
VERIFY(evhttp_uri_get_port(uri) > 0);
evutil_snprintf(buffer, URL_MAX, "%s:%d",
evhttp_uri_get_host(uri), evhttp_uri_get_port(uri));
return buffer;
}
static void get_cb(struct evhttp_request *req, void *arg)
{
ev_ssize_t len;
struct evbuffer *evbuf;
struct evhttp_connection *evcon;
VERIFY(req);
evcon = evhttp_request_get_connection(req);
VERIFY(evcon);
evbuf = evhttp_request_get_input_buffer(req);
len = evbuffer_get_length(evbuf);
@ -41,26 +70,26 @@ static void get_cb(struct evhttp_request *req, void *arg)
static void connect_cb(struct evhttp_request *proxy_req, void *arg)
{
char buffer[URL_MAX];
struct connect_base *base = arg;
struct evhttp_connection *evcon = base->evcon;
struct evhttp_uri *location = base->location;
struct evhttp_request *req;
char buffer[URL_MAX];
VERIFY(proxy_req);
if (evcon) {
struct evhttp_request *req = evhttp_request_new(get_cb, NULL);
evhttp_add_header(req->output_headers, "Connection", "close");
VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
evhttp_uri_join(location, buffer, URL_MAX)));
}
VERIFY(evcon);
req = evhttp_request_new(get_cb, NULL);
evhttp_add_header(req->output_headers, "Connection", "close");
evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location));
VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
uri_path(location, buffer)));
}
int main(int argc, const char **argv)
{
char buffer[URL_MAX];
char hostport[URL_MAX];
struct evhttp_uri *host_port;
struct evhttp_uri *location;
struct evhttp_uri *proxy;
@ -75,28 +104,8 @@ int main(int argc, const char **argv)
return 1;
}
{
VERIFY(proxy = evhttp_uri_parse(argv[1]));
VERIFY(evhttp_uri_get_host(proxy));
VERIFY(evhttp_uri_get_port(proxy) > 0);
}
{
host_port = evhttp_uri_parse(argv[2]);
evhttp_uri_set_scheme(host_port, NULL);
evhttp_uri_set_userinfo(host_port, NULL);
evhttp_uri_set_path(host_port, NULL);
evhttp_uri_set_query(host_port, NULL);
evhttp_uri_set_fragment(host_port, NULL);
VERIFY(evhttp_uri_get_host(host_port));
VERIFY(evhttp_uri_get_port(host_port) > 0);
}
{
location = evhttp_uri_parse(argv[2]);
evhttp_uri_set_scheme(location, NULL);
evhttp_uri_set_userinfo(location, 0);
evhttp_uri_set_host(location, NULL);
evhttp_uri_set_port(location, -1);
}
proxy = uri_parse(argv[1]);
location = uri_parse(argv[2]);
VERIFY(base = event_base_new());
VERIFY(evcon = evhttp_connection_base_new(base, NULL,
@ -105,17 +114,18 @@ int main(int argc, const char **argv)
connect_base.location = location;
VERIFY(req = evhttp_request_new(connect_cb, &connect_base));
uri_hostport(location, hostport);
evhttp_add_header(req->output_headers, "Connection", "keep-alive");
evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive");
evutil_snprintf(buffer, URL_MAX, "%s:%d",
evhttp_uri_get_host(host_port), evhttp_uri_get_port(host_port));
evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, buffer);
evhttp_add_header(req->output_headers, "Host", hostport);
evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport);
event_base_dispatch(base);
evhttp_connection_free(evcon);
event_base_free(base);
evhttp_uri_free(proxy);
evhttp_uri_free(host_port);
evhttp_uri_free(location);
return 0;
}

View File

@ -99,14 +99,14 @@ static const struct table_entry {
{ NULL, NULL },
};
struct options
{
struct options {
int port;
int iocp;
int verbose;
int unlink;
const char *unixsock;
const char *docroot;
};
/* Try to guess a good content-type for 'path' */
@ -182,7 +182,7 @@ static void
send_document_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb = NULL;
const char *docroot = arg;
struct options *o = arg;
const char *uri = evhttp_request_get_uri(req);
struct evhttp_uri *decoded = NULL;
const char *path;
@ -222,12 +222,12 @@ send_document_cb(struct evhttp_request *req, void *arg)
if (strstr(decoded_path, ".."))
goto err;
len = strlen(decoded_path)+strlen(docroot)+2;
len = strlen(decoded_path)+strlen(o->docroot)+2;
if (!(whole_path = malloc(len))) {
perror("malloc");
goto err;
}
evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path);
evutil_snprintf(whole_path, len, "%s/%s", o->docroot, decoded_path);
if (stat(whole_path, &st)<0) {
goto err;
@ -346,12 +346,13 @@ done:
static void
print_usage(FILE *out, const char *prog, int exit_code)
{
fprintf(out, "Syntax: [ OPTS ] %s <docroot>\n", prog);
fprintf(out, " -p - port\n");
fprintf(out, " -U - bind to unix socket\n");
fprintf(out, " -u - unlink unix socket before bind\n");
fprintf(out, " -I - IOCP\n");
fprintf(out, " -v - verbosity, enables libevent debug logging too\n");
fprintf(out,
"Syntax: %s [ OPTS ] <docroot>\n"
" -p - port\n"
" -U - bind to unix socket\n"
" -u - unlink unix socket before bind\n"
" -I - IOCP\n"
" -v - verbosity, enables libevent debug logging too\n", prog);
exit(exit_code);
}
static struct options
@ -374,9 +375,10 @@ parse_opts(int argc, char **argv)
}
}
if (optind >= argc || (argc-optind) > 1) {
if (optind >= argc || (argc - optind) > 1) {
print_usage(stdout, argv[0], 1);
}
o.docroot = argv[optind];
return o;
}
@ -504,7 +506,7 @@ main(int argc, char **argv)
/* We want to accept arbitrary requests, so we need to set a "generic"
* cb. We can also add callbacks for specific paths. */
evhttp_set_gencb(http, send_document_cb, argv[1]);
evhttp_set_gencb(http, send_document_cb, &o);
if (o.unixsock) {
#ifdef EVENT__HAVE_STRUCT_SOCKADDR_UN

View File

@ -118,7 +118,6 @@ err_openssl(const char *func)
exit(1);
}
#ifndef _WIN32
/* See http://archives.seul.org/libevent/users/Jan-2013/msg00039.html */
static int cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg)
{
@ -181,6 +180,35 @@ static int cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg)
return 0;
}
}
#ifdef _WIN32
static int
add_cert_for_store(X509_STORE *store, const char *name)
{
HCERTSTORE sys_store = NULL;
PCCERT_CONTEXT ctx = NULL;
int r = 0;
sys_store = CertOpenSystemStore(0, name);
if (!sys_store) {
err("failed to open system certificate store");
return -1;
}
while ((ctx = CertEnumCertificatesInStore(sys_store, ctx))) {
X509 *x509 = d2i_X509(NULL, (unsigned char const **)&ctx->pbCertEncoded,
ctx->cbCertEncoded);
if (x509) {
X509_STORE_add_cert(store, x509);
X509_free(x509);
} else {
r = -1;
err_openssl("d2i_X509");
break;
}
}
CertCloseStore(sys_store, 0);
return r;
}
#endif
int
@ -335,17 +363,22 @@ main(int argc, char **argv)
goto error;
}
#ifndef _WIN32
/* TODO: Add certificate loading on Windows as well */
if (crt == NULL) {
X509_STORE *store;
/* Attempt to use the system's trusted root certificates. */
store = SSL_CTX_get_cert_store(ssl_ctx);
#ifdef _WIN32
if (add_cert_for_store(store, "CA") < 0 ||
add_cert_for_store(store, "AuthRoot") < 0 ||
add_cert_for_store(store, "ROOT") < 0) {
goto error;
}
#else // _WIN32
if (X509_STORE_set_default_paths(store) != 1) {
err_openssl("X509_STORE_set_default_paths");
goto error;
}
#endif // _WIN32
} else {
if (SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL) != 1) {
err_openssl("SSL_CTX_load_verify_locations");
@ -376,9 +409,6 @@ main(int argc, char **argv)
* "wrapping" OpenSSL's routine, not replacing it. */
SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback,
(void *) host);
#else // _WIN32
(void)crt;
#endif // _WIN32
// Create event base
base = event_base_new();

View File

@ -25,6 +25,9 @@ sample_https_client_SOURCES = \
sample/hostcheck.c \
sample/openssl_hostname_validation.c
sample_https_client_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
if BUILD_WIN32
sample_https_client_LDADD += -lcrypt32
endif
sample_https_client_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
noinst_HEADERS += \
sample/hostcheck.h \

View File

@ -44,8 +44,9 @@ signal_cb(evutil_socket_t fd, short event, void *arg)
int
main(int argc, char **argv)
{
struct event *signal_int;
struct event *signal_int = NULL;
struct event_base* base;
int ret = 0;
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
@ -55,18 +56,28 @@ main(int argc, char **argv)
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
/* Initalize the event library */
/* Initialize the event library */
base = event_base_new();
if (!base) {
ret = 1;
goto out;
}
/* Initalize one event */
/* Initialize one event */
signal_int = evsignal_new(base, SIGINT, signal_cb, event_self_cbarg());
if (!signal_int) {
ret = 2;
goto out;
}
event_add(signal_int, NULL);
event_base_dispatch(base);
event_free(signal_int);
event_base_free(base);
return (0);
out:
if (signal_int)
event_free(signal_int);
if (base)
event_base_free(base);
return ret;
}

View File

@ -88,10 +88,10 @@ main(int argc, char **argv)
flags = 0;
}
/* Initalize the event library */
/* Initialize the event library */
base = event_base_new();
/* Initalize one event */
/* Initialize one event */
event_assign(&timeout, base, -1, flags, timeout_cb, (void*) &timeout);
evutil_timerclear(&tv);

View File

@ -98,7 +98,7 @@ const struct eventop selectops = {
select_del,
select_dispatch,
select_dealloc,
0, /* doesn't need reinit. */
1, /* need_reinit. */
EV_FEATURE_FDS,
0,
};

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.1.2)
if (POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
project(verify)
# set(CMAKE_VERBOSE_MAKEFILE 1)
if(NOT ${EVENT__CODE_COMPONENT} STREQUAL "")
string(TOUPPER ${EVENT__CODE_COMPONENT} _UPPER_COMPONENT)
endif()
find_package(Libevent 2.1.0 REQUIRED COMPONENTS ${EVENT__LINK_COMPONENT})
add_definitions(-DEVENT_EXPORT_TEST_COMPONENT_${_UPPER_COMPONENT})
add_executable(test-export test-export.c)
target_link_libraries(test-export ${LIBEVENT_LIBRARIES})
enable_testing()
add_test(test-export test-export)

122
test-export/test-export.c Normal file
View File

@ -0,0 +1,122 @@
#include <event2/event.h>
#if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA)
#include "event2/http.h"
#include "event2/rpc.h"
#include <event2/dns.h>
#elif defined(EVENT_EXPORT_TEST_COMPONENT_PTHREADS)
#include <event2/thread.h>
#elif defined(EVENT_EXPORT_TEST_COMPONENT_OPENSSL)
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <event2/bufferevent_ssl.h>
#endif
#if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA)
static int
test()
{
struct event_base *base = NULL;
struct evhttp *http = NULL;
struct evdns_base *dns_base = NULL;
struct evrpc_base *rpc_base = NULL;
base = event_base_new();
if (base) {
http = evhttp_new(base);
dns_base = evdns_base_new(base,
EVDNS_BASE_DISABLE_WHEN_INACTIVE);
}
if (http)
rpc_base = evrpc_init(http);
if (base)
event_base_free(base);
if (http)
evhttp_free(http);
if (rpc_base)
evrpc_free(rpc_base);
if (dns_base)
evdns_base_free(dns_base, 0);
return 0;
}
#elif defined(EVENT_EXPORT_TEST_COMPONENT_PTHREADS)
static int
test()
{
return evthread_use_pthreads();
}
#elif defined(EVENT_EXPORT_TEST_COMPONENT_OPENSSL)
static int
test()
{
struct event_base *base = NULL;
SSL_CTX *ssl_ctx = NULL;
SSL *ssl = NULL;
struct bufferevent *bev;
int r = 1;
SSL_library_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
base = event_base_new();
if (!base) {
goto error;
}
ssl_ctx = SSL_CTX_new(SSLv23_method());
if (!ssl_ctx) {
goto error;
}
ssl = SSL_new(ssl_ctx);
if (ssl == NULL) {
goto error;
}
bev = bufferevent_openssl_socket_new(base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
if (bev == NULL) {
goto error;
}
r = 0;
error:
if (base)
event_base_free(base);
if (ssl_ctx)
SSL_CTX_free(ssl_ctx);
if (ssl)
SSL_free(ssl);
return r;
}
#else
static int
test()
{
struct event_base *base = NULL;
base = event_base_new();
if (base)
event_base_free(base);
return 0;
}
#endif
int
main(int argc, char const *argv[])
{
int r = 0;
#ifdef _WIN32
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
#endif
r = test();
#ifdef _WIN32
WSACleanup();
#endif
return r;
}

199
test-export/test-export.py Normal file
View File

@ -0,0 +1,199 @@
#!/usr/bin/env python3
#
# Check if find_package(Libevent COMPONENTS xxx) can get the correct library.
# Note: this script has only been tested on python3.
# Usage:
# cd cmake-build-dir
# cmake <options> .. && cmake --build .
# python /path/to/test-export.py [static|shared]
import sys
import os
import shutil
import platform
import subprocess
import tempfile
results = ("success", "failure")
FNULL = open(os.devnull, 'wb')
script_dir = os.path.split(os.path.realpath(sys.argv[0]))[0]
# working_dir is cmake build dir
working_dir = os.getcwd()
if len(sys.argv) > 1 and sys.argv[1] == "static":
link_type = sys.argv[1]
else:
link_type = "shared"
def exec_cmd(cmd, silent):
if silent:
p = subprocess.Popen(cmd, stdout=FNULL, stderr=FNULL, shell=True)
else:
p = subprocess.Popen(cmd, shell=True)
p.communicate()
return p.poll()
def link_and_run(link, code):
"""Check if the source code matches the library component.
Compile source code relative to one component and link to another component.
Then run the generated executor.
Args:
link: The name of component that the source code will link with.
code: The source code related component name.
Returns:
Returns 0 if links and runs successfully, otherwise 1.
"""
exec_cmd("cmake --build . --target clean", True)
arch = ''
if platform.system() == "Windows":
arch = '-A x64'
cmd = 'cmake .. %s -DEVENT__LINK_COMPONENT=%s -DEVENT__CODE_COMPONENT=%s' % (
arch, link, code)
if link_type == "static":
cmd = "".join([cmd, " -DLIBEVENT_STATIC_LINK=1"])
r = exec_cmd(cmd, True)
if r == 0:
r = exec_cmd('cmake --build .', True)
if r == 0:
r = exec_cmd('ctest', True)
if r != 0:
r = 1
return r
# expect 0:success 1:failure
def testcase(link, code, expect):
r = link_and_run(link, code)
if link == "":
link = "all"
if code == "":
code = "all"
if r != expect:
print('[test-export] fail: link %s and run %s expects %s but gets %s.' %
(link, code, results[expect], results[r]))
sys.exit(1)
else:
print('[test-export] success: link %s and run %s expects and gets %s.' %
(link, code, results[r]))
# Dependency relationships between libevent libraries:
# core: none
# extra: core
# pthreads: core,pthread
# openssl: core,openssl
def test_group():
testcase("core", "core", 0)
testcase("extra", "extra", 0)
testcase("openssl", "openssl", 0)
testcase("", "", 0)
testcase("extra", "core", 0)
testcase("openssl", "core", 0)
testcase("core", "extra", 1)
testcase("core", "openssl", 1)
testcase("extra", "openssl", 1)
testcase("openssl", "extra", 1)
if platform.system() != "Windows":
testcase("pthreads", "pthreads", 0)
testcase("pthreads", "core", 0)
testcase("core", "pthreads", 1)
testcase("extra", "pthreads", 1)
testcase("pthreads", "extra", 1)
testcase("pthreads", "openssl", 1)
testcase("openssl", "pthreads", 1)
def config_restore():
if os.path.isfile("tempconfig") and not os.path.isfile("LibeventConfig.cmake"):
os.rename("tempconfig", "LibeventConfig.cmake")
def config_backup():
if os.path.isfile("tempconfig"):
os.remove("tempconfig")
if os.path.isfile("LibeventConfig.cmake"):
os.rename("LibeventConfig.cmake", "tempconfig")
shutil.rmtree(os.path.join(script_dir, "build"), ignore_errors=True)
def run_test_group():
os.chdir(script_dir)
if not os.path.isdir("build"):
os.mkdir("build")
os.chdir("build")
test_group()
os.chdir(working_dir)
need_exportdll = False
if link_type == "shared" and platform.system() == "Windows":
need_exportdll = True
# On Windows, we need to add the directory containing the dll to the
# 'PATH' environment variable so that the program can call it.
def export_dll(dir):
if need_exportdll:
os.environ["PATH"] += os.pathsep + dir
def unexport_dll(dir):
if need_exportdll:
paths = os.environ["PATH"].split(os.pathsep)
paths = list(set(paths))
if dir in paths:
paths.remove(dir)
os.environ["PATH"] = os.pathsep.join(paths)
print("[test-export] use %s library" % link_type)
# Test for build tree.
print("[test-export] test for build tree")
dllpath = os.path.join(working_dir, "bin", "Debug")
config_restore()
os.environ["CMAKE_PREFIX_PATH"] = working_dir
export_dll(dllpath)
run_test_group()
del os.environ["CMAKE_PREFIX_PATH"]
unexport_dll(dllpath)
# Install libevent libraries to system path. Remove LibeventConfig.cmake
# from build directory to avoid confusion when using find_package().
print("[test-export] test for install tree(in system-wide path)")
if platform.system() == "Windows":
prefix = "C:\\Program Files\\libevent"
dllpath = os.path.join(prefix, "lib")
else:
prefix = "/usr/local"
exec_cmd('cmake -DCMAKE_INSTALL_PREFIX="%s" ..' % prefix, True)
exec_cmd('cmake --build . --target install', True)
config_backup()
os.environ["CMAKE_PREFIX_PATH"] = os.path.join(prefix, "lib/cmake/libevent")
export_dll(dllpath)
run_test_group()
unexport_dll(dllpath)
del os.environ["CMAKE_PREFIX_PATH"]
# Uninstall the libraries installed in the above steps. Install the libraries
# into a temporary directory. Same as above, remove LibeventConfig.cmake from
# build directory to avoid confusion when using find_package().
print("[test-export] test for install tree(in non-system-wide path)")
exec_cmd("cmake --build . --target uninstall", True)
tempdir = tempfile.TemporaryDirectory()
cmd = 'cmake -DCMAKE_INSTALL_PREFIX="%s" ..' % tempdir.name
exec_cmd(cmd, True)
exec_cmd("cmake --build . --target install", True)
config_backup()
os.environ["CMAKE_PREFIX_PATH"] = os.path.join(tempdir.name, "lib/cmake/libevent")
dllpath = os.path.join(tempdir.name, "lib")
export_dll(dllpath)
run_test_group()
unexport_dll(dllpath)
del os.environ["CMAKE_PREFIX_PATH"]
config_restore()
print("[test-export] all testcases have run successfully")

View File

@ -70,6 +70,7 @@ static int writes, failures;
static evutil_socket_t *pipes;
static int num_pipes, num_active, num_writes;
static struct event *events;
static struct event_base *base;
static void
@ -105,11 +106,11 @@ run_once(void)
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
if (event_initialized(&events[i]))
event_del(&events[i]);
event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i);
event_assign(&events[i], base, cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i);
event_add(&events[i], NULL);
}
event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);
event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK);
fired = 0;
space = num_pipes / num_active;
@ -123,7 +124,7 @@ run_once(void)
int xcount = 0;
evutil_gettimeofday(&ts, NULL);
do {
event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);
event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK);
xcount++;
} while (count != fired);
evutil_gettimeofday(&te, NULL);
@ -147,6 +148,9 @@ main(int argc, char **argv)
int i, c;
struct timeval *tv;
evutil_socket_t *cp;
const char **methods;
const char *method = NULL;
struct event_config *cfg = NULL;
#ifdef _WIN32
WSADATA WSAData;
@ -155,7 +159,7 @@ main(int argc, char **argv)
num_pipes = 100;
num_active = 1;
num_writes = num_pipes;
while ((c = getopt(argc, argv, "n:a:w:")) != -1) {
while ((c = getopt(argc, argv, "n:a:w:m:l")) != -1) {
switch (c) {
case 'n':
num_pipes = atoi(optarg);
@ -166,6 +170,16 @@ main(int argc, char **argv)
case 'w':
num_writes = atoi(optarg);
break;
case 'm':
method = optarg;
break;
case 'l':
methods = event_get_supported_methods();
fprintf(stdout, "Using Libevent %s. Available methods are:\n",
event_get_version());
for (i = 0; methods[i] != NULL; ++i)
printf(" %s\n", methods[i]);
exit(0);
default:
fprintf(stderr, "Illegal argument \"%c\"\n", c);
exit(1);
@ -187,7 +201,16 @@ main(int argc, char **argv)
exit(1);
}
event_init();
if (method != NULL) {
cfg = event_config_new();
methods = event_get_supported_methods();
for (i = 0; methods[i] != NULL; ++i)
if (strcmp(methods[i], method))
event_config_avoid_method(cfg, methods[i]);
base = event_base_new_with_config(cfg);
event_config_free(cfg);
} else
base = event_base_new();
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
#ifdef USE_PIPES

View File

@ -31,10 +31,6 @@
#include <windows.h>
#endif
#ifdef EVENT__HAVE_PTHREADS
#include <pthread.h>
#endif
#include "event2/event-config.h"
#include <sys/types.h>
@ -73,6 +69,7 @@
#include "time-internal.h"
#include "regress.h"
#include "regress_thread.h"
#ifndef _WIN32
#include "regress.gen.h"
@ -390,7 +387,7 @@ record_event_cb(evutil_socket_t s, short what, void *ptr)
}
static void
test_simpleclose(void *ptr)
test_simpleclose_rw(void *ptr)
{
/* Test that a close of FD is detected as a read and as a write. */
struct event_base *base = event_base_new();
@ -472,6 +469,56 @@ end:
event_base_free(base);
}
static void
test_simpleclose(void *ptr)
{
struct basic_test_data *data = ptr;
struct event_base *base = data->base;
evutil_socket_t *pair = data->pair;
const char *flags = (const char *)data->setup_data;
int et = !!strstr(flags, "ET");
int persist = !!strstr(flags, "persist");
short events = EV_CLOSED | (et ? EV_ET : 0) | (persist ? EV_PERSIST : 0);
struct event *ev = NULL;
short got_event;
if (!(event_base_get_features(data->base) & EV_FEATURE_EARLY_CLOSE))
tt_skip();
/* XXX: should this code moved to regress_et.c ? */
if (et && !(event_base_get_features(data->base) & EV_FEATURE_ET))
tt_skip();
ev = event_new(base, pair[0], events, record_event_cb, &got_event);
tt_assert(ev);
tt_assert(!event_add(ev, NULL));
got_event = 0;
if (strstr(flags, "close")) {
tt_assert(!evutil_closesocket(pair[1]));
/* avoid closing in setup routines */
pair[1] = -1;
} else if (strstr(flags, "shutdown")) {
tt_assert(!shutdown(pair[1], EVUTIL_SHUT_WR));
} else {
tt_abort_msg("unknown flags");
}
/* w/o edge-triggerd but w/ persist it will not stop */
if (!et && persist) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10000;
tt_assert(!event_base_loopexit(base, &tv));
}
tt_int_op(event_base_loop(base, EVLOOP_NONBLOCK), ==, !persist);
tt_int_op(got_event, ==, (events & ~EV_PERSIST));
end:
if (ev)
event_free(ev);
}
static void
test_multiple(void)
@ -979,7 +1026,7 @@ test_fork(void)
evutil_closesocket(child_pair[1]);
}
#ifdef EVENT__HAVE_PTHREADS
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
static void* del_wait_thread(void *arg)
{
struct timeval tv_start, tv_end;
@ -1007,14 +1054,14 @@ static void
test_del_wait(void)
{
struct event ev;
pthread_t thread;
THREAD_T thread;
setup_test("event_del will wait: ");
event_set(&ev, pair[1], EV_READ|EV_PERSIST, del_wait_cb, &ev);
event_add(&ev, NULL);
pthread_create(&thread, NULL, del_wait_thread, NULL);
THREAD_START(thread, del_wait_thread, NULL);
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
tt_fail_perror("write");
@ -1033,7 +1080,7 @@ test_del_wait(void)
test_timeval_diff_eq(&tv_start, &tv_end, 270);
}
pthread_join(thread, NULL);
THREAD_JOIN(thread);
tt_int_op(test_ok, ==, 1);
@ -1051,14 +1098,14 @@ static void
test_del_notify(void)
{
struct event ev;
pthread_t thread;
THREAD_T thread;
test_ok = 1;
event_set(&ev, -1, EV_READ, null_cb, &ev);
event_add(&ev, NULL);
pthread_create(&thread, NULL, test_del_notify_thread, NULL);
THREAD_START(thread, test_del_notify_thread, NULL);
{
struct timeval delay = { 0, 1000 };
@ -1066,7 +1113,7 @@ test_del_notify(void)
}
event_del(&ev);
pthread_join(thread, NULL);
THREAD_JOIN(thread);
}
#endif
@ -3464,8 +3511,35 @@ struct testcase_t main_testcases[] = {
LEGACY(simpleread, TT_ISOLATED),
LEGACY(simpleread_multiple, TT_ISOLATED),
LEGACY(simplewrite, TT_ISOLATED),
{ "simpleclose", test_simpleclose, TT_FORK, &basic_setup,
NULL },
{ "simpleclose_rw", test_simpleclose_rw, TT_FORK, &basic_setup, NULL },
/* simpleclose */
{ "simpleclose_close", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"close" },
{ "simpleclose_shutdown", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"shutdown" },
/* simpleclose_*_persist */
{ "simpleclose_close_persist", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"close_persist" },
{ "simpleclose_shutdown_persist", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"shutdown_persist" },
/* simpleclose_*_et */
{ "simpleclose_close_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"close_ET" },
{ "simpleclose_shutdown_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"shutdown_ET" },
/* simpleclose_*_persist_et */
{ "simpleclose_close_persist_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"close_persist_ET" },
{ "simpleclose_shutdown_persist_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, (void *)"shutdown_persist_ET" },
LEGACY(multiple, TT_ISOLATED),
LEGACY(persistent, TT_ISOLATED),
LEGACY(combined, TT_ISOLATED),
@ -3505,8 +3579,8 @@ struct testcase_t main_testcases[] = {
#ifndef _WIN32
LEGACY(fork, TT_ISOLATED),
#endif
#ifdef EVENT__HAVE_PTHREADS
/** TODO: support win32 */
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
#endif

View File

@ -95,6 +95,7 @@ extern int libevent_tests_running_in_debug_mode;
#define TT_NO_LOGS (TT_FIRST_USER_FLAG<<5)
#define TT_ENABLE_IOCP_FLAG (TT_FIRST_USER_FLAG<<6)
#define TT_ENABLE_IOCP (TT_ENABLE_IOCP_FLAG|TT_NEED_THREADS)
#define TT_ENABLE_DEBUG_MODE (TT_ENABLE_IOCP_FLAG<<7)
/* All the flags that a legacy test needs. */
#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE

View File

@ -425,6 +425,36 @@ test_evbuffer_remove_buffer_with_empty3(void *ptr)
evbuffer_free(buf);
}
static void
test_evbuffer_pullup_with_empty(void *ptr)
{
struct evbuffer *buf = NULL;
buf = evbuffer_new();
evbuffer_add(buf, "foo", 3);
evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
evbuffer_validate(buf);
tt_int_op(evbuffer_get_length(buf), ==, 3);
tt_mem_op(evbuffer_pullup(buf, -1), ==, "foo", 3);
evbuffer_free(buf);
buf = evbuffer_new();
evbuffer_validate(buf);
tt_int_op(evbuffer_get_length(buf), ==, 0);
tt_int_op(evbuffer_pullup(buf, -1), ==, NULL);
evbuffer_free(buf);
buf = evbuffer_new();
evbuffer_add(buf, "foo", 3);
evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
evbuffer_validate(buf);
tt_mem_op(evbuffer_pullup(buf, 3), ==, "foo", 3);
end:
if (buf)
evbuffer_free(buf);
}
static void
test_evbuffer_remove_buffer_with_empty_front(void *ptr)
{
@ -2327,7 +2357,7 @@ test_evbuffer_empty_reference_prepend_buffer(void *ptr)
tt_assert(!strncmp((char *)evbuffer_pullup(buf2, -1), "foo", 3));
evbuffer_validate(buf2);
tt_assert(!strncmp((char *)evbuffer_pullup(buf1, -1), "", 0));
tt_assert(evbuffer_pullup(buf1, -1) == NULL);
evbuffer_validate(buf2);
end:
@ -2494,28 +2524,37 @@ end:
static void
test_evbuffer_freeze(void *ptr)
{
struct evbuffer *buf = NULL, *tmp_buf=NULL;
struct basic_test_data *testdata = ptr;
evutil_socket_t *pair = testdata->pair;
struct evbuffer *buf = NULL, *buf_two = NULL, *tmp_buf = NULL;
const char string[] = /* Year's End, Richard Wilbur */
"I've known the wind by water banks to shake\n"
"The late leaves down, which frozen where they fell\n"
"And held in ice as dancers in a spell\n"
"Fluttered all winter long into a lake...";
const int start = !strcmp(ptr, "start");
const int start = !strcmp(testdata->setup_data, "start");
const char tmpfilecontent[] = "file_freeze_test_file";
char *cp;
char charbuf[128];
char *tmpfilename = NULL;
int fd = -1;
int r;
size_t orig_length;
size_t orig_length, len;
struct evbuffer_iovec v[1];
if (!start)
tt_str_op(ptr, ==, "end");
tt_str_op(testdata->setup_data, ==, "end");
buf = evbuffer_new();
buf_two = evbuffer_new();
tmp_buf = evbuffer_new();
tt_assert(tmp_buf);
evbuffer_add(buf, string, strlen(string));
evbuffer_add(buf_two, "abc", 3);
evbuffer_add(tmp_buf, "xyz", 3);
evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
evbuffer_freeze(buf_two, start);
#define FREEZE_EQ(a, startcase, endcase) \
do { \
@ -2544,7 +2583,22 @@ test_evbuffer_freeze(void *ptr)
FREEZE_EQ(r, 0, -1);
r = evbuffer_add_printf(buf, "Hello %s", "world");
FREEZE_EQ(r, 11, -1);
/* TODO: test add_buffer, add_file, read */
r = evbuffer_add_buffer(buf, tmp_buf);
FREEZE_EQ(r, 0, -1);
len = strlen(tmpfilecontent);
fd = regress_make_tmpfile(tmpfilecontent, len, &tmpfilename);
r = evbuffer_add_file(buf, fd, 0, len);
FREEZE_EQ(r, 0, -1);
if (start)
evbuffer_add(tmp_buf, "xyz", 3);
tt_assert(evbuffer_get_length(tmp_buf));
len = evbuffer_get_length(tmp_buf);
evbuffer_write(tmp_buf, pair[0]);
r = evbuffer_read(buf, pair[1], -1);
FREEZE_EQ(r, len, -1);
if (!start)
tt_int_op(orig_length, ==, evbuffer_get_length(buf));
@ -2562,7 +2616,24 @@ test_evbuffer_freeze(void *ptr)
FREEZE_EQ(cp==NULL, 1, 0);
if (cp)
free(cp);
/* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
evbuffer_add(tmp_buf, "xyz", 3);
tt_assert(evbuffer_get_length(tmp_buf));
r = evbuffer_remove_buffer(buf, tmp_buf, 3);
FREEZE_EQ(r, -1, 3);
r = evbuffer_drain(buf, 3);
FREEZE_EQ(r, -1, 0);
r = evbuffer_prepend_buffer(buf, tmp_buf);
FREEZE_EQ(r, -1, 0);
len = evbuffer_get_length(buf);
r = evbuffer_write(buf, pair[0]);
evbuffer_read(tmp_buf, pair[1], -1);
FREEZE_EQ(r, -1, len);
len = evbuffer_get_length(buf_two);
r = evbuffer_write_atmost(buf_two, pair[0], -1);
evbuffer_read(tmp_buf, pair[1], -1);
FREEZE_EQ(r, -1, len);
if (start)
tt_int_op(orig_length, ==, evbuffer_get_length(buf));
@ -2571,8 +2642,16 @@ end:
if (buf)
evbuffer_free(buf);
if (buf_two)
evbuffer_free(buf_two);
if (tmp_buf)
evbuffer_free(tmp_buf);
if (tmpfilename) {
unlink(tmpfilename);
free(tmpfilename);
}
}
static void
@ -2756,11 +2835,12 @@ struct testcase_t evbuffer_testcases[] = {
{ "empty_reference_prepend_buffer", test_evbuffer_empty_reference_prepend_buffer, TT_FORK, NULL, NULL },
{ "peek", test_evbuffer_peek, 0, NULL, NULL },
{ "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
{ "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
{ "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
{ "freeze_start", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"start" },
{ "freeze_end", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"end" },
{ "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
{ "copyout", test_evbuffer_copyout, 0, NULL, NULL},
{ "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL },
{ "pullup_with_empty", test_evbuffer_pullup_with_empty, 0, NULL, NULL },
#define ADDFILE_TEST(name, parameters) \
{ name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \

View File

@ -29,6 +29,19 @@
/* The old tests here need assertions to work. */
#undef NDEBUG
/**
* - clang supports __has_feature
* - gcc supports __SANITIZE_ADDRESS__
*
* Let's set __SANITIZE_ADDRESS__ if __has_feature(address_sanitizer)
*/
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#if !defined(__SANITIZE_ADDRESS__) && __has_feature(address_sanitizer)
#define __SANITIZE_ADDRESS__
#endif
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
@ -203,7 +216,7 @@ static void test_bufferevent_pair_flush_normal(void) { test_bufferevent_impl(1,
static void test_bufferevent_pair_flush_flush(void) { test_bufferevent_impl(1, BEV_FLUSH); }
static void test_bufferevent_pair_flush_finished(void) { test_bufferevent_impl(1, BEV_FINISHED); }
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__)
/**
* Trace lock/unlock/alloc/free for locks.
* (More heavier then evthread_debug*)
@ -787,16 +800,29 @@ end:
bufferevent_free(bev2);
}
static void
close_socket_cb(evutil_socket_t fd, short what, void *arg)
{
evutil_socket_t *fdp = arg;
if (*fdp >= 0) {
evutil_closesocket(*fdp);
*fdp = -1;
}
}
static void
test_bufferevent_connect_fail_eventcb(void *arg)
{
struct basic_test_data *data = arg;
int flags = BEV_OPT_CLOSE_ON_FREE | (long)data->setup_data;
struct event close_listener_event;
struct bufferevent *bev = NULL;
struct evconnlistener *lev = NULL;
struct sockaddr_in localhost;
struct timeval close_timeout = { 0, 300000 };
ev_socklen_t slen = sizeof(localhost);
evutil_socket_t fake_listener = -1;
int r;
fake_listener = fake_listener_create(&localhost);
@ -809,10 +835,22 @@ test_bufferevent_connect_fail_eventcb(void *arg)
bufferevent_enable(bev, EV_READ|EV_WRITE);
tt_int_op(n_events_invoked, ==, 0);
tt_int_op(n_reads_invoked, ==, 0);
/** @see also test_bufferevent_connect_fail() */
bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen);
r = bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen);
/* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells
* detects the error immediately, which is not really wrong of it. */
tt_want(r == 0 || r == -1);
tt_int_op(n_events_invoked, ==, 0);
tt_int_op(n_reads_invoked, ==, 0);
/* Close the listener socket after a delay. This should trigger
"connection refused" on some other platforms, including OSX. */
evtimer_assign(&close_listener_event, data->base, close_socket_cb,
&fake_listener);
event_add(&close_listener_event, &close_timeout);
event_base_dispatch(data->base);
tt_int_op(n_events_invoked, ==, 1);
tt_int_op(n_reads_invoked, ==, 0);
@ -846,16 +884,6 @@ want_fail_eventcb(struct bufferevent *bev, short what, void *ctx)
event_base_loopexit(base, NULL);
}
static void
close_socket_cb(evutil_socket_t fd, short what, void *arg)
{
evutil_socket_t *fdp = arg;
if (*fdp >= 0) {
evutil_closesocket(*fdp);
*fdp = -1;
}
}
static void
test_bufferevent_connect_fail(void *arg)
{
@ -863,7 +891,7 @@ test_bufferevent_connect_fail(void *arg)
struct bufferevent *bev=NULL;
struct event close_listener_event;
int close_listener_event_added = 0;
struct timeval one_second = { 1, 0 };
struct timeval close_timeout = { 0, 300000 };
struct sockaddr_in localhost;
ev_socklen_t slen = sizeof(localhost);
evutil_socket_t fake_listener = -1;
@ -882,11 +910,11 @@ test_bufferevent_connect_fail(void *arg)
* detects the error immediately, which is not really wrong of it. */
tt_want(r == 0 || r == -1);
/* Close the listener socket after a second. This should trigger
/* Close the listener socket after a delay. This should trigger
"connection refused" on some other platforms, including OSX. */
evtimer_assign(&close_listener_event, data->base, close_socket_cb,
&fake_listener);
event_add(&close_listener_event, &one_second);
event_add(&close_listener_event, &close_timeout);
close_listener_event_added = 1;
event_base_dispatch(data->base);
@ -1336,7 +1364,7 @@ struct testcase_t bufferevent_testcases[] = {
LEGACY(bufferevent_pair_flush_normal, TT_ISOLATED),
LEGACY(bufferevent_pair_flush_flush, TT_ISOLATED),
LEGACY(bufferevent_pair_flush_finished, TT_ISOLATED),
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__)
{ "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY|TT_NO_LOGS,
&basic_setup, NULL },

View File

@ -1265,27 +1265,9 @@ test_bufferevent_connect_hostname(void *arg)
int n_accept=0, n_dns=0;
char buf[128];
int emfile = data->setup_data && !strcmp(data->setup_data, "emfile");
int success = BEV_EVENT_CONNECTED;
int default_error = 0;
unsigned i;
int ret;
if (emfile) {
success = BEV_EVENT_ERROR;
#if defined(__linux__)
/* on linux glibc/musl reports EAI_SYSTEM, when getaddrinfo() cannot
* open file for resolving service. */
default_error = EVUTIL_EAI_SYSTEM;
#elif defined(__sun__)
/* on solaris it returns EAI_FAIL */
default_error = EVUTIL_EAI_FAIL;
/** the DP_POLL can also fail with EINVAL under EMFILE */
#else
/* on osx/freebsd it returns EAI_NONAME */
default_error = EVUTIL_EAI_NONAME;
#endif
}
be_connect_hostname_base = data->base;
/* Bind an address and figure out what port it's on. */
@ -1376,12 +1358,16 @@ test_bufferevent_connect_hostname(void *arg)
tt_int_op(be_outcome[0].what, ==, BEV_EVENT_ERROR);
tt_int_op(be_outcome[0].dnserr, ==, EVUTIL_EAI_NONAME);
tt_int_op(be_outcome[1].what, ==, success);
tt_int_op(be_outcome[1].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
tt_int_op(be_outcome[1].dnserr, ==, 0);
tt_int_op(be_outcome[2].what, ==, success);
tt_int_op(be_outcome[2].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
tt_int_op(be_outcome[2].dnserr, ==, 0);
tt_int_op(be_outcome[3].what, ==, success);
tt_int_op(be_outcome[3].dnserr, ==, default_error);
tt_int_op(be_outcome[3].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
if (!emfile) {
tt_int_op(be_outcome[3].dnserr, ==, 0);
} else {
tt_int_op(be_outcome[3].dnserr, !=, 0);
}
if (expect_err) {
tt_int_op(be_outcome[4].what, ==, BEV_EVENT_ERROR);
tt_int_op(be_outcome[4].dnserr, ==, expect_err);
@ -1822,7 +1808,8 @@ struct gaic_request_status {
#define GAIC_MAGIC 0x1234abcd
static int pending = 0;
static int gaic_pending = 0;
static int gaic_freed = 0;
static void
gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg)
@ -1867,7 +1854,13 @@ gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg)
free(status);
end:
if (--pending <= 0)
if (res)
{
TT_BLATHER(("evutil_freeaddrinfo(%p)", res));
evutil_freeaddrinfo(res);
++gaic_freed;
}
if (--gaic_pending <= 0)
event_base_loopexit(base, NULL);
}
@ -1885,7 +1878,7 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
"foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb,
status);
event_add(&status->cancel_event, &tv);
++pending;
++gaic_pending;
}
#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
@ -2108,6 +2101,9 @@ test_getaddrinfo_async_cancel_stress(void *ptr)
event_base_dispatch(base);
// at least some was canceled via external event
tt_int_op(gaic_freed, !=, 1000);
end:
if (dns_base)
evdns_base_free(dns_base, 1);
@ -2124,6 +2120,7 @@ dns_client_fail_requests_test(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
int limit_inflight = data->setup_data && !strcmp(data->setup_data, "limit-inflight");
struct evdns_base *dns = NULL;
struct evdns_server_port *dns_port = NULL;
ev_uint16_t portnum = 0;
@ -2141,6 +2138,9 @@ dns_client_fail_requests_test(void *arg)
dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
if (limit_inflight)
tt_assert(!evdns_base_set_option(dns, "max-inflight:", "11"));
for (i = 0; i < 20; ++i)
evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
@ -2372,6 +2372,71 @@ end:
evdns_base_free(dns_base, 0);
}
static void
test_set_option(void *arg)
{
#define SUCCESS 0
#define FAIL -1
struct basic_test_data *data = arg;
struct evdns_base *dns_base;
size_t i;
/* Option names are allowed to have ':' at the end.
* So all test option names come in pairs.
*/
const char *int_options[] = {
"ndots", "ndots:",
"max-timeouts", "max-timeouts:",
"max-inflight", "max-inflight:",
"attempts", "attempts:",
"randomize-case", "randomize-case:",
"so-rcvbuf", "so-rcvbuf:",
"so-sndbuf", "so-sndbuf:",
};
const char *timeval_options[] = {
"timeout", "timeout:",
"getaddrinfo-allow-skew", "getaddrinfo-allow-skew:",
"initial-probe-timeout", "initial-probe-timeout:",
};
const char *addr_port_options[] = {
"bind-to", "bind-to:",
};
dns_base = evdns_base_new(data->base, 0);
tt_assert(dns_base);
for (i = 0; i < ARRAY_SIZE(int_options); ++i) {
tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "0"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "1"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "10000"));
tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "foo"));
tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "3.14"));
}
for (i = 0; i < ARRAY_SIZE(timeval_options); ++i) {
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "1"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "0.001"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "3.14"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "10000"));
tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "0"));
tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "foo"));
}
for (i = 0; i < ARRAY_SIZE(addr_port_options); ++i) {
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "8.8.8.8:80"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "1.2.3.4"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "::1:82"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "3::4"));
tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "3.14"));
tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "foo"));
}
#undef SUCCESS
#undef FAIL
end:
if (dns_base)
evdns_base_free(dns_base, 0);
}
#define DNS_LEGACY(name, flags) \
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
dns_##name }
@ -2432,6 +2497,8 @@ struct testcase_t dns_testcases[] = {
{ "client_fail_requests", dns_client_fail_requests_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "client_fail_waiting_requests", dns_client_fail_requests_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, (char*)"limit-inflight" },
{ "client_fail_requests_getaddrinfo",
dns_client_fail_requests_getaddrinfo_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
@ -2443,6 +2510,8 @@ struct testcase_t dns_testcases[] = {
{ "set_SO_RCVBUF_SO_SNDBUF", test_set_so_rcvbuf_so_sndbuf,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "set_options", test_set_option,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
END_OF_TESTCASES
};

View File

@ -102,7 +102,7 @@ test_edgetriggered(void *data_)
"support edge-triggering", event_base_get_method(base),
supports_et?"":"not "));
/* Initalize one event */
/* Initialize one event */
ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev);
tt_assert(ev != NULL);
tt_int_op(event_add(ev, NULL), ==, 0);

View File

@ -290,6 +290,53 @@ end:
;
}
static void
event_finalize_callback_free(struct event *ev, void *arg)
{
struct event_base *base = arg;
int err;
if (base) {
err = event_assign(ev, base, -1, EV_TIMEOUT, NULL, NULL);
tt_int_op(err, ==, 0);
test_ok += 1;
} else {
free(ev);
test_ok += 1;
}
end:
;
}
static void
test_fin_debug_use_after_free(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct event *ev;
tt_ptr_op(ev = event_new(base, -1, EV_TIMEOUT, NULL, base), !=, NULL);
tt_int_op(event_add(ev, NULL), ==, 0);
tt_int_op(event_finalize(0, ev, event_finalize_callback_free), ==, 0);
// Dispatch base to trigger callbacks
event_base_dispatch(base);
event_base_assert_ok_(base);
tt_int_op(test_ok, ==, 1);
// Now add again, since we did event_assign in event_finalize_callback_free
// This used to fail in event_debug_assert_is_setup_
tt_int_op(event_add(ev, NULL), ==, 0);
// Finalize and dispatch again
tt_int_op(event_finalize(0, ev, event_finalize_callback_free), ==, 0);
event_base_dispatch(base);
event_base_assert_ok_(base);
tt_int_op(test_ok, ==, 2);
end:
;
}
#if 0
static void
timer_callback_3(evutil_socket_t *fd, short what, void *arg)
@ -339,6 +386,7 @@ struct testcase_t finalize_testcases[] = {
TEST(cb_invoked, TT_FORK|TT_NEED_BASE),
TEST(free_finalize, TT_FORK),
TEST(within_cb, TT_FORK|TT_NEED_BASE),
TEST(debug_use_after_free, TT_FORK|TT_NEED_BASE|TT_ENABLE_DEBUG_MODE),
// TEST(many, TT_FORK|TT_NEED_BASE),

View File

@ -66,6 +66,8 @@
#include "regress.h"
#include "regress_testutils.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
/* set if a test needs to call loopexit on a base */
static struct event_base *exit_base;
@ -230,6 +232,8 @@ evbuffer_datacmp(struct evbuffer *buf, const char *s)
return -1;
d = evbuffer_pullup(buf, s_sz);
if (!d)
d = (unsigned char *)"";
if ((r = memcmp(d, s, s_sz)))
return r;
@ -457,9 +461,9 @@ http_chunked_cb(struct evhttp_request *req, void *arg)
}
static struct bufferevent *
create_bev(struct event_base *base, evutil_socket_t fd, int ssl_mask)
create_bev(struct event_base *base, evutil_socket_t fd, int ssl_mask, int flags_)
{
int flags = BEV_OPT_DEFER_CALLBACKS;
int flags = BEV_OPT_DEFER_CALLBACKS | flags_;
struct bufferevent *bev = NULL;
if (!ssl_mask) {
@ -522,7 +526,7 @@ http_basic_test_impl(void *arg, int ssl, const char *request_line)
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, http_readcb, http_half_writecb,
http_errorcb, data->base);
out = bufferevent_get_output(bev);
@ -538,12 +542,11 @@ http_basic_test_impl(void *arg, int ssl, const char *request_line)
/* connect to the second port */
bufferevent_free(bev);
evutil_closesocket(fd);
fd = http_connect("127.0.0.1", port2);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, data->base);
out = bufferevent_get_output(bev);
@ -560,12 +563,11 @@ http_basic_test_impl(void *arg, int ssl, const char *request_line)
/* Connect to the second port again. This time, send an absolute uri. */
bufferevent_free(bev);
evutil_closesocket(fd);
fd = http_connect("127.0.0.1", port2);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, data->base);
@ -1283,6 +1285,7 @@ http_autofree_connection_test(void *arg)
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req[2] = { NULL };
struct evhttp *http = http_setup(&port, data->base, 0);
size_t i;
test_ok = 0;
@ -1297,19 +1300,14 @@ http_autofree_connection_test(void *arg)
req[1] = evhttp_request_new(http_request_empty_done, data->base);
/* Add the information that we care about */
evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Connection", "close");
evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Empty", "itis");
evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Connection", "close");
evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Empty", "itis");
for (i = 0; i < ARRAY_SIZE(req); ++i) {
evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Connection", "close");
evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Empty", "itis");
/* We give ownership of the request to the connection */
if (evhttp_make_request(evcon, req[0], EVHTTP_REQ_GET, "/test") == -1) {
tt_abort_msg("couldn't make request");
}
if (evhttp_make_request(evcon, req[1], EVHTTP_REQ_GET, "/test") == -1) {
tt_abort_msg("couldn't make request");
if (evhttp_make_request(evcon, req[i], EVHTTP_REQ_GET, "/test") == -1) {
tt_abort_msg("couldn't make request");
}
}
/*
@ -1320,7 +1318,8 @@ http_autofree_connection_test(void *arg)
evhttp_connection_free_on_completion(evcon);
evcon = NULL;
event_base_dispatch(data->base);
for (i = 0; i < ARRAY_SIZE(req); ++i)
event_base_dispatch(data->base);
/* at this point, the http server should have no connection */
tt_assert(TAILQ_FIRST(&http->connections) == NULL);
@ -3119,7 +3118,7 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout, int ssl)
tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
bev = create_bev(data->base, fd, ssl, 0);
bufferevent_setcb(bev,
http_incomplete_readcb, http_incomplete_writecb,
http_incomplete_errorcb, use_timeout ? NULL : &fd);
@ -3319,7 +3318,7 @@ static void
http_chunk_out_test_impl(void *arg, int ssl)
{
struct basic_test_data *data = arg;
struct bufferevent *bev;
struct bufferevent *bev = NULL;
evutil_socket_t fd;
const char *http_request;
ev_uint16_t port = 0;
@ -3336,7 +3335,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev,
http_chunked_readcb, http_chunked_writecb,
http_chunked_errorcb, data->base);
@ -3354,6 +3353,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
event_base_dispatch(data->base);
bufferevent_free(bev);
bev = NULL;
evutil_gettimeofday(&tv_end, NULL);
evutil_timersub(&tv_end, &tv_start, &tv_end);
@ -3363,7 +3363,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
tt_int_op(test_ok, ==, 2);
/* now try again with the regular connection object */
bev = create_bev(data->base, -1, ssl);
bev = create_bev(data->base, -1, ssl, BEV_OPT_CLOSE_ON_FREE);
evcon = evhttp_connection_base_bufferevent_new(
data->base, NULL, bev, "127.0.0.1", port);
tt_assert(evcon);
@ -3371,14 +3371,13 @@ http_chunk_out_test_impl(void *arg, int ssl)
/* make two requests to check the keepalive behavior */
for (i = 0; i < 2; i++) {
test_ok = 0;
req = evhttp_request_new(http_chunked_request_done,data->base);
req = evhttp_request_new(http_chunked_request_done, data->base);
/* Add the information that we care about */
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
/* We give ownership of the request to the connection */
if (evhttp_make_request(evcon, req,
EVHTTP_REQ_GET, "/chunked") == -1) {
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) {
tt_abort_msg("Couldn't make request");
}
@ -3409,7 +3408,7 @@ http_stream_out_test_impl(void *arg, int ssl)
test_ok = 0;
exit_base = data->base;
bev = create_bev(data->base, -1, ssl);
bev = create_bev(data->base, -1, ssl, 0);
evcon = evhttp_connection_base_bufferevent_new(
data->base, NULL, bev, "127.0.0.1", port);
tt_assert(evcon);
@ -3609,7 +3608,7 @@ http_connection_fail_test_impl(void *arg, int ssl)
/* auto detect a port */
evhttp_free(http);
bev = create_bev(data->base, -1, ssl);
bev = create_bev(data->base, -1, ssl, 0);
/* Pick an unroutable address. This administratively scoped multicast
* address should do when working with TCP. */
evcon = evhttp_connection_base_bufferevent_new(
@ -3681,7 +3680,7 @@ http_simple_test_impl(void *arg, int ssl, int dirty, const char *uri)
exit_base = data->base;
test_ok = 0;
bev = create_bev(data->base, -1, ssl);
bev = create_bev(data->base, -1, ssl, 0);
#ifdef EVENT__HAVE_OPENSSL
bufferevent_openssl_set_allow_dirty_shutdown(bev, dirty);
#endif
@ -3728,7 +3727,7 @@ http_connection_retry_test_basic(void *arg, const char *addr, struct evdns_base
/* auto detect a port */
evhttp_free(http);
bev = create_bev(data->base, -1, ssl);
bev = create_bev(data->base, -1, ssl, 0);
evcon = evhttp_connection_base_bufferevent_new(data->base, dns_base, bev, addr, hs.port);
tt_assert(evcon);
if (dns_base)
@ -4516,7 +4515,7 @@ http_write_during_read_test_impl(void *arg, int ssl)
fd = http_connect("127.0.0.1", port);
tt_assert(fd != EVUTIL_INVALID_SOCKET);
bev = create_bev(data->base, fd, 0);
bev = create_bev(data->base, fd, 0, 0);
bufferevent_setcb(bev, NULL, NULL, NULL, data->base);
bufferevent_disable(bev, EV_READ);
@ -4588,7 +4587,7 @@ static void http_run_bev_request(struct event_base *base, int port,
tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = create_bev(base, fd, 0);
bev = create_bev(base, fd, 0, 0);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, base);
out = bufferevent_get_output(bev);

View File

@ -33,6 +33,14 @@
#include <fcntl.h>
#endif
/* move_pthread_to_realtime_scheduling_class() */
#ifdef EVENT__HAVE_MACH_MACH_H
#include <mach/mach.h>
#endif
#ifdef EVENT__HAVE_MACH_MACH_TIME_H
#include <mach/mach_time.h>
#endif
#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
@ -81,10 +89,12 @@
#include "event2/event-config.h"
#include "regress.h"
#include "regress_thread.h"
#include "tinytest.h"
#include "tinytest_macros.h"
#include "../iocp-internal.h"
#include "../event-internal.h"
#include "../evthread-internal.h"
struct evutil_weakrand_state test_weakrand_state;
@ -186,6 +196,45 @@ ignore_log_cb(int s, const char *msg)
{
}
/**
* Put into the real time scheduling class for better timers latency.
* https://developer.apple.com/library/archive/technotes/tn2169/_index.html#//apple_ref/doc/uid/DTS40013172-CH1-TNTAG6000
*/
#if defined(__APPLE__)
static void move_pthread_to_realtime_scheduling_class(pthread_t pthread)
{
mach_timebase_info_data_t info;
mach_timebase_info(&info);
const uint64_t NANOS_PER_MSEC = 1000000ULL;
double clock2abs =
((double)info.denom / (double)info.numer) * NANOS_PER_MSEC;
thread_time_constraint_policy_data_t policy;
policy.period = 0;
policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
policy.constraint = (uint32_t)(10 * clock2abs);
policy.preemptible = FALSE;
int kr = thread_policy_set(pthread_mach_thread_np(pthread),
THREAD_TIME_CONSTRAINT_POLICY,
(thread_policy_t)&policy,
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
if (kr != KERN_SUCCESS) {
mach_error("thread_policy_set:", kr);
exit(1);
}
}
void thread_setup(THREAD_T pthread)
{
move_pthread_to_realtime_scheduling_class(pthread);
}
#else /** \__APPLE__ */
void thread_setup(THREAD_T pthread) {}
#endif /** \!__APPLE__ */
void *
basic_test_setup(const struct testcase_t *testcase)
{
@ -193,11 +242,19 @@ basic_test_setup(const struct testcase_t *testcase)
evutil_socket_t spair[2] = { -1, -1 };
struct basic_test_data *data = NULL;
thread_setup(THREAD_SELF());
#ifndef _WIN32
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
return (void*)TT_SKIP;
#endif
if (testcase->flags & TT_ENABLE_DEBUG_MODE &&
!libevent_tests_running_in_debug_mode) {
event_enable_debug_mode();
libevent_tests_running_in_debug_mode = 1;
}
if (testcase->flags & TT_NEED_THREADS) {
if (!(testcase->flags & TT_FORK))
return NULL;

View File

@ -148,9 +148,9 @@ ssl_getcert(EVP_PKEY *key)
X509_set_issuer_name(x509, name);
X509_NAME_free(name);
X509_time_adj(X509_get_notBefore(x509), 0, &now);
X509_time_adj(X509_getm_notBefore(x509), 0, &now);
now += 3600;
X509_time_adj(X509_get_notAfter(x509), 0, &now);
X509_time_adj(X509_getm_notAfter(x509), 0, &now);
X509_set_pubkey(x509, key);
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
@ -469,8 +469,8 @@ regress_bufferevent_openssl(void *arg)
type = (enum regress_openssl_type)data->setup_data;
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
if (SSLeay() >= 0x10001000 &&
SSLeay() < 0x1000104f) {
if (OPENSSL_VERSION_NUMBER >= 0x10001000 &&
OPENSSL_VERSION_NUMBER < 0x1000104f) {
/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
* can't renegotiate with themselves. Disable. */
disable_tls_11_and_12 = 1;
@ -974,6 +974,7 @@ regress_bufferevent_openssl_wm(void *arg)
tt_int_op(client.get, ==, client.limit);
tt_int_op(server.get, ==, server.limit);
end:
free(payload);
evbuffer_free(client.data);
@ -981,6 +982,10 @@ end:
evconnlistener_free(listener);
bufferevent_free(client.bev);
bufferevent_free(server.bev);
/* XXX: by some reason otherise there is a leak */
if (!(type & REGRESS_OPENSSL_FILTER))
event_base_loop(base, EVLOOP_ONCE);
}
struct testcase_t ssl_testcases[] = {

View File

@ -110,7 +110,7 @@ regress_get_dnsserver(struct event_base *base,
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(*portnum);
my_addr.sin_addr.s_addr = htonl(0x7f000001UL);
my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) {
evutil_closesocket(sock);
tt_abort_perror("bind");

View File

@ -27,23 +27,30 @@
#ifndef REGRESS_THREAD_H_INCLUDED_
#define REGRESS_THREAD_H_INCLUDED_
#ifdef EVENT__HAVE_PTHREADS
#if defined(_WIN32) /** _WIN32 */
#define THREAD_T void * /* HANDLE */
#define THREAD_FN unsigned __stdcall
#define THREAD_RETURN() return (0)
#define THREAD_SELF() GetCurrentThreadId()
#define THREAD_START(threadvar, fn, arg) do { \
uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
(threadvar) = (THREAD_T)threadhandle; \
thread_setup(threadvar); \
} while (0)
#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
#else /* !_WIN32 */
#include <pthread.h>
#define THREAD_T pthread_t
#define THREAD_FN void *
#define THREAD_RETURN() return (NULL)
#define THREAD_START(threadvar, fn, arg) \
pthread_create(&(threadvar), NULL, fn, arg)
#define THREAD_SELF() pthread_self()
#define THREAD_START(threadvar, fn, arg) do { \
if (!pthread_create(&(threadvar), NULL, fn, arg)) \
thread_setup(threadvar); \
} while (0)
#define THREAD_JOIN(th) pthread_join(th, NULL)
#else
#define THREAD_T HANDLE
#define THREAD_FN unsigned __stdcall
#define THREAD_RETURN() return (0)
#define THREAD_START(threadvar, fn, arg) do { \
uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
(threadvar) = (HANDLE) threadhandle; \
} while (0)
#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
#endif
#endif /* \!_WIN32 */
void thread_setup(THREAD_T pthread);
#endif

View File

@ -211,6 +211,65 @@ regress_ipv6_parse(void *ptr)
#endif
}
static struct ipv6_entry_scope {
const char *addr;
ev_uint32_t res[4];
unsigned scope;
enum entry_status status;
} ipv6_entries_scope[] = {
{ "2001:DB8::", { 0x20010db8, 0, 0 }, 0, NORMAL },
{ "2001:DB8::%0", { 0x20010db8, 0, 0, 0 }, 0, NORMAL },
{ "2001:DB8::%1", { 0x20010db8, 0, 0, 0 }, 1, NORMAL },
{ "foobar.", { 0, 0, 0, 0 }, 0, BAD },
{ "2001:DB8::%does-not-exist", { 0, 0, 0, 0 }, 0, BAD },
{ NULL, { 0, 0, 0, 0, }, 0, BAD },
};
static void
regress_ipv6_parse_scope(void *ptr)
{
#ifdef AF_INET6
int i, j;
unsigned if_scope;
for (i = 0; ipv6_entries_scope[i].addr; ++i) {
struct ipv6_entry_scope *ent = &ipv6_entries_scope[i];
struct in6_addr in6;
int r;
r = evutil_inet_pton_scope(AF_INET6, ent->addr, &in6,
&if_scope);
if (r == 0) {
if (ent->status != BAD)
TT_FAIL(("%s did not parse, but it's a good address!",
ent->addr));
continue;
}
if (ent->status == BAD) {
TT_FAIL(("%s parsed, but we expected an error", ent->addr));
continue;
}
for (j = 0; j < 4; ++j) {
/* Can't use s6_addr32 here; some don't have it. */
ev_uint32_t u =
((ev_uint32_t)in6.s6_addr[j*4 ] << 24) |
((ev_uint32_t)in6.s6_addr[j*4+1] << 16) |
((ev_uint32_t)in6.s6_addr[j*4+2] << 8) |
((ev_uint32_t)in6.s6_addr[j*4+3]);
if (u != ent->res[j]) {
TT_FAIL(("%s did not parse as expected.", ent->addr));
continue;
}
}
if (if_scope != ent->scope) {
TT_FAIL(("%s did not parse as expected.", ent->addr));
continue;
}
}
#else
TT_BLATHER(("Skipping IPv6 address parsing."));
#endif
}
static struct sa_port_ent {
const char *parse;
int safamily;
@ -925,6 +984,16 @@ end:
;
}
static void
test_EVUTIL_IS_(void *arg)
{
tt_int_op(EVUTIL_ISDIGIT_('0'), ==, 1);
tt_int_op(EVUTIL_ISDIGIT_('a'), ==, 0);
tt_int_op(EVUTIL_ISDIGIT_('\xff'), ==, 0);
end:
;
}
static void
test_evutil_getaddrinfo(void *arg)
{
@ -1121,6 +1190,41 @@ end:
evutil_freeaddrinfo(ai);
}
static void
test_evutil_getaddrinfo_AI_ADDRCONFIG(void *arg)
{
struct evutil_addrinfo *ai = NULL;
struct evutil_addrinfo hints;
int r;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
/* IPv4 */
r = evutil_getaddrinfo("127.0.0.1", "80", &hints, &ai);
tt_int_op(r, ==, 0);
tt_assert(ai);
tt_ptr_op(ai->ai_next, ==, NULL);
test_ai_eq(ai, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP);
evutil_freeaddrinfo(ai);
ai = NULL;
/* IPv6 */
r = evutil_getaddrinfo("::1", "80", &hints, &ai);
tt_int_op(r, ==, 0);
tt_assert(ai);
tt_ptr_op(ai->ai_next, ==, NULL);
test_ai_eq(ai, "[::1]:80", SOCK_STREAM, IPPROTO_TCP);
evutil_freeaddrinfo(ai);
ai = NULL;
end:
if (ai)
evutil_freeaddrinfo(ai);
}
#ifdef _WIN32
static void
test_evutil_loadsyslib(void *arg)
@ -1539,6 +1643,7 @@ end:
struct testcase_t util_testcases[] = {
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
{ "ipv6_parse_scope", regress_ipv6_parse_scope, 0, NULL, NULL },
{ "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
{ "sockaddr_port_format", regress_sockaddr_port_format, 0, NULL, NULL },
{ "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL },
@ -1551,8 +1656,10 @@ struct testcase_t util_testcases[] = {
{ "upcast", test_evutil_upcast, 0, NULL, NULL },
{ "integers", test_evutil_integers, 0, NULL, NULL },
{ "rand", test_evutil_rand, TT_FORK, NULL, NULL },
{ "EVUTIL_IS_", test_EVUTIL_IS_, 0, NULL, NULL },
{ "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL },
{ "getaddrinfo_live", test_evutil_getaddrinfo_live, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
{ "getaddrinfo_AI_ADDRCONFIG", test_evutil_getaddrinfo_AI_ADDRCONFIG, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
#ifdef _WIN32
{ "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL },
#endif

View File

@ -182,11 +182,11 @@ main(int argc, char **argv)
if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
return (1);
/* Initalize the event library */
/* Initialize the event library */
if (!(base = event_base_new()))
return (1);
/* Initalize a timeout to terminate the test */
/* Initialize a timeout to terminate the test */
timeout = evtimer_new(base,timeout_cb,&timeout);
/* and watch for writability on one end of the pipe */
ev = event_new(base,pair[1],EV_WRITE | EV_PERSIST, write_cb, &ev);

View File

@ -104,6 +104,7 @@ main(int argc, char **argv)
event_base_dispatch(base);
/* Finalize library */
event_free(ev);
event_base_free(base);
return 0;
}

View File

@ -102,10 +102,10 @@ main(int argc, char **argv)
return (1);
shutdown(pair[0], EVUTIL_SHUT_WR);
/* Initalize the event library */
/* Initialize the event library */
event_init();
/* Initalize one event */
/* Initialize one event */
event_set(&ev, pair[1], EV_READ | EV_TIMEOUT, read_cb, &ev);
event_add(&ev, &timeout);

View File

@ -57,7 +57,7 @@ main(int argc, char **argv)
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
/* Initalize the event library */
/* Initialize the event library */
event_init();
return (0);

View File

@ -50,6 +50,10 @@
#include "event2/listener.h"
#include "event2/thread.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
static struct evutil_weakrand_state weakrand_state;
static int cfg_verbose = 0;
@ -85,6 +89,18 @@ struct client_state {
};
static const struct timeval *ms100_common=NULL;
/* Timers bias for slow CPUs, affects:
* - cfg_connlimit_tolerance (--check-connlimit)
* - cfg_grouplimit_tolerance (--check-grouplimit)
* - cfg_stddev_tolerance (--check-stddev)
*/
static int timer_bias_events;
static struct timeval timer_bias_start;
double timer_bias_spend;
/* Real cost is less (approximately ~5 usec),
* this macros adjusted to make the bias less */
#define TIMER_MAX_COST_USEC 10
/* info from check_bucket_levels_cb */
static int total_n_bev_checks = 0;
static ev_int64_t total_rbucket_level=0;
@ -244,6 +260,64 @@ group_drain_cb(evutil_socket_t fd, short events, void *arg)
bufferevent_rate_limit_group_decrement_write(ratelim_group, cfg_group_drain);
}
static void
timer_bias_cb(evutil_socket_t fd, short events, void *arg)
{
struct event *event = arg;
struct timeval end;
struct timeval diff;
/** XXX: use rdtsc? (portability issues?) */
evutil_gettimeofday(&end, NULL);
evutil_timersub(&end, &timer_bias_start, &diff);
timer_bias_spend += diff.tv_sec + diff.tv_usec * 1e6;
timer_bias_start = end;
if (++timer_bias_events == 100)
event_del(event);
}
static double
timer_bias_calculate(void)
{
struct event_config *cfg = NULL;
struct event_base *base = NULL;
struct event *timer = NULL;
struct timeval tv = { 0, 1 };
int done = 0;
cfg = event_config_new();
if (!cfg)
goto err;
if (event_config_set_flag(cfg, EVENT_BASE_FLAG_PRECISE_TIMER))
goto err;
base = event_base_new_with_config(cfg);
if (!base)
goto err;
timer = event_new(base, -1, EV_PERSIST, timer_bias_cb, event_self_cbarg());
if (!timer || event_add(timer, &tv)) {
goto err;
}
evutil_gettimeofday(&timer_bias_start, NULL);
event_base_dispatch(base);
done = 1;
err:
if (cfg)
event_config_free(cfg);
if (timer)
event_free(timer);
if (base)
event_base_free(base);
if (done)
return MIN(timer_bias_spend / 1e6 / timer_bias_events / TIMER_MAX_COST_USEC, 5);
fprintf(stderr, "Couldn't create event for CPU cycle counter bias\n");
return -1;
}
static int
test_ratelimiting(void)
{
@ -266,6 +340,7 @@ test_ratelimiting(void)
struct event_config *base_cfg;
struct event *periodic_level_check;
struct event *group_drain_event=NULL;
double timer_bias;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
@ -275,6 +350,16 @@ test_ratelimiting(void)
if (0)
event_enable_debug_mode();
timer_bias = timer_bias_calculate();
if (timer_bias > 1) {
fprintf(stderr, "CPU is slow, timers bias is %f\n", timer_bias);
cfg_connlimit_tolerance *= timer_bias;
cfg_grouplimit_tolerance *= timer_bias;
cfg_stddev_tolerance *= timer_bias;
} else {
printf("CPU is fast enough, timers bias is %f\n", timer_bias);
}
base_cfg = event_config_new();
#ifdef _WIN32
@ -376,7 +461,7 @@ test_ratelimiting(void)
ratelim_group = NULL; /* So no more responders get added */
event_free(periodic_level_check);
if (group_drain_event)
event_del(group_drain_event);
event_free(group_drain_event);
for (i = 0; i < cfg_n_connections; ++i) {
bufferevent_free(bevs[i]);

View File

@ -81,8 +81,10 @@ time_cb(evutil_socket_t fd, short event, void *arg)
int
main(int argc, char **argv)
{
struct event_base *base;
struct timeval tv;
int i;
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
@ -94,23 +96,28 @@ main(int argc, char **argv)
evutil_weakrand_seed_(&weakrand_state, 0);
/* Initalize the event library */
event_init();
if (getenv("EVENT_DEBUG_LOGGING_ALL")) {
event_enable_debug_logging(EVENT_DBG_ALL);
}
base = event_base_new();
for (i = 0; i < NEVENT; i++) {
ev[i] = malloc(sizeof(struct event));
/* Initalize one event */
evtimer_set(ev[i], time_cb, ev[i]);
ev[i] = evtimer_new(base, time_cb, event_self_cbarg());
tv.tv_sec = 0;
tv.tv_usec = rand_int(50000);
evtimer_add(ev[i], &tv);
}
event_dispatch();
i = event_base_dispatch(base);
printf("event_base_dispatch=%d, called=%d, EVENT=%d\n",
i, called, NEVENT);
printf("%d, %d\n", called, NEVENT);
return (called < NEVENT);
if (i == 1 && called >= NEVENT) {
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}

View File

@ -99,10 +99,10 @@ main(int argc, char **argv)
if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
return (1);
/* Initalize the event library */
/* Initialize the event library */
event_init();
/* Initalize one event */
/* Initialize one event */
event_set(&ev, pair[1], EV_WRITE, write_cb, &ev);
event_add(&ev, NULL);

View File

@ -60,12 +60,8 @@
#include "tinytest_macros.h"
#define LONGEST_TEST_NAME 16384
#ifndef _WIN32
#define DEFAULT_TESTCASE_TIMEOUT 30U
#else
#define DEFAULT_TESTCASE_TIMEOUT 0U
#endif
#define MAGIC_EXITCODE 42
static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
static int n_ok = 0; /**< Number of tests that have passed */
@ -86,33 +82,73 @@ const char *cur_test_prefix = NULL; /**< prefix of the current test group */
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL;
static void usage(struct testgroup_t *groups, int list_groups)
__attribute__((noreturn));
static int process_test_option(struct testgroup_t *groups, const char *test);
#ifdef _WIN32
/* Copy of argv[0] for win32. */
static char commandname[MAX_PATH+1];
#endif
static void usage(struct testgroup_t *groups, int list_groups)
__attribute__((noreturn));
static int process_test_option(struct testgroup_t *groups, const char *test);
struct timeout_thread_args {
const testcase_fn *fn;
void *env;
};
static DWORD WINAPI
timeout_thread_proc_(LPVOID arg)
{
struct timeout_thread_args *args = arg;
(*(args->fn))(args->env);
ExitThread(cur_test_outcome == FAIL ? 1 : 0);
}
static enum outcome
testcase_run_in_thread_(const struct testcase_t *testcase, void *env)
{
/* We will never run testcase in a new thread when the
timeout is set to zero */
assert(opt_timeout);
DWORD ret, tid;
HANDLE handle;
struct timeout_thread_args args = {
&(testcase->fn),
env
};
handle =CreateThread(NULL, 0, timeout_thread_proc_,
(LPVOID)&args, 0, &tid);
ret = WaitForSingleObject(handle, opt_timeout * 1000U);
if (ret == WAIT_OBJECT_0) {
ret = 0;
if (!GetExitCodeThread(handle, &ret)) {
printf("GetExitCodeThread failed\n");
ret = 1;
}
} else if (ret == WAIT_TIMEOUT) {
printf("timeout\n");
} else {
printf("Wait failed\n");
}
CloseHandle(handle);
if (ret == 0)
return OK;
else if (ret == MAGIC_EXITCODE)
return SKIP;
else
return FAIL;
}
#else
static unsigned int testcase_set_timeout_(void)
{
if (!opt_timeout)
return 0;
#ifndef _WIN32
return alarm(opt_timeout);
#else
/** TODO: win32 support */
fprintf(stderr, "You cannot set alarm on windows\n");
exit(1);
#endif
}
static unsigned int testcase_reset_timeout_(void)
{
#ifndef _WIN32
return alarm(0);
#endif
}
#endif
static enum outcome
testcase_run_bare_(const struct testcase_t *testcase)
@ -129,9 +165,17 @@ testcase_run_bare_(const struct testcase_t *testcase)
cur_test_outcome = OK;
{
testcase_set_timeout_();
testcase->fn(env);
testcase_reset_timeout_();
if (opt_timeout) {
#ifdef _WIN32
cur_test_outcome = testcase_run_in_thread_(testcase, env);
#else
testcase_set_timeout_();
testcase->fn(env);
testcase_reset_timeout_();
#endif
} else {
testcase->fn(env);
}
}
outcome = cur_test_outcome;
@ -143,7 +187,6 @@ testcase_run_bare_(const struct testcase_t *testcase)
return outcome;
}
#define MAGIC_EXITCODE 42
#ifndef NO_FORKING
@ -164,7 +207,7 @@ testcase_run_forked_(const struct testgroup_t *group,
char buffer[LONGEST_TEST_NAME+256];
STARTUPINFOA si;
PROCESS_INFORMATION info;
DWORD exitcode;
DWORD ret;
if (!in_tinytest_main) {
printf("\nERROR. On Windows, testcase_run_forked_ must be"
@ -174,7 +217,7 @@ testcase_run_forked_(const struct testgroup_t *group,
if (opt_verbosity>0)
printf("[forking] ");
snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s --timeout 0 %s%s",
commandname, verbosity_flag, group->prefix, testcase->name);
memset(&si, 0, sizeof(si));
@ -185,15 +228,23 @@ testcase_run_forked_(const struct testgroup_t *group,
0, NULL, NULL, &si, &info);
if (!ok) {
printf("CreateProcess failed!\n");
return 0;
return FAIL;
}
ret = WaitForSingleObject(info.hProcess,
(opt_timeout ? opt_timeout * 1000U : INFINITE));
if (ret == WAIT_OBJECT_0) {
GetExitCodeProcess(info.hProcess, &ret);
} else if (ret == WAIT_TIMEOUT) {
printf("timeout\n");
} else {
printf("Wait failed\n");
}
WaitForSingleObject(info.hProcess, INFINITE);
GetExitCodeProcess(info.hProcess, &exitcode);
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
if (exitcode == 0)
if (ret == 0)
return OK;
else if (exitcode == MAGIC_EXITCODE)
else if (ret == MAGIC_EXITCODE)
return SKIP;
else
return FAIL;
@ -228,7 +279,7 @@ testcase_run_forked_(const struct testgroup_t *group,
return FAIL; /* unreachable */
} else {
/* parent */
int status, r;
int status, r, exitcode;
char b[1];
/* Close this now, so that if the other side closes it,
* our read fails. */
@ -236,12 +287,20 @@ testcase_run_forked_(const struct testgroup_t *group,
r = (int)read(outcome_pipe[0], b, 1);
if (r == 0) {
printf("[Lost connection!] ");
return 0;
return FAIL;
} else if (r != 1) {
perror("read outcome from pipe");
}
waitpid(pid, &status, 0);
exitcode = WEXITSTATUS(status);
close(outcome_pipe[0]);
if (opt_verbosity>1)
printf("%s%s: exited with %i (%i)\n", group->prefix, testcase->name, exitcode, status);
if (exitcode != 0)
{
printf("[atexit failure!] ");
return FAIL;
}
return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
}
#endif
@ -520,7 +579,7 @@ tinytest_set_test_failed_(void)
printf("%s%s: ", cur_test_prefix, cur_test_name);
cur_test_name = NULL;
}
cur_test_outcome = 0;
cur_test_outcome = FAIL;
}
void

View File

@ -113,8 +113,8 @@
#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
setup_block,cleanup_block,die_on_fail) \
TT_STMT_BEGIN \
type val1_ = (a); \
type val2_ = (b); \
type val1_ = (type)(a); \
type val2_ = (type)(b); \
int tt_status_ = (test); \
if (!tt_status_ || tinytest_get_verbosity_()>1) { \
printf_type print_; \

View File

@ -352,7 +352,6 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
}
}
if (win32op->writeset_out->fd_count) {
SOCKET s;
i = evutil_weakrand_range_(&base->weakrand_seed,
win32op->writeset_out->fd_count);
for (j=0; j<win32op->writeset_out->fd_count; ++j) {