dcsimg
Results 1 to 11 of 11

Thread: Multithreading question

  1. #1

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Multithreading question

    I have a fairly heavily multi threaded application (yes I know I shouldn't) and have the following question.

    During process rundown I currently have all my threads kill themselves in a controlled fashion and then at the last minute in my main thread I call CloseHandle on all the thread handles that were returned from CreateThread.

    My question is will ExitProcess clean up for me if I don't call CloseHandle and what cleanup does the VB6
    end statement actually do. I can try to step through the dissembled code in WinDbg but I thought someone might have been down this road before.

    The reason I ask is that the thread object hangs around even after the thread is dead (which you would expect as it is reference counted) but I am unable to find a way to determine the PID that a thread handle belongs to to verify I am not calling close handle on someone else's handle. In theory the handle should only belong to me but I am unsure if handle addresses can be duplicated in another process.

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    4,651

    Re: Multithreading question

    I can't really answer much of anything, but as far as what cleanup the VB6 End Statement actually does, my understanding from many years of repeatedly seeing it discussed, is that End does no clean up and really should never be used. It essentially kills the process without processing things like you might handle in the Form unload events to manually clean up stuff.

  3. #3
    Fanatic Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    880

    Re: Multithreading question

    Once the process is terminated you cannot leave anything in memory -- threads, GDI/GDI+ handles, open files, everything is (fortunately) cleaned up.

    You cannot possibly close other processes' threads, GDI/GDI+ handles or open files even if you want to. Moreover IDs are *not* guaranteed to be unique accross processes as it's not necessary anymore (past win9x).

    You can have a handle with ID=1234, another process can have the same type of handle with ID=1234 too. The OS has no problems dealing with matching IDs as your handles are limited to your process.

    Tear-down is complicated and error-prone but usually reveals lots of subtle problems your application has been dealing in sub-optimal way. Also very useful is to monitor windows event log for App Hang/Crash events for your application -- these might happen silently during process termination.

    cheers,
    </wqw>

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,465

    Re: Multithreading question

    RE: End

    Generally... VB cleans up what it knows about, what it created; however, small leaks can be expected anyway. It won't clean up stuff you've created via APIs or other non-VB calls. When uncompiled, END does not trigger Form/Class/UserControl/etc Terminate events. That event is typically where coders place their cleanup code.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    4,831

    Re: Multithreading question

    Here's the biggest problem I see with the End statement.

    Let's take a new project with a Form1, and add a Form2 and a Class1.

    And then, in Form1's code, add:
    Code:
    
    Option Explicit
    '
    Dim o As Class1
    '
    
    Private Sub Form_Load()
        Form2.Show
        Set o = New Class1
    End Sub
    
    Private Sub Form_Click()
        End
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Unload Form2
    End Sub
    
    
    In Form2's code, add:
    Code:
    
    Option Explicit
    
    Private Sub Form_Unload(Cancel As Integer)
        Debug.Print "Form2 Unloading"
    End Sub
    
    
    And, in Class1's code, add:
    Code:
    
    Option Explicit
    
    Private Sub Class_Terminate()
        Debug.Print "Class1 terminating"
    End Sub
    
    And now, while executing this project, let's terminate it in two ways: 1) click the "X" for closing on Form1. Everything terminates as it should, and 2) lets click Form1 anywhere, executing the END. This time, we get no message for Form2 unloading nor for Class1 terminating.

    Therefore, we see, when we execute an END statement, no windows (hWnds) get correctly unloaded, and no COM objects get correctly uninstantiated. They just get yanked out of memory. Now, I know from experience that the message pumps associated with the hWnds will still attempt to send a WM_DESTROY message, but that doesn't help us much. We get very little (if any) chance to un-subclass and/or shut down things like the GDI+ when we execute an END statement.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  6. #6

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: Multithreading question

    Thanks everybody all for excellent feedback. One question. With regard to the statement

    "You cannot possibly close other processes' threads, GDI/GDI+ handles or open files even if you want to. "

    Is this really true as process explorer can close just about any handle.
    Last edited by vbcommander; May 17th, 2018 at 08:17 AM.

  7. #7

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: Multithreading question

    On this statement...

    "Therefore, we see, when we execute an END statement, no windows (hWnds) get correctly unloaded, and no COM objects get correctly uninstantiated. They just get yanked out of memory. "

    So what harm can be caused by this PROVIDING nothing needs to be saved or written back somewhere. I can't believe it can cause leaks etc otherwise every time an un-managed piece of code fails due to an AV or some other unhandled exception Windows would leak which I don't think is the case.

    I do make sure (I think) that I terminate everything properly on a signal before calling ExitThread to have my threads go away. Learnt some interesting things about the loader lock in the process.

  8. #8
    Fanatic Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    880

    Re: Multithreading question

    Quote Originally Posted by vbcommander View Post
    Thanks everybody all for excellent feedback. One question. With regard to the statement

    "You cannot possibly close other processes' threads, GDI/GDI+ handles or open files even if you want to. "

    Is this really true as process explorer can close just about any handle.
    It injects a DLL into the foreign process, remotely starts a thread in the foreign process to execute an entry point in it's DLL, and then this remotely executed function closes foreign process handles from within the foreign process.

    If you do anything remotely similar in your application then you could start worrying that you can accidentally close foreign process handles :-))

    cheers,
    </wqw>

  9. #9

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: Multithreading question

    Quote Originally Posted by wqweto View Post
    It injects a DLL into the foreign process, remotely starts a thread in the foreign process to execute an entry point in it's DLL, and then this remotely executed function closes foreign process handles from within the foreign process.

    If you do anything remotely similar in your application then you could start worrying that you can accidentally close foreign process handles :-))

    cheers,
    </wqw>
    Good information. Thanks for the clarification.

  10. #10
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    4,831

    Re: Multithreading question

    Quote Originally Posted by vbcommander View Post
    On this statement...

    "Therefore, we see, when we execute an END statement, no windows (hWnds) get correctly unloaded, and no COM objects get correctly uninstantiated. They just get yanked out of memory. "

    So what harm can be caused by this PROVIDING nothing needs to be saved or written back somewhere. I can't believe it can cause leaks etc otherwise every time an un-managed piece of code fails due to an AV or some other unhandled exception Windows would leak which I don't think is the case.

    I do make sure (I think) that I terminate everything properly on a signal before calling ExitThread to have my threads go away. Learnt some interesting things about the loader lock in the process.
    Hi vbcommander,

    I've been messing with DirectX9 lately. It has methods for copying memory into and out-of the GPU's memory, specifically the IDirect3DVertexBuffer9.Lock and IDirect3DVertexBuffer9.Unlock commands. And the GDI+ has similar commands: GdipBitmapLockBits & GdipBitmapUnlockBits. I've never tried it (and probably never will), but I'm not sure what would happen if you did an END after a "Lock" and never "Unlocked". I'm not sure but that could be a system-wide memory leak. I also occasionally issue the GlobalLock and GlobalUnlock commands to get various things done. Same potential problem.

    Regarding shutting down the GDI+ or memory leaks within your own process, you're probably safe. Regarding multi-threading with VB6, I've only dabbled in it very little. However, given that it's a separate thread, it must have it's own memory block, and must therefore manage that block on its own. I've got no idea what's going to happen if that thread gets hung up in memory with perpetual execution. That would almost have to be yet another system-wide memory leak (similar to a program hung in memory).

    I know that Windows (since XP) does excellent memory management (unlike 95, 98, & ME). However, it just seems like good programming practice to make every attempt to shut down with some grace. And, I suppose that means, with multi-threading, have some way to tell the thread to prematurely terminate if it's taking too long.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  11. #11

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: Multithreading question

    Hey Elroy,

    "However, given that it's a separate thread, it must have it's own memory block, and must therefore manage that block on its own"

    Actually memory belongs to a process not a thread. Thread is "merely" a kind of unit of execution within the context of the process.

    All of the process address space is accessible to any thread in the process unless it is protected (as in via memory management subsystem) in some way I think.

    With regard to your example I am not familiar with DirextX9 at all but I would think if the call to .Lock has a system wide blocking effect then I would think you might be in a spot of bother calling END.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width