Skip to content
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

GDI false positives from system DC used in more than one thread #1192

Open
derekbruening opened this issue Nov 28, 2014 · 1 comment
Open

Comments

@derekbruening
Copy link
Contributor

From bruen...@google.com on April 24, 2013 16:46:18

xref http://crbug.com/234484 Error #1: GDI USAGE ERROR: DC created by one thread 11236 and used by another 6900
#0 USER32.dll!BitmapFromDIB
#1 USER32.dll!ConvertDIBBitmap
#2 USER32.dll!CopyBmp
#3 USER32.dll!CreateIconIndirect
#4 ui.dll!IconUtil::CreateHICONFromSkBitmap [e:\derek\chromium\src\ui\gfx\icon_util.cc:120]
#5 chrome::anonymous namespace'::SetOverlayIcon [e:\derek\chromium\src\chrome\browser\ui\views\frame\taskbar_decorator_win.cc:65] \# 6 base::internal::RunnableAdapter<void (__cdecl*)(HWND__ *,scoped_ptr<SkBitmap,base::DefaultDeleter<SkBitmap> >)>::Run [e:\derek\chromium\src\base\bind_internal.h:228] \# 7 base::internal::InvokeHelper<0,void,base::internal::RunnableAdapter<void (__cdecl*)(HWND__ *,scoped_ptr<SkBitmap,base::DefaultDeleter<SkBitmap> >)>,void __cdecl(HWND__ * const &,scoped_ptr<SkBitmap,base::DefaultDeleter<SkBitmap> >)>::MakeItSo [e:\derek\chromium\src\base\bind_internal.h:899] \# 8 base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void (__cdecl*)(HWND__ *,scoped_ptr<SkBitmap,base::DefaultDeleter<SkBitmap> >)>,void __cdecl(HWND__ *,scoped_ptr<SkBitmap,base::DefaultDeleter<SkBitmap> >),void __cdecl(HW [e:\derek\chromium\src\base\bind_internal.h:1257] \# 9 base.dll!base::Callback<void __cdecl(void)>::Run [e:\derek\chromium\src\base\callback.h:396] \#10 base.dll!base::anonymous namespace'::WorkItemCallback [e:\derek\chromium\src\base\threading\worker_pool_win.cc:32]
#11 ntdll.dll!RtlpTpWorkCallback
Note: @0:00:29.820 in thread 6900
Note: DC was allocated here:
Note: # 0 system call NtGdiGetDCforBitmap
Note: # 1 GDI32.dll!SetDIBits
Note: # 2 USER32.dll!BitmapFromDIB
Note: # 3 USER32.dll!ConvertDIBBitmap
Note: # 4 USER32.dll!ConvertDIBIcon
Note: # 5 USER32.dll!ObjectFromDIBResource
Note: # 6 USER32.dll!LoadIcoCur
Note: # 7 USER32.dll!LoadIconW
Note: # 8 GetAppIcon [e:\derek\chromium\src\chrome\browser\app_icon_win.cc:33]
Note: # 9 ChromeViewsDelegate::GetDefaultWindowIcon [e:\derek\chromium\src\chrome\browser\ui\views\chrome_views_delegate.cc:134]
Note: #10 views.dll!views::HWNDMessageHandler::GetDefaultWindowIcon [e:\derek\chromium\src\ui\views\win\hwnd_message_handler.cc:845]
Note: #11 ui.dll!ui::WindowImpl::GetWindowClassAtom [e:\derek\chromium\src\ui\base\win\window_impl.cc:264]

USER32!BitmapFromDIB+0x1ce:
76b5e1f6 57 push edi
76b5e1f7 56 push esi
76b5e1f8 ff7524 push dword ptr [ebp+0x24]
76b5e1fb 8b450c mov eax,[ebp+0xc]
76b5e1fe 99 cdq
76b5e1ff 33c2 xor eax,edx
76b5e201 2bc2 sub eax,edx
76b5e203 50 push eax
76b5e204 57 push edi
76b5e205 ff75e4 push dword ptr [ebp-0x1c]
76b5e208 ff350001bc76 push dword ptr [USER32!ghdcBits2 (76bc0100)]
76b5e20e ff157002b576 call dword ptr [USER32!_imp__SetDIBits (76b50270)]
int SetDIBits(
In HDC hdc,

USER32!BitmapFromDIB+0xa5:
76b5e149 6a00 push 0x0
76b5e14b 56 push esi
76b5e14c 6a00 push 0x0
76b5e14e 6a02 push 0x2
76b5e150 56 push esi
76b5e151 ff350001bc76 push dword ptr [USER32!ghdcBits2 (76bc0100)]
76b5e157 ff157802b576 call dword ptr [USER32!_imp__CreateDIBitmap (76b50278)]

HBITMAP CreateDIBitmap(
In HDC hdc,

xref this comment in gdicheck.c:
/* w/o early injection we end up not seeing creation of DC's like
* USER32!ghdcBits2
*/

GDI32!SetDIBits+0x4f:
758b75df ff750c push dword ptr [ebp+0xc]
758b75e2 e889ffffff call GDI32!NtGdiGetDCforBitmap (758b7570)
758b75e7 8bf8 mov edi,eax
758b75e9 3bfb cmp edi,ebx
758b75eb 0f84324b0000 je GDI32!SetDIBits+0x5d (758bc123)

GDI32!SetDIBits+0x5d:
758bc123 ff7508 push dword ptr [ebp+0x8]
758bc126 e8c993ffff call GDI32!CreateCompatibleDC (758b54f4)
758bc12b 8bf8 mov edi,eax
758bc12d c745fc01000000 mov dword ptr [ebp-0x4],0x1
758bc134 3bfb cmp edi,ebx
758bc136 0f85c3b4ffff jne GDI32!SetDIBits+0x7e (758b75ff)

GDI32!SetDIBits+0x74:
758b75f1 57 push edi
758b75f2 e80ef8ffff call GDI32!SaveDC (758b6e05)
758b75f7 85c0 test eax,eax
758b75f9 0f844a4b0000 je GDI32!SetDIBits+0x46 (758bc149)

Theory: NtGdiGetDCforBitmap is returning pre-existing DC USER32!ghdcBits2
0:004> dv
hdc = 0xbd010c55
0:004> dd user32!ghdcBits2
76bc0100 bd010c55 00000000 05e00040 05dd0000

yup!

And user32!ghdcBits2 violates rules about use in multiple threads, it seems.

so does NtGdiGetDCforBitmap ever "create" a bitmap? is it like a Get and
needs a Release?

in ReactOS, it just returns the HDC: it does none of the work that UserGetDC does.

action items:

  1. ignore NtGdiGetDCforBitmap?
    or keep considering an "alloc" b/c we want that DC in our table?
    just don't complain if it's not released. we should see a real release
    later so shouldn't end up stale in table. but, we should mark
    as a non-real-alloc, b/c any de-alloc need not be in the thread
    that called NtGdiGetDCforBitmap.

  2. presumably user32!ghdcBits2 is created by initial thread during user32
    startup? and freed at exit? so seems ok to use a DC in different
    threads, just not simultaneously? is SaveDC relevant here?

initialized here:
USER32!ClientThreadSetup+0x117:
76b5cdd5 ff159c02b576 call dword ptr [USER32!_imp__CreateCompatibleDC (76b5029c)]
76b5cddb a30001bc76 mov [USER32!ghdcBits2 (76bc0100)],eax
0:000> kn

ChildEBP RetAddr

00 0045f018 76b59d82 USER32!ClientThreadSetup+0x122
01 0045f01c 7717010a USER32!__ClientThreadSetup+0x5
02 0045f034 758b6388 ntdll!KiUserCallbackDispatcher+0x2e
03 76b59d82 ffffff25 GDI32!GdiDllInitialize+0x1c

*** TODO can we find ghdcBits2 w/o syms?

I can't find it in any exported routine: only deep inside user32.

may need to turn this GDI warning off by default.

Original issue: http://code.google.com/p/drmemory/issues/detail?id=1192

@derekbruening
Copy link
Contributor Author

From bruen...@google.com on April 26, 2013 08:22:24

we decided to disable this error under off-by-default -check_gdi_multithread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant