1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-03-09 17:59:19 +03:00

Compare commits

...

8 Commits

Author SHA1 Message Date
9a42563bbc Merge pull request #2211 from synqa/add-ci-for-sanitizer
Add CI for Sanitizer
2026-02-23 15:11:01 +01:00
7d86756e72 Add CI for Sanitizer
Added Address/Leak/Thread/Undefined Behavior Sanitizer to the CI
workflow. Summary reports are displayed in the Job Summary, while full
logs are available via GitHub Artifacts. Initial verification is
handled by vpntools-check.sh.
2026-02-23 21:51:08 +09:00
e247cf0513 Merge pull request #2241 from synqa/suppress-tsan-accept-disconnect
Suppress Thread Sanitizer for Accept and Disconnect
2026-02-23 13:46:16 +01:00
a247e3ecdc Suppress Thread Sanitizer for Accept and Disconnect
Thread Sanitizer reports two data races on CancelAccept and
CallingThread in SOCK, shared between Accept(Accept6) and Disconnect.
These are used when interrupting an Accept operation from a Disconnect.
These races are benign because they work correctly even if both fields
have old values.
2026-02-23 21:32:26 +09:00
61b920f957 Merge pull request #2239 from synqa/add-comment-unix-lock
Add comment for UnixLock
2026-02-21 15:36:51 +01:00
290f125abc Merge pull request #2240 from synqa/suppress-tsan-threadpoolproc
Suppress Thread Sanitizer for ThreadPoolProc
2026-02-21 15:35:56 +01:00
93bf90ba95 Add comment for UnixLock
The Lock/Unlock mechanism on Unix is a manual, hand-coded implementation
of PTHREAD_MUTEX_RECURSIVE. We avoid using the PTHREAD_MUTEX_RECURSIVE
directly because it exhibits critical bugs, such as deadlocks on
certain older systems(Linux, Solaris, or macOS).
followup #2219
2026-02-21 21:15:56 +09:00
5b356616a7 Suppress Thread Sanitizer for ThreadPoolProc
Thread Sanitizer reports data races on PoolHalting in THREAD, shared
between ThreadPoolProc and WaitThread. But if WaitThread reads false,
synchronization is ensured by Wait from the PoolWaitList. If it reads
true, WaitThread simply returns.
2026-02-21 20:26:39 +09:00
3 changed files with 96 additions and 0 deletions

80
.github/workflows/sanitizer.yml vendored Normal file
View File

@ -0,0 +1,80 @@
name: Sanitizer
on: [push, pull_request]
permissions:
contents: read
jobs:
run_sanitizer:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sanitizer:
- "address,leak,undefined"
- "thread,undefined"
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: |
sudo apt update
sudo apt-get -y install cmake gcc g++ ninja-build libncurses5-dev libreadline-dev libsodium-dev libssl-dev make zlib1g-dev liblz4-dev libnl-genl-3-dev
- name: Build
run: |
mkdir build
cd build
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-O1 -fsanitize=${{ matrix.sanitizer }} -fno-omit-frame-pointer" ..
cmake --build .
- name: Test
env:
ASAN_OPTIONS: halt_on_error=0:exitcode=0
TSAN_OPTIONS: halt_on_error=0:exitcode=0:suppressions=./tsan_suppressions.txt
UBSAN_OPTIONS: halt_on_error=0:exitcode=0
LSAN_OPTIONS: exitcode=0
run: |
.ci/vpntools-check.sh 2> sanitizer.log
- name: Make job summary
run: |
echo "### Sanitizer Report (${{ matrix.sanitizer }})" >> $GITHUB_STEP_SUMMARY
REPORTS=$(grep -E "SUMMARY:|runtime error:" sanitizer.log | sort | uniq)
REPORT_COUNT=$(echo "$REPORTS" | grep -c . || true)
echo "Found $REPORT_COUNT issues" >> $GITHUB_STEP_SUMMARY
echo "<details><summary>View Summary</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "$REPORTS" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
if [ "$REPORT_COUNT" -ne 0 ]; then
echo "HAS_ISSUES=true" >> $GITHUB_ENV
echo "REPORT_COUNT=$REPORT_COUNT" >> $GITHUB_ENV
fi
- name: Upload full sanitizer log
if: env.HAS_ISSUES == 'true'
uses: actions/upload-artifact@v4
with:
name: sanitizer-logs-${{ matrix.sanitizer }}
path: |
sanitizer.log
retention-days: 30
- name: Fail on sanitizer issues
if: env.HAS_ISSUES == 'true'
run: |
echo "Found ${{ env.REPORT_COUNT }} issues."
echo "Please check the Job Summary page for a quick overview."
echo "Full logs are available in the GitHub Artifacts."
exit 1

View File

@ -1849,6 +1849,8 @@ void UnixUnlockEx(LOCK *lock, bool inner)
}
// Lock
// Recursive locking is implemented manually instead of using PTHREAD_MUTEX_RECURSIVE.
// See: https://github.com/SoftEtherVPN/SoftEtherVPN/pull/2219
bool UnixLock(LOCK *lock)
{
pthread_mutex_t *mutex;

View File

@ -17,6 +17,20 @@ race_top:BindConnectThreadForIPv4
race_top:BindConnectThreadForIPv6
race_top:BindConnectEx5
# Thread Sanitizer reports data races on PoolHalting in THREAD, shared between ThreadPoolProc and WaitThread.
# But if WaitThread reads false, synchronization is ensured by Wait from the PoolWaitList. If it reads true,
# WaitThread simply returns.
race_top:ThreadPoolProc
## Accept/Disconnect cancellation
# Thread Sanitizer reports two data races on CancelAccept and CallingThread in SOCK, shared between
# Accept(Accept6) and Disconnect. These are used when interrupting an Accept operation from a Disconnect.
# They are race-safe because they work correctly even if both fields have old values.
race_top:^Accept$
race_top:^Accept6$
race_top:^Disconnect$
## Manual PTHREAD_MUTEX_RECURSIVE
# The Lock/Unlock mechanism on Unix is a manual, hand-coded implementation of PTHREAD_MUTEX_RECURSIVE.