3

I'm a little confused here as to why _beginthreadex() doesn't start my thread. Basically, I have a thread:

EDIT #3 -- Added the while(), as its part of my code, but I never stated that initially, therefore this thread has to always run until an exit code is prompted inside of it. And it has to run alongside my actual application (therefore, I cannot actually WaitForSingleObject(HANDLE, INFINITE))

unsigned int WINAPI MyThread1(LPVOID)
{  
     MessageBoxA(0, "We're in!", 0, 0);
     while (TRUE)
     {
          // do something
     }
}

And I have my _beginthreadex() code:

/*
   take note that, this is inside another function, and that function is also 
   called through a seperate _beginthreadex() call, so basically, this thread
   is supposed to be called from within another thread
*/
if (user.settingsPage.ChangeVolume > 0)
{
   _beginthreadex(0, 0, &MyThread1, 0, 0, 0);
   // do some cleanup here, of non-related things
}

This file is a DLL extension.

Why doesn't the thread ever run, in other words, why don't I ever see the MessageBoxA() appear on my screen when _beginthreadex() is passed? Is it not possible use _beginthreadex() in a DLL file, or what?

EDIT #1

I've implemented what Richard Chambers said in his reply.

I got the error code from GetExitCodeThread(), and outputted it in a MessageBoxA(), the error code output was 259.

After looking at the MSDN system error codes list: here

The error code corresponds to the following:

ERROR_NO_MORE_ITEMS
259 (0x103)
No more data is available.

EDIT #2

I was reading here, and I noticed this text If a thread returns STILL_ACTIVE (259) as an error code, applications that test for this value could interpret it to mean that the thread is still running and continue to test for the completion of the thread after the thread has terminated, which could put the application into an infinite loop. -- Could this have anything to do with my issue? And if so, what does it mean by the thread is still running? If it's already running, then how come I can't see any output from it in my MessageBox, or the rest of its content?

So, provided those conclusions, what am I to do? How can I solve this issue?

user5315978
  • 53
  • 1
  • 7
  • What's the context around that call to `_beginthreadex`? What's the return value? (Is the return a valid `HANDLE`, or is it `NULL`) – theB Sep 19 '15 at 22:30
  • How do you get the return value from `_beginthreadex`? I tried GetLastError() but it returned 0. How do I check? – user5315978 Sep 19 '15 at 22:42
  • There is insufficient information to do more than guess. – Richard Chambers Sep 19 '15 at 22:50
  • What else would you like me to provide? – user5315978 Sep 19 '15 at 22:51
  • 1
    ["On an error, _beginthreadex returns 0, and errno and _doserrno are set."](https://msdn.microsoft.com/en-us/library/kdzttdcb.aspx). Also, `GetLastError` is only valid if 2 things are true: 1- The function failed. 2- The documentation for the function being called says that `GetLastError` is should be called. – theB Sep 19 '15 at 22:52
  • @theB: I don't mean to change topic here, but regarding GetLastError, I thought that I could set it since, in this guys post here -> http://stackoverflow.com/a/6220176/5315978 ... The code in `_beginthreadex()` apparently does set GetLastError() if CreateThread fails. I will give that other link a read in order to properly be able to distinguish how I can obtain more information as to why _beginthreadex fails. I will update this post once I find out how. Thanks! – user5315978 Sep 19 '15 at 22:55
  • @theB How can I print the value of `errno` in a message box, if it is set? – user5315978 Sep 19 '15 at 22:59
  • @user5315978: The return value is what the function *returns*, just like `sqrt(9.0)` returns the value `3.0`. –  Sep 19 '15 at 23:08
  • Why are you using `MessageBox()`? `MessageBox()` displays a modal dialog box which means that you need all the Windows message pump functionality in place. If you want to know that the thread is starting then just use standard I/O and write to a file or something. see http://stackoverflow.com/questions/2222365/what-is-a-message-pump – Richard Chambers Sep 20 '15 at 00:00
  • @RichardChambers but I'm using the windows api. That shouldn't be problem since I have all that functionality already in place. Also, I've tried writing to a file, and opening a console and writing output to it, nothing works... I simply dont know why its not working, and the error code produced doesn't help much either! :( – user5315978 Sep 20 '15 at 00:05
  • I added `MessageBox (0, _T("A message text"), _T("Caption"), 0);` to my thread example and got a message box just fine. However in a DLL, things may or may not be different. – Richard Chambers Sep 20 '15 at 00:07
  • It is important to take note, the `_T` pre-processor definition is only for Unicode-enabled project solutions, or if you're using `MessageBoxW()` directly. However, in my case, I am using a multi-byte solution, so either way it should have produced the same output as you, I don't know why my message box isn't produced any output in the thread. Thanks for your help to atleast get the error code though, I hope that assists someone in provided an answer for me. – user5315978 Sep 20 '15 at 00:12
  • I just added a new dll project to my sample Visual Studio 2012 console application which started a thread and it worked fine including popping up the second message box. One question is where are you attempting to start the thread. The DLL main needs to finish initializing and the function to start the thread should be a separate function and not part of DLL attach. – Richard Chambers Sep 20 '15 at 00:24
  • @RichardChambers There is a thread started inside my `DLL_PROCESS_ATTACH`. That thread operates just fine, and that is in fact the same thread which launches the concerning thread provided the given condition is met `if (user.settingsPage.ChangeVolume > 0)` - is it possible that the 2nd thread is returning `error code: 259` because you can't start one thread inside another? – user5315978 Sep 20 '15 at 00:31
  • 1
    Everything I have read is that doing anything within the DLL startup, attach, etc. can introduce some real issues. There is nothing to stop a thread from starting another thread, it happens all the time. I just added that to my demo for the second thread to start a third and it worked just fine. `MessageBox()` is modal and that may be part of your problem. – Richard Chambers Sep 20 '15 at 00:40
  • Error 259 usually indicates that the thread *is* actually running. Have you tried using the debugger to see what's going on? – Harry Johnston Sep 20 '15 at 23:55

1 Answers1

3

Here are two simple examples that compile and run in Visual Studio 2012 as a console application. Create a simple Windows console application and then paste this source code into the file. There is not much in the way of error detection however the main parts work.

_beginthreadex() provides a wrapper for CreateThread() in the Windows API however the documentation indicates that it does the necessary initiation for the C/C++ run time as part of starting up the thread. See Windows threading: _beginthread vs _beginthreadex vs CreateThread C++ for details about the differences between these three ways of starting a thread in Windows.

Starting a thread is used in DLLs and COM objects all the time so there is something else that is wrong. The following example starts up a thread at a time.

    // threadtest.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"

    // necessary include files for a Console application wanting to do some Windows things with threads.
    // ordinarily #include <Windows.h> would be added to stdafx.h for this Console application.
    //   Windows.h provides things such as the Sleep() function as well as definitions for HANDLE, etc.
    //   process.h provides the prototypes and declarations for _beginthreadex()
    //   iostream with no .h provides the C++ Standard Library I/O routines for std::cout
    #include <Windows.h>
    #include <process.h>

    #include <iostream>

    // list of arguments to provide to the thread being started up.
    struct argList {
        int i1;
        int i2;
        int i3;
    };

    unsigned int WINAPI myThread (void * args)
    {
        argList *pArgs = (argList *)args;  // convert the LPVOID to the proper type to access the arguments.

        // a bit of output to let us know we got here then a sleep to slow things down a touch.
        std::cout << "myThread is running? args " << pArgs->i1 << ", " << pArgs->i2 << ", " << pArgs->i3 << std::endl;

        Sleep(1000);

        // add the arguments and return the sum.
        return (pArgs->i1 + pArgs->i2 + pArgs->i3);
    }

// declare the function in the DLL we are going to call.
__declspec(dllimport) HANDLE __cdecl Function1(void);

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE   hThread;
    DWORD    exitCode;
    argList myArgs = {1, 2, 3};

    std::cout << "main is running?" << std::endl;

    // start a thread with the arguments we want to sum and wait for it to complete and return to us.
    // when it returns we will fetch the return value which is the sum of the arguments.

    hThread = (HANDLE)_beginthreadex (0, 0, myThread, &myArgs, 0, 0);
    WaitForSingleObject (hThread, INFINITE);       // Wait for the thread we started to complete, a kind of Join
    GetExitCodeThread (hThread, &exitCode);        // Get the thread's exit code so that we can print it out
    CloseHandle (hThread);                         // We be done with the thread so close out it's handle to release resources

    std::cout << "main ending, thread exit code " << exitCode << std::endl;

    // now call the function in our DLL which will start up a thread there
    // get its handle so that we can check the exit code, etc.
    hThread = Function1();
    WaitForSingleObject (hThread, INFINITE);       // Wait for the thread we started to complete, a kind of Join
    GetExitCodeThread (hThread, &exitCode);        // Get the thread's exit code so that we can print it out
    CloseHandle (hThread);                         // We be done with the thread so close out it's handle to release resources
    std::cout << "main ending, Function1 exit code " << exitCode << std::endl;
    return 0;
}

A simple console DLL project was added to the Visual Studio 2012 solution using the standard Add wizard. I modified what was an empty file, not the DLL main file containing the DLL message handlers for attach, etc. The modified file contains the following:

#include "stdafx.h"

#include <Windows.h>

#include <process.h>
#include <iostream>

unsigned int WINAPI myThread2 (void * args)
{

    // a bit of output to let us know we got here then a sleep to slow things down a touch.
    std::cout << "myThread2 is running? args " << std::endl;

    MessageBox (0, L"A message2  text", L"Caption 2", 0);
    Sleep(1000);

    // add the arguments and return the sum.
    return 345;
}

__declspec(dllexport) HANDLE __cdecl Function1(void)
{
    std::cout << " in DLL, starting thread." << std::endl;

    HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread2, 0, 0, 0);

    return hThread;
}

Multiple Threads

If the simple application is modified to have loops in the threads with output we could have several simultaneous threads running. The main could be modified to look like the following where we start two different threads which we are interested in managing and then wait for both to finish then check the exit status of both threads as follows. There is a third thread which is started however we do not both to get its handle nor manage it. It runs a short time then ends.

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE          hThreads[2];
    DWORD           exitCode;
    unsigned int    threadId;
    argList myArgs = {1, 2, 3};

    std::cout << "main is running?" << std::endl;

    // start a thread with the arguments we want to sum and wait for it to complete and return to us.
    // when it returns we will fetch the return value which is the sum of the arguments.

    hThreads[0] = (HANDLE)_beginthreadex (0, 0, myThread, &myArgs, 0, &threadId);
    hThreads[1] = Function1();

    WaitForMultipleObjects  (2, hThreads, TRUE, INFINITE);       // Wait for all threads we started to complete, a kind of Join
    GetExitCodeThread (hThreads[0], &exitCode);        // Get the thread's exit code so that we can print it out
    std::cout << "main ending, thread 1 exit code " << exitCode << std::endl;
    GetExitCodeThread (hThreads[1], &exitCode);        // Get the thread's exit code so that we can print it out
    std::cout << "main ending, thread 2 exit code " << exitCode << std::endl;
    CloseHandle (hThreads[0]);                         // We be done with the thread so close out it's handle to release resources
    CloseHandle (hThreads[1]);                         // We be done with the thread so close out it's handle to release resources
    return 0;
}

Each of the three threads has a simple loop which counts up to a final value and displays a message to standard output. A Sleep(1000) gives us a way to slow down everything. So each thread has a loop that looks like the following which is from thread number 3.

MessageBox (0, L"A message 3  text", L"Caption 3", 0);

std::cout << "    myThread 3 after MessageBox - start loop" << std::endl;

for (int i = 0; i < 10; i++) {
    Sleep(1000);
    std::cout << "    myThread 3 is running step "<< i << std::endl;
}

std::cout << "myThread 3 end" << std::endl;

The DLL source for this example starts a thread in the exported entry point Function1() and the thread started in Function1() starts a third thread.

#include "stdafx.h"

#include <Windows.h>

#include <process.h>
#include <iostream>

unsigned int WINAPI myThread3 (void * args)
{
    // a bit of output to let us know we got here then a sleep to slow things down a touch.
    std::cout << "myThread3 is running? args " << std::endl;

    MessageBox (0, L"A message 3  text", L"Caption 3", 0);

    std::cout << "    myThread 3 after MessageBox - start loop" << std::endl;

    for (int i = 0; i < 10; i++) {
        Sleep(1000);
        std::cout << "    myThread 3 is running step "<< i << std::endl;
    }

    std::cout << "myThread 3 end" << std::endl;
    return 2356;
}

unsigned int WINAPI myThread2 (void * args)
{

    // a bit of output to let us know we got here then a sleep to slow things down a touch.
    std::cout << "myThread2 is running? args " << std::endl;

    MessageBox (0, L"A message 2  text", L"Caption 2", 0);

    std::cout << "    myThread 2 after MessageBox - start myThread3 then loop" << std::endl;

    HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread3, 0, 0, 0);

    for (int i = 0; i < 10; i++) {
        Sleep(1000);
        std::cout << "    myThread 2 is running "<< i << std::endl;
    }

    std::cout << "myThread 2 end" << std::endl;
    // add the arguments and return the sum.
    return 345;
}

__declspec(dllexport) HANDLE __cdecl Function1(void)
{
    std::cout << " in DLL, starting myThread 2." << std::endl;

    HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread2, 0, 0, 0);

    return hThread;
}

The output shows all the various threads running with the count up. Notice in the output that thread 3, which was started by thread 2 continues running after thread 2 ends due to the delay of starting its loop. Both thread 2 and thread 3 are in the DLL code and are started when the main calls the DLL entry point of Function1().

main is running?
 in DLL, starting myThread 2.
myThread is running? args myThread2 is running? args 1, 2, 3

    myThread after MessageBox - start loop
    myThread is running i = 0
    myThread is running i = 1
    myThread 2 after MessageBox - start myThread3 then loop
myThread3 is running? args
    myThread is running i = 2
    myThread 2 is running 0
    myThread is running i = 3
    myThread 2 is running 1
    myThread is running i = 4
    myThread 3 after MessageBox - start loop
    myThread 2 is running 2
    myThread is running i = 5
    myThread 3 is running step 0
    myThread 2 is running 3
    myThread is running i = 6
    myThread 3 is running step 1
    myThread 2 is running 4
    myThread is running i = 7
    myThread 3 is running step 2
    myThread 2 is running 5
    myThread is running i = 8
    myThread 3 is running step 3
    myThread 2 is running 6
    myThread is running i = 9
    myThread 3 is running step 4
    myThread 2 is running 7
    myThread is running i = 10
    myThread 3 is running step 5
    myThread 2 is running 8
    myThread is running i = 11
    myThread 3 is running step 6
    myThread 2 is running 9
myThread 2 end
    myThread is running i = 12
    myThread 3 is running step 7
    myThread is running i = 13
    myThread 3 is running step 8
    myThread is running i = 14
    myThread 3 is running step 9
myThread 3 end
    myThread is running i = 15
    myThread is running i = 16
    myThread is running i = 17
    myThread is running i = 18
    myThread is running i = 19
myThread end
main ending, thread 1 exit code 6
main ending, thread 2 exit code 345
Community
  • 1
  • 1
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • `GetExitCodeThread()`. Thats what I was looking for thanks, I will post my results to you in a moment. – user5315978 Sep 19 '15 at 23:11
  • I've editted my post with the error code which I've received by using your code, thank you very much, once I get 15 reputation, I will upvote the answer - but how can I solve the issue at hand? – user5315978 Sep 19 '15 at 23:47