Results 1 to 19 of 19

Thread: Windows API for Simba1.2+

  1. #1
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default Windows API for Simba1.2+

    Hey! Im working on a Windows API wrapper.
    Thought I'd just share it even tho it's partial. It does have a buckload of methods, and the include works fine, apart from some kinks here and there, heh.

    Download it from: https://github.com/slackydev/Simba-Windows-API
    Have a look at the examples: https://github.com/slackydev/Simba-W...e/master/tests

    If you see some (useful) methods missing, please speak!

    For code-completion to show methods available you have to be specific..:
    > "Windows" can be used to call any & all methods, but wont show any methods in code-completion.
    > "User32", "Kernel32", "Gdi32" etc, have to be used for code-completion to show thair methods.
    Last edited by slacky; 08-01-2017 at 12:32 PM.
    !No priv. messages please

  2. #2
    Join Date
    Oct 2011
    Posts
    805
    Mentioned
    21 Post(s)
    Quoted
    152 Post(s)

  3. #3
    Join Date
    May 2012
    Location
    Moscow, Russia
    Posts
    661
    Mentioned
    35 Post(s)
    Quoted
    102 Post(s)

    Default

    Nice!
    Per aspera ad Astra!
    ----------------------------------------
    Slow and steady wins the race.

  4. #4
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by bg5 View Post
    No idea about the callbacks too :/
    DW, it's a lape bug, it has been resolved, the fixes should be in the next Simba RC.
    Updated that test with a full GetVisibleWindows func, and tested with the lape fixes

    Pretty fun to finally be able to wrap libraries directly in Simba. Makes a lot of stuff so much easier.
    !No priv. messages please

  5. #5
    Join Date
    Oct 2011
    Posts
    805
    Mentioned
    21 Post(s)
    Quoted
    152 Post(s)

    Default

    I've tried your EnumWidows example with newest Simba build and got an error:

    Error: Can't assign "native[register] function(UInt32,Pointer):False..True(4294967295)" to "native[stdcall] function(UInt32,Pointer):False..True(4294967295)" at line 48

    It seems that this utility:
    Added automatic wrapping of Lape function types when assigned to Native function types (e.g. for form callbacks).
    uses default calling convention.

    What to do ?

  6. #6
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    A small update:

    * Callbacks works in the latest Simba 1.2 RC.
    * Added basic stuff for multi-threading (Example)
    * Wrapped MML methods, so that most of them can be used within threads without complications. Enabled with {$DEFINE THREADED_MML}
    * Wrapped WriteLn so that it prints to the debug-box even from a thread (not thread-safe tho, two threads can write at the same time)
    * Some more functions from the Windows API has been added.

    I think that covers it. Have fun!
    Last edited by slacky; 05-27-2017 at 04:57 PM.
    !No priv. messages please

  7. #7
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    A small update:

    * Callbacks works in the latest Simba 1.2 RC.
    * Added basic stuff for multi-threading (Example)
    * Wrapped MML methods, so that most of them can be used within threads without complications. Enabled with {$DEFINE THREADED_MML}
    * Wrapped WriteLn so that it prints to the debug-box even from a thread (not thread-safe tho, two threads can write at the same time)
    * Some more functions from the Windows API has been added.

    I think that covers it. Have fun!


    Nice! But for those that do not know, you should NEVER call "TerminateThread" on Windows unless you absolutely have no choice.. It will leak memory.

    https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

    Code:
    TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
    If the target thread owns a critical section, the critical section will not be released.
    If the target thread is allocating memory from the heap, the heap lock will not be released.
    If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
    If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
    I am Ggzz..
    Hackintosher

  8. #8
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    Quote Originally Posted by Brandon View Post
    Nice! But for those that do not know, you should NEVER call "TerminateThread" on Windows unless you absolutely have no choice.. It will leak memory.

    https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

    Code:
    TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
    If the target thread owns a critical section, the critical section will not be released.
    If the target thread is allocating memory from the heap, the heap lock will not be released.
    If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
    If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
    The Remarks section labels that as applicable to only Windows Server 2003 and Windows XP. An OS-level memory leak is a pretty serious bug, though.
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  9. #9
    Join Date
    Dec 2010
    Posts
    483
    Mentioned
    30 Post(s)
    Quoted
    328 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    The Remarks section labels that as applicable to only Windows Server 2003 and Windows XP
    This is incorrect.

    Windows Server 2003 and Windows XP: The target thread's initial stack is not freed, causing a resource leak.
    The above applies only to the aforementioned windows versions, however the following applies to future versions too;
    If the target thread owns a critical section, the critical section will not be released.
    If the target thread is allocating memory from the heap, the heap lock will not be released.
    The source of the possible memory leak may not be the same, but it is a leak none-the-less.

    Additionally, as already mentioned;
    If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
    If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
    Brandon is entirely correct, TerminateThread should be avoided at all costs. Its labeled as dangerous in almost every place it is documented. Albeit, sometimes Microsoft likes to use some inaccurate keywords ("unsafe" code really just meaning unmanaged for example), but this caveat does not apply whenever they drop the actual word "dangerous".

    The proper alternatives would be to post a WM_QUIT message to the thread. Alternatively, use an Event, and pass the Event object to the thread at initialization. Then you can use WaitForSingleObject to signal the thread termination and cleanup gracefully.

  10. #10
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    I would only be glad to receive a PR with some more proper implementation of a threading wrappers (or whatever else), I haven't had to use Windows' own methods for creating and ending threads before as most languages I use has their own implementations for just this, result is that I was not aware of the unsafe nature of TerminateThread, but it makes perfect sense that it will forcefully terminate the thread and this alone can have ugly side-effects. @Brandon; @the bank;

    Edit: So I have updated the timer to not use TerminateThread and instead just use a "Enabled" flag, and rely on ending the thread by simply returning and WaitForSingleObject.
    For regular threads I guess it's up to the user to manage it.
    Last edited by slacky; 05-28-2017 at 11:13 AM.
    !No priv. messages please

  11. #11
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    I would only be glad to receive a PR with some more proper implementation of a threading wrappers (or whatever else), I haven't had to use Windows' own methods for creating and ending threads before as most languages I use has their own implementations for just this, result is that I was not aware of the unsafe nature of TerminateThread, but it makes perfect sense that it will forcefully terminate the thread and this alone can have ugly side-effects. @Brandon; @the bank;

    Edit: So I have updated the timer to not use TerminateThread and instead just use a "Enabled" flag, and rely on ending the thread by simply returning and WaitForSingleObject.
    For regular threads I guess it's up to the user to manage it.

    Perfect. That is how it should be done. Let the user handle the termination with booleans and locks OR even better with pools and queues. If for some reason they absolutely need to kill the thread because they've lost control of it, then terminate should still be an option.. albeit a last resort.

    Good update!



    Idea:
    Something like the below is what users will have to implement themselves or you can include such functionality.. but the user will still have to make sure that they aren't running an infinite loop on the thread.. You can stop them by throwing an exception when the thread won't terminate gracefully:

    Pascal Code:
    $i atomic
    $i windows
    $i threads

    type Task = record
      stopped: boolean;
      funcPtr: procedure(t: Task);
    end;

    function Task.Create(funcToExecute: Procedure(t: Task)): Task;
    begin
      self.funcPtr := funcToExecute;
      result := self;
    end;

    procedure Task.Destroy();
    begin
      self.funcPtr := nil;
    end;

    procedure Task.run();
    begin
      if (self.funcPtr) then
      begin
        self.funcPtr(self);
      end;
    end;

    procedure Task.stop();
    begin
      self.stopped := true;
    end;

    function Task.isStopped(): Boolean;
    begin
      result := self.stopped;
    end;



    type ThreadPool = record
      stop: AtomicBool;
      lock: Mutex;
      tasks: Queue;
      tasksInProgress: Queue;
      cpu_cores: Integer;
      workers: array of Thread;
    end;

    function ThreadPool.Create(): ThreadPool;
    var
      sysInfo: SYSTEM_INFO;
      i: Integer;
      threadID: DWORD;
    begin
      windows.GetSystemInfo(@sysInfo);
      self.cpu_cores = sysInfo.dwNumberOfProcessors;

      self.stop.setValue(false);
      self.lock = windows.CreateMutex(nil, false, nil);
      SetLength(self.workers, self.cpu_cores);

      for i := 0 to high(self.workers) do
      begin
        self.workers[i] := windows.CreateThread(nil, 0, InternalThreadFunc, self, 0, @threadID);
      end;

      result := self;
    end;

    procedure ThreadPool.Destroy()
    var
      i, exitcode: Integer;
    begin
      for i := 0 to high(self.tasksInProgress) do
      begin
        self.tasksInProgress[i].stop();
      end;

      self.stop.setValue(true);
      windows.WaitForMultipleObjects(self.max_cpu_cores, workers, true, 5 * 1000);

      for i := 0 to high(self.workers) do
      begin
        windows.GetExitCodeThread(self.workers[i], @exitcode);

        if (exitcode == STILL_ACTIVE) then
        begin
          //raiseException('Cannot Terminate Thread.. Gracefully.. Stop running infinite loops');
          windows.TerminateThread(self.workers[i]);
        end;

        windows.CloseHandle(self.workers[i]);
      end;

      SetLength(self.workers, 0);
      SetLength(self.tasks, 0);
      SetLength(self.tasksInProgress, 0);
    end;

    procedure ThreadPool.AddTask(funcToExecute: procedure);
    var
      locked: DWORD;
    begin
      locked := windows.WaitForSingleObject(self.lock, INFINITE);

      if (locked == WAIT_OBJECT_0) then
      begin
        self.tasks.enqueue(Task.create(funcToExecute));
        windows.ReleaseMutex(self.lock);
      end;
    end;

    procedure ThreadPool.ExecuteTask();
    var
      locked: DWORD;
      tsk: Task;
    begin
      while (not self.stop.getValue()) do
      begin
        locked := windows.WaitForSingleObject(self.lock, INFINITE);

        if (locked == WAIT_OBJECT_0) then
        begin
          if (self.tasks.count()) then
          begin
            tsk := self.tasks.dequeue();
            self.tasksInProgress.enqueue(t);
          end;

          windows.ReleaseMutex(self.lock);

          tsk.run();

          locked := windows.WaitForSingleObject(self.lock, INFINITE);
          if (locked == WAIT_OBJECT_0) then
          begin
            tsk := self.tasksInProgress.dequeue();
            tsk.stop();
            windows.ReleaseMutex(self.lock);
          end;
        end;
      end;
    end;

    function __InternalThreadFunc(ptr: Pointer): DWORD; __stdcall;
    begin
      ThreadPool(ptr)^.ExecuteTask();
      result := 0;
    end;

    C++ Code:
    #include <atomic>
    #include <windows.h>

    class Task
    {
    private:
        bool stopped;
        void(*funcPtr)(Task* t);
       
    public:
        Task(void(*funcToExecute)(Task* t))
        {
            this->funcPtr = funcToExecute;
        }
       
        ~Task()
        {
            this->stopped = true;
            funcPtr = nullptr;
        }
       
        void run()
        {
            if (funcPtr)
            {
                funcPtr(this);
            }
        }

        void stop()
        {
            this->stopped = true;
        }

        bool isStopped()
        {
            return this->stopped;
        }
    };

    class ThreadPool
    {
    private:
        atomic_bool stop = false;
        HANDLE lock;
        Queue<Task*> tasks = {};
        Queue<Task*> tasksInProgress = {};
        Handle* workers;
        int max_cpu_cores;
       
        static DWORD __stdcall InternalThreadFunc(void* ptr)
        {
            ThreadPool* pool = reinterpret_cast<ThreadPool*>(ptr);
            pool->ExecuteTask();
            return 0;
        }
       
        void ExecuteTask()
        {
            while(!this->stop) //Atomic :)
            {
                //Lock first before accessing tasks.
                DWORD locked = WaitForSingleObject(this->lock, INFINITE);
               
                if (locked == WAIT_OBJECT_0)
                {
                    Task *t = nullptr;
                    if (tasks.count()) //if there is a task.
                    {
                        t = tasks.dequeue(); //get the task
                        this->tasksInProgress.enqueue(t); //Task is now in progress.
                    }
                   
                    ReleaseMutex(this->lock); //Unlock.
     
                    t->run();  //run the task.

                    DWORD locked = WaitForSingleObject(this->lock, INFINITE);
                    if (locked == WAIT_OBJECT_0)
                    {
                        t = this->tasksInProgress.dequeue();
                        ReleaseMutex(this->lock); //Unlock.
                        t->stop();
                        delete t; //Free the task.
                    }
                }
            }
        }
       
    public:
        ThreadPool()
        {
            SYSTEM_INFO sysinfo;
            GetSystemInfo(&sysinfo);
            this->max_cpu_cores = sysinfo.dwNumberOfProcessors; //Rule of thumb: Have as many threads as we have cores. Either 4 or 8.
           
            //Create a lock for safety.
            this->lock = CreateMutex(nullptr, false, nullptr);
            this->workers = new HANDLE[this->max_cpu_cores]; //Allocate space for worker thread handles.
           
            //Thread the worker threads.. they will each wait on tasks..
            for (int i = 0; i < this->max_cpu_cores; ++i)
            {
                DWORD ThreadID = 0;
                workers[i] = CreateThread(nullptr, 0, InternalThreadFunc, reinterpret_cast<void*>(this), 0, &ThreadID);
            }
        }
       
        ~ThreadPool()
        {
            for (Task* t : this->tasksInProgress)
            {
                t->stop();  //Ask the tasks to quit/break their loops or hurry up and finish..
            }

            this->stop = true; //Ask all threads to stop.. We've already asked the tasks to hurry up..
            WaitForMultipleObjects(this->max_cpy_cores, workers, TRUE, 5 * 1000); //Wait 5 seconds for ALL threads and tasks to gracefully terminate..
           
            //Check which threads are still running and forcefully stop them if necessary.. Otherwise just gracefully close the thread handles.
            for (int i = 0; i < this->max_cpu_cores; ++i)
            {
                DWORD ExitCode = 0;
                GetExitCodeThread(this->workers[i], &ExitCode);
               
                if (ExitCode == STILL_ACTIVE)
                {
                    TerminateThread(this->workers[i]); //Bad idea but we don't have many options here.. We can try again and ask it to stop again or wait longer as well..
                }
               
                CloseHandle(this->workers[i]); //Close the handle to the threads.
            }
           
            //De-allocate the space for the threads.
            delete[] workers;
            workers = nullptr;
           
            //Delete all incomplete tasks..
            for (Task* task : this->queue)
            {
                delete task;
            }

            //Delete all tasks in progress..
            for (Task* task : this->tasksInProgress)
            {
                delete task;
            }

            this->queue.drain();
            this->tasksInProgress.drain();
        }
       
        void AddTask(void(*SomeTaskFunction)())
        {
            //Aquire the lock.
            DWORD locked = WaitForSingleObject(this->lock, INFINITE);
           
            if (locked == WAIT_OBJECT_0)
            {
                tasks.enqueue(new Task(SomeTaskFunction)); //Create a new tasks and enqueue it. The workers will execute it whenever they can.
               
                ReleaseMutex(this->lock); //Release the lock.
            }
        }
    };




    Usage:

    Pascal Code:
    procedure Foo(t: Task);
    begin
      while(not t.isStopped());
      begin
        //Run some intense code here..
      end;
    end;

    procedure Bar(t: Task);
    begin
      while(not t.isStopped());
      begin
        //Run some intense code here..
      end;
    end;

    var
      pool: ThreadPool;
    begin
      pool.addTask(@Foo);
      pool.addTask(@Bar);
    end;

    C++ Code:
    void Foo(Task* t)
    {
       while(!t->isStopped())
       {
           //Run some intense code here..
       }
    }

    void Bar(Task* t)
    {
       while(!t->isStopped())
       {
           //Run some intense code here..
       }
    }

    int main()
    {
        ThreadPool pool;
        pool.AddTask(&Foo);
        pool.AddTask(&Bar);
    }
    Last edited by Brandon; 05-28-2017 at 04:03 PM.
    I am Ggzz..
    Hackintosher

  12. #12
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    @the bank, you don't know what you're talking about nor how to interpret what is on that MSDN page. The only remark that says memory is leaked is the one I referenced. The reason this memory leak is not recoverable is because the initial stack is generally only visible to the OS. If the OS doesn't free it, it will remain unfreed unless there is garbage collection in the kernel memory manager that catches it. Per the documentation this does not exist in Windows Server 2003 and XP, but later versions of the kernel either free the initial stack properly and/or detect memory orphaned in this way.

    The other remarks don't deal with memory at all. You still need to design around that behavior and it may not be what people expect, but it's not like terminating the thread in any other way (e.g. passing it state that it checks to decide if it should terminate) removes the burden of properly managing shared objects.

    That you can corrupt your process state is rather humorous and is reason enough to avoid TerminateThread, but avoiding it because it leaks memory isn't a valid design choice in modern versions of Windows.
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  13. #13
    Join Date
    Dec 2010
    Posts
    483
    Mentioned
    30 Post(s)
    Quoted
    328 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    @the bank, you don't know what you're talking about nor how to interpret what is on that MSDN page.
    Excuse me? Sorry good sir, but you are the one that is incorrect. It's not my fault if you're butt-hurt because I pointed it out.

    A critical section is exactly what it sounds like, a region of memory used in concurrent programming, often made to be kernel level via the use of objects such as a mutex. Additionally, since Vista, microsoft also retains memory for debug information inside of every critical section, which can only be avoided via the CRITICAL_SECTION_NO_DEBUG_INFO flag with the Ex constructor.

    If you could please explain how not releasing a kernel level scope region of memory will not cause a memory leak, I'd love to hear it. Expecting some sort of OS-level garbage collection to do something is not an answer. Sure, a mutex is simply an integer, but there is plenty of Lock&Unlock information linked to it, and possibly even an access queue. Plus the CS debug info I mentioned earlier.

    Furthermore, my comments following in the same post also explained the preferred method, which is exactly what has been implemented now. But yes, I don't have a clue.

    Perhaps you should rephrase further comments to sound less like a pompous fruitcake. Stateing I have no idea what I'm talking about or how to interpret MSDN, after I answered your last two Win API related help threads correctly and included MSDN citations, is ironic at best and ridiculously rude at worst. Don't worry, I will make sure I don't do that again.

  14. #14
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    Quote Originally Posted by the bank View Post
    Excuse me? Sorry good sir, but you are the one that is incorrect. It's not my fault if you're butt-hurt because I pointed it out.

    A critical section is exactly what it sounds like, a region of memory used in concurrent programming, often made to be kernel level via the use of objects such as a mutex. Additionally, since Vista, microsoft also retains memory for debug information inside of every critical section, which can only be avoided via the CRITICAL_SECTION_NO_DEBUG_INFO flag with the Ex constructor.
    A critical section is a piece of code that requires exclusive access to memory. The object that represents a critical section is implemented in a way similar to (or exactly the same as) a mutual exclusion lock an is also called a critical section. The MSDN is saying that if a thread obtains a lock on a section it will not be automatically released if you call TerminateThread, so other portions of your program may never resume execution if they are waiting for that section to be released.

    You can free them and there is kernel memory associated with them, but similar to most Unix-based systems Windows tends to free objects at program exit. A critical section's memory, unlike the initial stack space, isn't owned by the kernel - it's associated with the process, so as soon as the process exits the OS can very easily tell that it is no longer needed and garbage collect it.

    Quote Originally Posted by the bank View Post
    If you could please explain how not releasing a kernel level region of memory will not cause a memory leak, I'd love to hear it. Expecting some sort of OS-level garbage collection to do something is not an answer. Sure, a mutex is simply an integer, but there is plenty of Lock&Unlock information linked to it, and possibly even an access queue. Plus the CS debug info I mentioned earlier.
    The heap lock isn't a region of memory. It's similar to a critical section, and might be implemented as a critical section. Not releasing the heap lock means subsequent attempts to allocate memory would stall indefinitely. There's a few comments I ran across related to TerminateThread where people reported their program freezing after calling it - this seems to be the most likely culprit among the errata in the Remarks section.

    Further each program has an associated heap, and if there is unfreed memory when the program terminates that memory is released along with the copy of the program in RAM. A similar process releases most kernel objects that your program can allocate.

    Quote Originally Posted by the bank View Post
    Perhaps you should rephrase further comments to sound less like a pompous fruitcake. Stateing I have no idea what I'm talking about, after I answered your last two Win API related help threads correctly, is ironic at best and ridiculously rude at worst. Don't worry, I will make sure I don't do that again.
    All that I did was tell you that you were wrong and then demonstrated how. In the two threads you mentioned the only reason you were right was because you were essentially quoting the documentation I had already referenced back at me, which doesn't make for a useful answer.
    Last edited by R0b0t1; 05-28-2017 at 09:01 PM.
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  15. #15
    Join Date
    Dec 2010
    Posts
    483
    Mentioned
    30 Post(s)
    Quoted
    328 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    A critical section is a piece of code that requires exclusive access to memory. The object that represents a critical section is implemented in a way similar to (or exactly the same as) a mutual exclusion lock an is also called a critical section.
    This is exactly what I said...you do realize mutex == mutual exclusions, right?

    Quote Originally Posted by R0b0t1 View Post
    You can free them and there is kernel memory associated with them, but similar to most Unix-based systems Windows tends to free objects at program exit. A critical section's memory, unlike the initial stack space, isn't owned by the kernel - it's associated with the process, so as soon as the process exits the OS can very easily tell that it is no longer needed and garbage collect it.
    So what you're saying is that because we can rely on Windows to free some associated memory for us (literally taught as an awful practice by the way), then there is no inherent leak? Well, yeah, you're right. Assuming windows cleans up properly on exit, there will be no leak. Like I said however, this is a bad practice, because it makes the assumption's that:
    a) We actually want to close the app when we terminate the thread
    b) Windows actually invokes GC
    c) Windows invoked GC occurs when we want it to
    d) That were too lazy to properly free our own memory and therefore rely on the OS to baby-step it for us

    There are plenty of kernel level objects that are not properly freed that way. As a programmer yourself, I am completely sure you are aware of this. Making assumptions of OS behavior when it is not necessary is risky business.

    The fact of the matter is, we are both right in a way. A leak is caused here, you are simply assuming the OS will clean that up when the program terminates. If the goal is not to terminate the application, then you will receive leaking behavior. Imagine a process which consistently spawns multiple threads (bruteforcer lets say, just as an example). If threads are constantly being spawned and concurrently accessing a list of strings, and terminated via TerminateThread, but the process is not being closed, then damn right you will get a hell of a memory leak buildup exactly like I described. The you being correct condition also requires that none of the conditions Brandon described above are true either.

    Its still a leak man...assuming that the leak will be fixed does not make it any less of a leak. It just means you're backpedaling your original argument.

    Quote Originally Posted by R0b0t1 View Post
    All that I did was tell you that you were wrong and then demonstrated how. In the two threads you mentioned the only reason you were right was because you were essentially quoting the documentation at me, which doesn't make for a useful answer.
    No, you stated I don't know what I am talking about and couldn't interpret the MSDN page. Quite frankly, that's rude as fuck, and has permanently stained my opinion of you. My answers to your questions were not "quoting documentation at you", if thats all it was then it says more about you than me, considering in that situation you couldn't be bothered to find the answers yourself. I offered you help because I found your questions fun, and because I've made a career out of Windows and Mobile development. I actually believed we had some mutual respect for each other, which is now gone.

    Quote Originally Posted by R0b0t1 View Post
    the only reason you were right
    Was because I posted the correct information, just as I have done here. Funny how that works.

    Either way, we're arguing the same point, and I'm done spamming poor Slacky's thread with it. If you have anything else to say you can PM me directly.

  16. #16
    Join Date
    Feb 2006
    Location
    Berkeley, CA
    Posts
    1,837
    Mentioned
    52 Post(s)
    Quoted
    60 Post(s)

    Default

    Let's move the sass to IRC please.

  17. #17
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    You really need to be paying attention to this statement you made:

    Quote Originally Posted by the bank View Post
    A critical section is exactly what it sounds like, a region of memory used in concurrent programming,
    It's not a region of memory. I can't store anything in it in the typical sense. This misunderstanding also made your interpretation of the other statements incorrect. So no,

    Quote Originally Posted by the bank View Post
    This is exactly what I said...you do realize mutex == mutual exclusions, right?
    That is not what you said and is as far as I can tell unrelated to your original point.

    Quote Originally Posted by the bank View Post
    So what you're saying is that because we can rely on Windows to free some associated memory for us (literally taught as an awful practice by the way), then there is no inherent leak? Well, yeah, you're right.
    Yes, that's what I'm saying, and you seem to agree.

    Quote Originally Posted by the bank View Post
    Assuming windows cleans up properly on exit, there will be no leak.
    If you aren't going to assume Windows does what it says it does then what is the point of this conversation? Anything could happen for any reason and our conjecture loses any useful meaning.

    TerminateThread seems to, in most cases, break a program to the extent the only action that it can take is termination. Regardless, it will at some point close. When that happens the memory associated with its process will be released.

    Quote Originally Posted by the bank View Post
    There are plenty of kernel level objects that are not properly freed that way. As a programmer yourself, I am completely sure you are aware of this. Making assumptions of OS behavior when it is not necessary is risky business.

    The fact of the matter is, we are both right in a way. A leak is caused here, you are simply assuming the OS will clean that up when the program terminates. If the goal is not to terminate the application, then you will receive leaking behavior. Imagine a process which consistently spawns multiple threads (bruteforcer lets say, just as an example). If threads are constantly being spawned and concurrently accessing a list of strings, and terminated via TerminateThread, but the process is not being closed, then damn right you will get a hell of a memory leak buildup exactly like I described.
    As far as I'm aware every object you could allocate is freed this way. This is because when a program exits you can't possibly still want to maintain control over any object you allocated. At one point I think Windows didn't do automatic deallocation, and it made the system susceptible to instability due to poorly written programs.

    I need to draw attention to what said in response to the previous quote: there is basically no way your program will continue operating after you call TerminateThread once unless you design around the restrictions outlined on the MSDN page. If you're doing that, then leaks due to TerminateThread are your own fault. If you're not doing that, then you called TerminateThread accidentally and your program will crash. There will be no memory leak that impacts your system.

    Quote Originally Posted by the bank View Post
    No, you stated I don't know what I am talking about and couldn't interpret the MSDN page. Quite frankly, that's rude as fuck, and has permanently stained my opinion of you.
    Unfortunately it is true. At some point it is necessary to tell someone they are wrong, and regardless of what language is used it must adequately convey that they are wrong. I'm sorry you don't like that and I understand it is uncomfortable.

    Quote Originally Posted by the bank View Post
    My answers to your questions were not "quoting documentation at you", if thats all it was then it says more about you than me, considering in that situation you couldn't be bothered to find the answers yourself.
    They were. There was some conversation in addition to the references to documentation but they did not add any insight I found useful. It was my intent that I made it clear that I had already referred to the documentation. Most of those questions I posed are still open, and the answer, if it exists, doesn't seem to be within the MSDN and requires knowledge of Windows I can't easily find.

    Quote Originally Posted by the bank View Post
    I offered you help because I found your questions fun, and because I've made a career out of Windows and Mobile development. I actually believed we had some mutual respect for each other, which is now gone.
    I appreciate your replies but I feel you need to know that they were not useful and why they were not useful. I am not responding to you in this way to insult you; I respect you enough to want to correct you when you are wrong. Due to past experience on this forum I'm not willing to move this to PM but this is the last I will comment on the issue.
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  18. #18
    Join Date
    Dec 2010
    Posts
    483
    Mentioned
    30 Post(s)
    Quoted
    328 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    ...
    I truly don't understand you anymore. A critical section exists in a region of memory, which is the basis of my entire point. Of course it is not literally a region itself, however it resides in one. My god are you ever backpedaling and becoming personal now.

    You said: TerminateThread leaking memory is only applicable to Windows XP and Server 2003.

    That statement is the only thing I have been talking about, and it is false. You're just so caught up in trying to "win" whatever this is that you have moved so far beyond that statement now. More over, other people came and also told you about instances where TerminateThread will leak memory. Yet you ignore those, and continue whatever this is.

    We're arguing the same damn point: Don't use TerminateThread. Lets just leave it at that.

  19. #19
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    If you call TerminateThread and your program isn't designed to use it your program will crash or need to be forcibly closed. When that happens, unless you are running Windows Server 2003 or Windows XP, there is no memory that is not reclaimed by the OS.

    TerminateThread leaking memory only on Windows Server 2003 or Windows XP seems like a reasonable conclusion.
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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