[PATCH 1/2] kernel32/tests/loader: Add tests for fiber-local storage.

John Sheu sheu at google.com
Mon Aug 1 18:29:25 CDT 2016


Note: test failures reported by the test bots for this patch, seen here:

  https://testbot.winehq.org/JobDetails.pl?Key=24662

are unrelated to the patch itself.  They appear also on the test run
seen here, which is built against an (almost) unmodified HEAD at
7aadb082:

  https://testbot.winehq.org/JobDetails.pl?Key=24670

On Mon, Aug 1, 2016 at 2:26 PM, John Sheu <sheu at google.com> wrote:
> Signed-off-by: John Sheu <sheu at google.com>
> ---
>  dlls/kernel32/tests/loader.c | 125 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 123 insertions(+), 2 deletions(-)
>
> diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
> index 0b38445..6fbc402 100644
> --- a/dlls/kernel32/tests/loader.c
> +++ b/dlls/kernel32/tests/loader.c
> @@ -70,6 +70,10 @@ static PVOID    (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRI
>                                                   PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
>                                                   PIMAGE_THUNK_DATA ThunkAddress,ULONG);
>  static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *);
> +static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
> +static BOOL (WINAPI *pFlsSetValue)(DWORD, PVOID);
> +static PVOID (WINAPI *pFlsGetValue)(DWORD);
> +static BOOL (WINAPI *pFlsFree)(DWORD);
>
>  static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
>  {
> @@ -1470,6 +1474,7 @@ static HANDLE attached_thread[MAX_COUNT];
>  static DWORD attached_thread_count;
>  HANDLE stop_event, event, mutex, semaphore, loader_lock_event, peb_lock_event, heap_lock_event, ack_event;
>  static int test_dll_phase, inside_loader_lock, inside_peb_lock, inside_heap_lock;
> +static LONG fls_callback_count;
>
>  static DWORD WINAPI mutex_thread_proc(void *param)
>  {
> @@ -1552,9 +1557,18 @@ static DWORD WINAPI noop_thread_proc(void *param)
>      return 195;
>  }
>
> +static VOID WINAPI fls_callback(PVOID lpFlsData)
> +{
> +    ok(lpFlsData == (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData, (void*) 0x31415);
> +    InterlockedIncrement(&fls_callback_count);
> +}
> +
>  static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
>  {
>      static LONG noop_thread_started;
> +    static DWORD fls_index = FLS_OUT_OF_INDEXES;
> +    static int fls_count = 0;
> +    static int thread_detach_count = 0;
>      DWORD ret;
>
>      ok(!inside_loader_lock, "inside_loader_lock should not be set\n");
> @@ -1568,6 +1582,33 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
>          ret = pRtlDllShutdownInProgress();
>          ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
>
> +        /* Set up the FLS slot, if FLS is available */
> +        if (pFlsAlloc)
> +        {
> +            ret = pFlsAlloc(&fls_callback);
> +            ok(ret != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret);
> +            fls_index = ret;
> +        }
> +
> +        /* Make sure the FLS slot is empty, if FLS is available */
> +        if (pFlsGetValue)
> +        {
> +            void* value;
> +            SetLastError(0xdeadbeef);
> +            value = pFlsGetValue(fls_index);
> +            ok(!value, "FlsGetValue returned %p, expected NULL\n", value);
> +            ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
> +        }
> +
> +        /* Set the FLS slot, if FLS is available */
> +        if (pFlsSetValue)
> +        {
> +            BOOL bret;
> +            bret = pFlsSetValue(fls_index, (void*) 0x31415);
> +            ok(bret, "FlsSetValue failed\n");
> +            fls_count++;
> +        }
> +
>          break;
>      case DLL_PROCESS_DETACH:
>      {
> @@ -1621,6 +1662,43 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
>                  ok(!ret || broken(ret) /* before Vista */, "RtlDllShutdownInProgress returned %d\n", ret);
>          }
>
> +        /* In the case that the process is terminating, FLS slots should still be accessible, but
> +         * the callback should be already run for this thread and the contents already NULL.
> +         * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
> +         * point has already run.
> +         */
> +        if (param && pFlsGetValue)
> +        {
> +            void* value;
> +            SetLastError(0xdeadbeef);
> +            value = pFlsGetValue(fls_index);
> +            todo_wine
> +            {
> +                ok(broken(value == (void*) 0x31415) || /* Win2k3 */
> +                   value == NULL, "FlsGetValue returned %p, expected NULL\n", value);
> +            }
> +            ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
> +            todo_wine
> +            {
> +                ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */
> +                   fls_callback_count == thread_detach_count + 1,
> +                   "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
> +            }
> +        }
> +        if (pFlsFree)
> +        {
> +            BOOL ret;
> +            /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */
> +            ret = pFlsFree(fls_index);
> +            ok(ret, "FlsFree failed with error %u\n", GetLastError());
> +            fls_index = FLS_OUT_OF_INDEXES;
> +            todo_wine
> +            {
> +                ok(fls_callback_count == fls_count,
> +                   "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count);
> +            }
> +        }
> +
>          ok(attached_thread_count >= 2, "attached thread count should be >= 2\n");
>
>          for (i = 0; i < attached_thread_count; i++)
> @@ -1791,9 +1869,30 @@ todo_wine
>                              0, TRUE, DUPLICATE_SAME_ACCESS);
>              attached_thread_count++;
>          }
> +
> +        /* Make sure the FLS slot is empty, if FLS is available */
> +        if (pFlsGetValue)
> +        {
> +            void* value;
> +            SetLastError(0xdeadbeef);
> +            value = pFlsGetValue(fls_index);
> +            ok(!value, "FlsGetValue returned %p, expected NULL\n", value);
> +            ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
> +        }
> +
> +        /* Set the FLS slot, if FLS is available */
> +        if (pFlsSetValue)
> +        {
> +            BOOL ret;
> +            ret = pFlsSetValue(fls_index, (void*) 0x31415);
> +            ok(ret, "FlsSetValue failed\n");
> +            fls_count++;
> +        }
> +
>          break;
>      case DLL_THREAD_DETACH:
>          trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
> +        thread_detach_count++;
>
>          ret = pRtlDllShutdownInProgress();
>          /* win7 doesn't allow creating a thread during process shutdown but
> @@ -1805,6 +1904,23 @@ todo_wine
>          else
>              ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
>
> +        /* FLS data should already be destroyed, if FLS is available.
> +         * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry
> +         * point has already run.
> +         */
> +        if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES)
> +        {
> +            void* value;
> +            SetLastError(0xdeadbeef);
> +            value = pFlsGetValue(fls_index);
> +            todo_wine
> +            {
> +                ok(broken(value == (void*) 0x31415) || /* Win2k3 */
> +                   !value, "FlsGetValue returned %p, expected NULL\n", value);
> +            }
> +            ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
> +        }
> +
>          break;
>      default:
>          trace("dll: %p, %d, %p\n", hinst, reason, param);
> @@ -2902,10 +3018,11 @@ START_TEST(loader)
>  {
>      int argc;
>      char **argv;
> -    HANDLE ntdll, mapping;
> +    HANDLE ntdll, mapping, kernel32;
>      SYSTEM_INFO si;
>
>      ntdll = GetModuleHandleA("ntdll.dll");
> +    kernel32 = GetModuleHandleA("kernel32.dll");
>      pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection");
>      pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection");
>      pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection");
> @@ -2922,7 +3039,11 @@ START_TEST(loader)
>      pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock");
>      pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock");
>      pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData");
> -    pResolveDelayLoadedAPI = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "ResolveDelayLoadedAPI");
> +    pFlsAlloc = (void *)GetProcAddress(kernel32, "FlsAlloc");
> +    pFlsSetValue = (void *)GetProcAddress(kernel32, "FlsSetValue");
> +    pFlsGetValue = (void *)GetProcAddress(kernel32, "FlsGetValue");
> +    pFlsFree = (void *)GetProcAddress(kernel32, "FlsFree");
> +    pResolveDelayLoadedAPI = (void *)GetProcAddress(kernel32, "ResolveDelayLoadedAPI");
>
>      GetSystemInfo( &si );
>      page_size = si.dwPageSize;
> --
> 2.8.0.rc3.226.g39d4020
>



More information about the wine-patches mailing list