-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ZDICT_trainFromBuffer_cover is not thread safe #4045
Comments
From what I could understand from the code, the issue derives from having to use a global context to pass extra information (i.e. a context) while performing the call to qsort(). Perhaps the reentrant qsort_r() could be a good fit for this problem? From the documentation (https://man7.org/linux/man-pages/man3/qsort_r.3.html), quote: "The qsort_r() function is identical to qsort() except that the comparison function compar takes a third argument. A pointer is passed to the comparison function via arg. In this way, the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads.". It is available with small variations (i.e. qsort_s()) for both Windows (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170) and BSD (https://man.freebsd.org/cgi/man.cgi?query=qsort_r&sektion=3), therefore should be portable. I would like to help on this one if it is available. |
An update: I have a first draft patch, it seems to work fine on OSX@clang and Linux@gcc. I will need a bit of time to get a Windows machine (and apparently a BSD machine too...), so I hope this is not a high priority bug. I got a few questions, please see below: @as-com: as you mentioned zstd-sys/cargo, I would assume that you are using zstd from Rust? Do you think it is possible to share a simple test case exposing the bug? @Cyan4973: concerning testing... what would be the recommended test suite (and how to build/run/etc) for changes in the cover.c file? So far, I only did my local changes and run 'make test' in the root folder for both OSX and Linux and after a while could only see PASS/Success/etc but I guess there is a more focused test suite for the code in the dictionary folder. |
There isn't actually. That's the reason why there is no report of any issue using current CI test suite. So one test must be added to observe the problem, and then see it fixed. While it's not very hard, it's not completely trivial either : |
Sounds good. I will hack something to test the fix. |
An update: I wrote a simple dictionary builder example calling ZDICT_trainFromBuffer_cover with 160 samples and each sample with 100KB in size. For a regular build (i.e. make -j8), it crashes reliably when I use 32 threads, not so reliably with 24 threads and rarely with 16 threads. |
Now when I apply the qsort_r() fix, it seems to run fine but it takes a little while to run (i.e. around 20s in a Intel 11th gen i7 processor). A link to the output of the test case: |
The current fix works fine on OSX & Linux. I got validate it for Windows and since I don't have a Win box, it will take a little bit to get one and setup compilers/devel tools/etc. |
Thanks @Adenilson ! This is trending well ! |
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
A test case to demonstrate the crashes reported on facebook#4045. Not for commit, builds only on POSIX systems.
@Cyan4973 the above branches have a rough draft of how the fix and the PoB (Proof of Bug) look like. They are not ready for landing yet, given that I need to validate the approach on BSD (I assume that it is an officially supported OS? Or not? Is it part of the CI?) and it is unclear to me ATM how the PoB should be integrated (or not) e.g. as a unit test? Do test runners time out or have resource restraints (i.e. I'm using 48 threads in the PoB)? Also I noticed that the MS Visual Studio files are for VS 2010. I got VS 2022 installed in an old Windows laptop and was forced to 're-target' the build files to VS 2022 to be able to build zstd. Is that expected? Or is zstd build in another way for MS Windows (e.g. cmake)? Finally, it seems that OSX Build on vanilla 'dev' branch (hash 3242ac5 from Friday Jun 14th) is now broken, I guess I got fix that too: |
Yes it is.
Yes, there's a hard limit at 1 hour, but in this project, we aim at a ~20mn max for any particular test, and ~5mn preferably.
Yes. Basically, VS2010 project file can be updated to any modern version, so we have used that since the beginning of the project (~2015). That being said, an even better future would be to no longer manually maintain any Solution file, and instead get them generated automatically, typically from
That's a concern. And it's surprising since Such a bug should be fixed a.s.a.p, though not necessarily by you, nor bundled into another PR with a different objective. edit : the pb seems bisected to #4067 , but here too, the edit 2: #4076 |
Oh, btw, |
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
@Cyan4973 I just had dinner and was going to open a detailed bug report for the OSX build breakage and just noticed that you already fixed the build. Thanks a lot! I will experiment with tsan and report back the results (also got get a *BSD environment to validate the qsort_r()/s() fix). |
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
An update: I got the fix to build for FreeBSD. Since I don't have a spare system to install FreeBSD, I just used a VM under VirtualBox and it worked reasonably well. Fortunately it seems that *BSD systems comply with the GNU API for qsort_r(), which simplifies the things (i.e. the same code is used for Linux and *BSD). I consider now the fix properly ready for review, since it was tested on 4 OSes (Linux, OSX, Windows, FreeBSD) and I will submit a merge request. What is missing is the PoB (Proof of Bug) integration. Is the later a hard requirement for the first? |
One last thing that occurred to me is to verify if it builds fine for Android (IIRC the NDK uses clang). |
The test matrix was: clang@OSX, gcc@Linux, gcc@FreeBSD, msvc@Windows. |
It's preferable, but if it's too hard to achieve within the constraints of CI, this could be left. A desirable intermediate solution could be to provide the test program or unit without making it a CI test, shipping with it a documentation to reproduce the test locally. |
Perhaps the PoB could be rewritten in a way to teach how to use the dictionary building API, thus addressing the other request on #4066. I still got investigate TSAN, it may be the case that it is able to simply the PoB quite a bit. I just noticed that the CI showed that a bot (MINGW64) failed to compile. That is a combination I haven't tested (gcc@Windows), but I think probably the fix should be pretty simple (i.e. test if the compiler used is GCC and then define _GNU_SOURCE). So not ready for landing yet, still needs some more work on it. |
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed for newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
…trant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue facebook#4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the <stdlib.h>. Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed on newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. For such cases we provide a fallback that will work only requiring support for compilers implementing support for C90. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
Fixed in #4086 |
Describe the bug
ZDICT_trainFromBuffer_cover is not thread safe due to the use of global state:
zstd/lib/dictBuilder/cover.c
Lines 235 to 236 in 78955f5
Calling this function from multiple threads may result in segfault/access violation, use-after-free and other badness.
To Reproduce
Call ZDICT_trainFromBuffer_cover from multiple threads
Desktop (please complete the following information):
The text was updated successfully, but these errors were encountered: