Commit d7c1d340 authored by Benoit Lize's avatar Benoit Lize Committed by Commit Bot

[PartitionAlloc] Save the last error around TLS access on Windows.

TLS access on Windows sets the last error, even in case of success. This
is causing issues with calling code which expects malloc() to not change
the last error. Work around it by saving the last error.

Issue found by tasak@.

Bug: 998048
Change-Id: I64fa7dc44abfae39d3d91d9d8e6dbb9e2721d136
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2529150
Commit-Queue: Benoit L <lizeb@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#826779}
parent a7812b87
...@@ -46,7 +46,23 @@ BASE_EXPORT bool PartitionTlsCreate(PartitionTlsKey* key, ...@@ -46,7 +46,23 @@ BASE_EXPORT bool PartitionTlsCreate(PartitionTlsKey* key,
void (*destructor)(void*)); void (*destructor)(void*));
ALWAYS_INLINE void* PartitionTlsGet(PartitionTlsKey key) { ALWAYS_INLINE void* PartitionTlsGet(PartitionTlsKey key) {
return TlsGetValue(key); // Accessing TLS resets the last error, which then makes |GetLastError()|
// return something misleading. While this means that properly using
// |GetLastError()| is difficult, there is currently code in Chromium which
// expects malloc() to *not* reset it. Meaning that we either have to fix this
// code, or pay the cost of saving/restoring it.
//
// Source:
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsgetvalue
// "Functions that return indications of failure call SetLastError() when they
// fail. They generally do not call SetLastError() when they succeed. The
// TlsGetValue() function is an exception to this general rule. The
// TlsGetValue() function calls SetLastError() to clear a thread's last error
// when it succeeds."
DWORD saved_error = GetLastError();
void* ret = TlsGetValue(key);
SetLastError(saved_error);
return ret;
} }
ALWAYS_INLINE void PartitionTlsSet(PartitionTlsKey key, void* value) { ALWAYS_INLINE void PartitionTlsSet(PartitionTlsKey key, void* value) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment