0

I have created a windows executable that serves as a simulaator for some embedded device (all the business logic is exactly the same as on original device and only HW related stuff is stubbed).

This simulation needs to reset from time to time, and in "normal" use case it does something like that:

//some global environment
...

int main(int argc, char* argv[])
{
    __debugbreak();

    //... do some stuff 

    //if( restart needed ){
        printf("before _execv");
        _execv(argv[0], argv); //"reset" simulated device
    //}

    //... do some other testing stuff
    return 0;
}

Note: code above is to just illustrate main idea, in real application that execv call is actually located in HW_Reset() stub, that is called from multiple places in original code.

The problem is that _execv on Windows does not behave exactly as execv on Linux: when I debug this application in Visual Studio the _execv does not replace current process image with "restarted" image. Instead it just creates a new process with new ID and terminates current process, causing detaching it from Visual Studio, so, to preserve all the breakpoints I need to reattach to that new process again and again (there are dozens of restarts in single debug session).

Currently I use __debugbreak() as a workaround. Other option is to reset simulation by reinitializing global environment and using some combination of setjmp/longjmp - but global environment and corresponding initializers are spread through thousends of original files, and most of them are static, so it is not possible to handle such reset manually (also I'm not allowed to edit original files).

So the question is: is there some Windows API / generic workaround that causes current process to restart "inplace" by resetting all the global (and static) variables, like in case if it was possible to reload the same process image inside the same address space, preserving outwardly observable process ID, process handle and connection to visual studio debugger?

Pavlo Mur
  • 350
  • 3
  • 6

2 Answers2

0

I'm afraid that the simple answer is that no such functionality exists on Windows.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

Windows does not support what you are asking for. You will have to restructure your main() code to run in a loop instead, eg:

//some global environment
...

int main(int argc, char* argv[])
{
    __debugbreak();

    do
    {
        //... (re)initialize simulated device
        //... do some stuff
    }
    while (restart needed);

    //... do some other testing stuff
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • in this case "(re)initialize simulated device" operation has to be done manually, including (re)initializing statics spread in those "thousands of original files" – Chajnik-U Aug 11 '17 at 07:25
  • @Chajnik-U: best to get rid of globals and statics, wrap them in objects instead, and then reinitializing can simply destroy the old objects and create new ones. – Remy Lebeau Aug 11 '17 at 07:56