Re: Reprise: Pended IOCtrl + LoadLibrary == Deadlock?

Tech-Archive recommends: Fix windows errors by optimizing your registry



Are you by any chance using PulseEvent?
How do you create cxt->semaphore?
Where do you reset cxt->IOPending (if ever)?
Is your driver calling KeEnterCriticalSection for some reason, or waiting
for a mutex object?
Is your driver handle open in FILE_FLAG_OVERLAPPED mode? Does the driver
perform synchronous operation or asynchronous?

"Tom Udale" <email@xxxxxxxxxxx> wrote in message
news:cf6dnUppNcqO2oXeRVn-uw@xxxxxxxxxxxxxx
> Alexander,
>
>> A few questions:
>> 1. Are by any chance using SuspendThread/ResumeThread?
> No.
>
>
>> 2. Are you using IoGetOverlappedResult to get the result of your
>> asynchronous operations?
> No.
>
> Entire threads code is:
>
> static DWORD WINAPI p_asyncThreadFunction(LPVOID param)
> {
> struct tag_cyiDrvAsyncContext* cxt=(struct
> tag_cyiDrvAsyncContext*)param;
>
> while(TRUE)
> {
> /* Wait for someone to tell us to do something. */
>
> verify(WaitForSingleObjectEx(cxt->semaphore,INFINITE,FALSE)==WAIT_OBJECT
> _0);
>
> if(cxt->quit) /* If we have been told to
> quit...*/
> {
> if(!cxt->quitting) /* ... see if we have already
> started the quitting procedure. If not..*/
> p_beginQuit(cxt); /* ...do so.*/
> if(!cxt->numOutstandingAPC) /* If there are no outstanding
> APCs...*/
> break; /* ...exit the thread.*/
> }
>
> if(cxt->IOPending) /* If we have been asked to make a
> call...*/
> {
> if(cxt->quit) /* ...first see if we were also
> told to quit. If so...*/
> {
> if(!cxt->quitting) /* ... see if we have already
> started the quitting procedure. If not..*/
> p_beginQuit(cxt); /* ...do so.*/
> if(!cxt->numOutstandingAPC) /* If there are no outstanding
> APCs...*/
> break; /* ...exit the thread.*/
> }
> else /* ...otherwise, do the IO.*/
> {
> cyiKerIOCallData* ioData=cxt->IOPending;
>
> cxt->ioRes=cxt->link.ioFunc /* Call the driver. This will
> block, perhaps for a _very_ long time. */
> (
> cxt->link.devDataPtr,
> ioData->func,
> ioData->in.buffer,
> ioData->in.bufferSize,
> ioData->out.buffer,
> ioData->out.bufferSize,
> &cxt->ioReturnCount
> );
> /* Driver call is finished. Schedule a callback on the original
> thread via an APC.*/
> p_scheduleAsynchCallback(cxt);
> }
> }
> }
> return 0;
> }
>
>> 3. How often you call CreateFile/CloseHandle for your driver?
>
> Once for the original load and then once per async thread.
>
>
>
>> Could you
>> accidentally call CloseHandle from one thread when another is waiting
> for
>> I/O?
> No. The open closes are all called from the main thread. And they only
> happen at startup and shutdown.
>
>
>
> Regards,
>
> Tom
>
>
>
>
>
>> "Tom Udale" <tom@xxxxxxx> wrote in message
>> news:vzPRe.5379$9i4.1727@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>> > Dear Ivan,
>> >
>> >> From what I can undestant from the limited information supplied on
> the
>> >> process creation logic,
>> > When you say this, do you mean limited information about this
> specific
>> > case or limited information about how the MS compiler supplied
> startup
>> > routines work in general?
>> >
>> >> the C-Rutnime is initializing the IO information, grabbing the
> handles
>> >> from process startup information, and, it's attempting to see if
> they
>> >> are "good" file handles to set them in the standard IO internal
>> >> structures
>> >> of the C-Runtime that has been linked against your DLL.
>> > It seems plausible from the evidence. Although why on earth would
> they do
>> > that?
>> >
>> > And if this is the case, does it not imply that it is simply illegal
> to
>> > load any module into the address space of a process when the process
> has
>> > any pending IO? This seems inconceivable.
>> >
>> >> Can you elaborate on handle inheritance and process creation
> hierarchy ?
>> > Do you mean what I am doing to create all these threads/load these
> DLLs,
>> > or what the OS is doing for us? I am doing very little magic
> myself.
>> >
>> > Assuming you meant the former, the app works like this:
>> >
>> > 1) Loads. Before entering its main PeekMessage loop, it scans its
>> > directory for a variety of plugins (dynamically loaded DLLs defined
> by
>> > me).
>> >
>> > 2) User selects one dll. The dll is loaded and instructed by the
> app to
>> > initialize itself. That in turn does some scanning of it own for
> some
>> > second tier plugins. This is where the dll that talks to the driver
> gets
>> > loaded, kscam_d4. kscam_d4 loads its closely coupled driver
> component,
>> > kscam_kw.
>> >
>> > 3) After the tree of dlls (and in some cases dll/driver pairs) is
> build,
>> > the app enters an intermediate state, effectivly a "preview" state,
> where
>> > all these threads are created (including the one that blocks on the
> pended
>> > IOCTRL). It is during the setup phase of this state that kscam_d4
> creates
>> > its notification thread and blocks on the a "notification callback"
> ioctrl
>> > it sends to the kscam_kw driver. After the setup phase, the app
> runs some
>> > sample data collection and allows the user to configure parameters
> for an
>> > "acquire" state.
>> >
>> > 4) The user selects to enter what is the "acquire" state.
>> >
>> > 5) All the preview threads are shut down, many of which end up
> blocking on
>> > one thing or another. The app is now ready to enter the "acquire"
> state.
>> > At this point, only the main app thread is active.
>> >
>> > 6) The main app goes to load its "full" GUI for the "acquire" state.
> This
>> > involves loading some other plugins. One of which is the monoatd4
> library
>> > that causes the deadlock.
>> >
>> >
>> > Some points about all these DLLs: They are all built from a common
>> > framework of my own creation. These dlls do nothing in the DLL
> main. All
>> > of them create their internal structures and/or load secondary dlls
> in
>> > response to explicit calls from the loading code through an exported
>> > function. Nothing more than standard CRT/C++ global initializers
> are
>> > called during DLLMain.
>> >
>> > I do not do any kind of clever thread local storage, system event
> hooking,
>> > or anything interesting of that nature that I am aware of.
>> >
>> >
>> >> Honestly, I cannot think of any good reason to have a handle to a
> file of
>> >> a custom driver in the startup information of a process.
>> > Nor I. I was hoping you, or someone else could elaborate on this
> point.
>> >
>> > In fact, I have no idea how I would get a handle of my own choosing
> into
>> > the startup information of a process even if I wanted to (by startup
>> > information I am assuming that you mean overriding the standard CRT
>> > handles such as stdin, stdout and so-on).
>> >
>> > I guess I will try to step through this startup code tomorrow.
>> >
>> > Oh that reminds me of one other thing. This failure only seems to
>> > transpire when I have launched the app from the Visual Studio IDE
> (F5). If
>> > I run it directly or without the debugger (ctrl-F5) it is fine. I
> had
>> > always assumed that the entire problem was a race condition so I did
> not
>> > figure this bit of data was that important in the sense of being
> causal.
>> > I had figured that the debugger was either slowing things down
> enough to
>> > cause the race winner to be different or changing the memory
> environment
>> > in such a way as to cause an uninitialized pointer to be less
> benign.
>> >
>> > Is it possible that this is _entirely_ a side effect of the
> debugger? Not
>> > that I can let that go as completing this project without the IDE
> debugger
>> > would be painful to say the least.
>> >
>> > At any rate, the reason I am reminded of this is that I would like
> to use
>> > windbg to step through this code as it has much more accurate call
> stacks
>> > and so on. But, I cannot figure out how to set the breakpoint.
>> >
>> > Devstudio and windbg both use int 3 for breakpoints. If I set the
> int 3
>> > from windbg, it is actually trapped first by devstudio which then
> takes
>> > over. I cannot figure out how to transfer control from devstudio,
> or
>> > alternately, prevent it from trapping int 3s from the get-go.
> Softice
>> > solves this sort of thing by allowing you to turn on and off int 3
>> > trapping. Is there something analogous for DevStudio? I could not
> find
>> > it.
>> >
>> > Thanks again for your input.
>> >
>> > Best regards,
>> >
>> > Tom Udale
>>
>>
>
>


.



Relevant Pages

  • Re: Verifying a driver loaded on startup
    ... > thinking of writing a guardian program to ensure that the driver ... > Of course the guardian program would be loaded at startup via the init ... If the dll is loaded then the guardian program would ...
    (microsoft.public.windowsce.platbuilder)
  • Verifying a driver loaded on startup
    ... Is there a way to verify that a driver has loaded on startup? ... Of course the guardian program would be loaded at startup via the init ... If the dll is loaded then the guardian program would ...
    (microsoft.public.windowsce.platbuilder)
  • Re: Changing Hardware Platform
    ... Some folks will find these two Kbs informative on troubleshooting related startup issues: ... The boot manager searches for and starts IA64ldr.efi. ... >> You can't expect PnP to solve your boot controller issue. ... >> that means that the driver is effectively preinstalled, ...
    (microsoft.public.windows.server.sbs)
  • Re: FTDI USB Serial Drivers
    ... The DLL accesses the inf for setup ... from the FTDI driver readme: ... Notes on INF files ... particular VID and PID requires access to a registry editor which (unlike ...
    (microsoft.public.windowsce.platbuilder)
  • Re: FTDI USB Serial Drivers
    ... The DLL accesses the inf for setup ... from the FTDI driver readme: ... Notes on INF files ... particular VID and PID requires access to a registry editor which (unlike ...
    (microsoft.public.windowsce.platbuilder)