53

I am developing a C++ program and it would be useful to use some function, script or something that makes the program restart. It's a big program so restarting all the variables manually will take me long time...

I do not know if there is any way to achieve this or if it is possible.

mid
  • 409
  • 5
  • 19
Julen Uranga
  • 757
  • 1
  • 5
  • 17
  • 39
    Whatever you do, do not call `main()` in your code. – NathanOliver Oct 13 '16 at 13:38
  • 15
    "restarting all the variables manually" Wut? – Treycos Oct 13 '16 at 13:39
  • 5
    Did you consider using a loop? – Baum mit Augen Oct 13 '16 at 13:40
  • 1
    the program has 6 threads, so it is not a small one – Julen Uranga Oct 13 '16 at 13:41
  • 8
    What platform? If it's anything remotely POSIX-like, you might want to look at the `exec()` family of functions. – Toby Speight Oct 13 '16 at 15:42
  • 1
    What OS is this for. Many OSes let you execute a new program image in the current process and that can include rerunning the current one. – Vality Oct 13 '16 at 15:51
  • 2
    What is your goal with restarting the program? What do you want to accomplish? This can help with determining the best way to go about restarting your application. – Jordan Melo Oct 13 '16 at 16:47
  • 4
    You may be in a touchy region. Do you want to a) "Develop a program which is aware that you may want to 'restart' by resetting its state to somewhere near the start of the program" or b) "Bash the existing program over the head and restart while it's not looking?" In a multi threaded program, the former requires a lot of attention to detail. The latter can be extremely dangerous depending on what the threads were doing at the time. – Cort Ammon Oct 13 '16 at 16:54
  • 1
    What about just using a loop? As long you don't use any globals you can modify this will be just fine. – Asu Oct 13 '16 at 19:22
  • 36
    This sounds like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – isanae Oct 13 '16 at 19:36
  • 1
    It is Linux, working in a Raspberry Pi board. It is a train's on board embedded system that locates the train (IMU, GPS, GSM/GPRS modem) and I need to be restarted after it receives a missed call. – Julen Uranga Oct 14 '16 at 06:32
  • 4
    As someone with some experience with the railway industry, this question frightens me a bit. By the way, perhaps your application could benefit from being written in [Erlang](http://www.erlang-embedded.com/2013/09/new-erlang-package-for-small-devices-erlang-mini/) rather than C++, as Erlang was literally [created for fault-tolerant telephony](https://en.wikipedia.org/wiki/Erlang_%28programming_language%29#History). –  Oct 14 '16 at 09:51
  • 2
    What I am developing is just a prototype, so it is not going to be implemented in a train for commercial purposes. It is part of a research project. – Julen Uranga Oct 14 '16 at 09:56
  • 2
    That sounds like the sort of thing a [watchdog daemon](https://linux.die.net/man/8/watchdog) was invented for (and check whether you have watchdog hardware, to enable full-system reboot if necessary). – Toby Speight Oct 14 '16 at 10:37

9 Answers9

66

If you really need to restart the whole program (i.e. to "close" and "open" again), the "proper" way would be to have a separate program with the sole purpose of restarting your main one. AFAIK a lot of applications with auto-update feature work this way. So when you need to restart your main program, you simply call the "restarter" one, and exit.

SingerOfTheFall
  • 27,171
  • 7
  • 60
  • 100
  • So would be enough having two programs that call each other and exit when restarting is required , wouldn't it? – Julen Uranga Oct 13 '16 at 13:48
  • 7
    They don't call each other; the caller is basically a loop that calls the second one, waits for it to exit, then calls it again. The "real" program doesn't know anything about the caller; it just exits. – chepner Oct 13 '16 at 15:29
  • 3
    And the worker may indicate via its exit code whether it wants to be restarted by the watch dog. – Carsten S Oct 13 '16 at 18:59
  • 4
    Why not just start another instance of your program, possibly specifying a flag to it that indicates that it's a restart? – David Schwartz Oct 13 '16 at 22:27
  • Okay! Currently I execute my program automatically at boot time using a script so I can change it and make the program "restart" (execute it again) when a specific exit code arrives. Am I correct? – Julen Uranga Oct 14 '16 at 06:44
  • The answer is correct, but I just want to emphasize that you don't have to have actual separate program (or script) lying anywhere on the disk. You can generate it dynamically in memory, create a process for it that waits for your current process handle to close and then starts your app again and then closes. I have no idea how hard can this be in C++, but I'm pretty sure it is possible given that you can easily do this in C# or Java. – Archeg Oct 14 '16 at 07:48
51

You can use a loop in your main function:

int main()
{
    while(!i_want_to_exit_now) {
        // code
    }
}

Or, if you want to actually restart the program, run it from a harness:

program "$@"
while [ $? -e 42 ]; do
    program "$@"
done

where 42 is a return code meaning "restart, please".

Then inside the program your restart function would look like this:

void restart() {
    std::exit(42);
}
bishop
  • 32,403
  • 9
  • 89
  • 122
krzaq
  • 15,660
  • 3
  • 41
  • 59
  • 3
    The first solution will not work well if the program is not well-written. For example, if it contains a memory leaks, it will not get freed by simply going through a loop. However, the other solution you provided will handle even these kind of problems. – Humam Helfawi Oct 13 '16 at 13:53
  • 16
    @HumamHelfawi If the program has memory leaks, they should be fixed anyhow, whether it is run in a loop or not. With the same logic you could say the first approach is not good because if the program has UB it will have UB several times... – 463035818_is_not_a_number Oct 13 '16 at 13:57
  • 3
    @tobi303 No it is not good. However, the phrase "restart the program" means something like "cleaning all the garbages" or in other words: "clear everything and start fresh".. So I supposed that cleaning any leaks is part of it... Anyway, I am with you that no one leaves a leaks and use restart method to solve it. I just thought it is worth to be mentioned – Humam Helfawi Oct 13 '16 at 14:01
  • 4
    This is the most specific answer. It should be _marked as answer_. – Charles Oct 13 '16 at 14:28
  • 3
    @HumamHelfawi: Actually, I have seen programs to analyse images that made no attempt to release memory. They were single shot programs that would be rerun externally for the next image. (I often don't worry about freeing memory in small test programs either.) – Martin Bonner supports Monica Oct 13 '16 at 15:20
  • @Martin Indeed. Also freeing memory in response to being told to shut down is actually an anti-pattern - at least as far as performance is concerned. The OS will do the work for you anyhow and way faster at that. There are some programs that shall go unnamed that can spend several seconds paging in additional data just to free it afterwards.. (you may want to free everything in debug mode to make it easier to find real memory leaks). – Voo Oct 14 '16 at 10:23
  • should use -eq instead of -e – zero.zero.seven Dec 04 '20 at 06:05
  • Please, be aware that a lot of stuff runs *before* `main()`. For example, you may have code like `class Klass { ... } klass;` (this calls Klass' constructor upon loading) in libraries or even in your own code that won't be restarted by using the loop in `main()`. Dynamic library process and thread attachment code (`DllMain()` in Windows) also often runs before `main()`. Hence, a true restarting procedure requires an `exit()` and a separate restarter program or script as suggested. – Paulo Carvalho May 09 '21 at 13:03
16

On Unicies, or anywhere else you have execve and it works like the man page specifies, you can just...kill me for using atoi, because it's generally awful, except for this sort of case.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char** argv) {

  (void) argc;

  printf("arg: %s\n", argv[1]);
  int count = atoi(argv[1]);

  if ( getchar() == 'y' ) {

    ++count;

    char buf[20];
    sprintf(buf, "%d", count);

    char* newargv[3];
    newargv[0] = argv[0];
    newargv[1] = buf;
    newargv[2] = NULL;

    execve(argv[0], newargv, NULL);
  }

  return count;
}

Example:

$ ./res 1
arg: 1
y
arg: 2
y
arg: 3
y
arg: 4
y
arg: 5
y
arg: 6
y
arg: 7
n

7 | $

(7 was the return code).

It neither recurses nor explicitly loops -- instead, it just calls itself, replacing its own memory space with a new version of itself.

In this way, the stack will never overflow, though all previous variables will be redeclared, just like with any reinvocation -- the getchar call prevents 100% CPU utilisation.

In the case of a self-updating binary, since the entire binary (at least, on Unix-likes, I don't know about Windows) will be copied into memory at runtime, then if the file changes on disk before the execve(argv[0], ... call, the new binary found on disk, not the same old one, will be run instead.

As @CarstenS and @bishop point out in the comments, due to the unique way in which Unix was designed, open file descriptors are kept across fork/exec, and as a result in order to avoid leaking open file descriptors across calls to execve, you should either close them before execve or open them with e, FD_CLOEXEC / O_CLOEXEC in the first place -- more information can be found on Dan Walsh's blog.

cat
  • 3,442
  • 3
  • 28
  • 55
  • 3
    What about resources that may have been acquired? – Carsten S Oct 13 '16 at 18:57
  • 1
    @CarstenS They get leaked, probably. See http://danwalsh.livejournal.com/53603.html – bishop Oct 13 '16 at 20:23
  • @CarstenS Good question, I'll have to do some testing. My hunch is that the heap just disappears along with the *entire rest of the program memory*, and overwritten with a "fresh" heap, so they get demolished just like when a program exits. – cat Oct 13 '16 at 20:36
  • 2
    Oh, I suppose @bishop's right about open file descriptors -- those need to be closed first, or opened with `FD_CLOEXEC` in the first place. File descriptors are not what first come to my mind when someone talks about C/C++ leaks :) – cat Oct 13 '16 at 21:08
  • @CarstenS Well as I thought and as is probably obvious, heap allocations just disappear and the only leaks to be worried about are those left by the last iteration of the program. Indeed, however, it does, *of course*, leak open file descriptors. going up to `arg: 36` leaves 36 more open file descriptors in `/proc/$PID/fd`. – cat Oct 14 '16 at 01:27
  • 2
    It may be instructive to `strace` a version of this. I wrote one that terminates: `int main(int argc, char** argv) { (void)argc; printf("arg: %s\n", argv[1]); int count = atoi(argv[1]); if (count > 0) { char buf[20]; sprintf(buf, "%d", count-1); argv[1] = buf; execv(argv[0], argv); } return count; }`. You can see the startup (loading `libc`, etc) each time around. – Toby Speight Oct 14 '16 at 10:48
  • 1
    Don't do this in any security related context. This is vulnerable to launching any code an attacker might want to run. – Daniel Jour Oct 14 '16 at 13:42
  • 1
    @DanielJour Well, duh, executing arbitrary programs as this does obviously has some drawbacks -- you could checksum the binary before running it to make sure it's the one you want. – cat Oct 14 '16 at 14:07
14

This is a very OS-specific question. In Windows you can use the Application Restart API or MFC Restart Manager. In Linux you could do an exec()

However most of the time there is a better solution. You're likely better off using a loop, as suggested in other answers.

BlueRaja - Danny Pflughoeft
  • 75,675
  • 28
  • 177
  • 259
9

This sounds like the wrong approach, like all your state is global and so the only clear-cut method you have of resetting everything (other than to manually assign "default" values to each variable) is to restart the whole program.

Instead, your state should be held in objects (of class type, or whatever). You are then free to create and destroy these objects whenever you like. Each new object has a fresh state with "default" values.

Don't fight C++; use it!

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
6

You probably need a loop:

int main()
{
    while (true)
    {
        //.... Program....
    }
}

Every time you need to restart, call continue; within the loop, and to end your program, use break;.

Arnav Borborah
  • 9,956
  • 4
  • 32
  • 69
4

When I develop realtime systems my approach is normally a "derived main()" where I write all code called from a real main(), something like:

The main.cpp program:

int main (int argc, char *argv[])
{
   while (true)
   {
       if (programMain(argc, argv) == 1)
           break;
   }
}

The programmain.cpp, where all code is written:

int programMain(int argc, char *argv[])
{
    // Do whatever - the main logic goes here

    // When you need to restart the program, call
    return 0;

    // When you need to exit the program, call
    return 1;
}

In that way, every time we decide to exit the program the program will be restarted.

Detail: all variables, globals and logic must be written inside programMain()- nothing inside "main()" except the restart control.

This approach works in both Linux and Windows systems.

Mendes
  • 13,757
  • 24
  • 122
  • 217
  • Wouldn't this just loop back and call programMain again? You'd need something to break the outer while loop. I'm not a C++ guy, but I'd be surprised if a 1 return code did that, especially as you're not using it anywhere... – Alex Oct 14 '16 at 13:26
  • Yes, the idea is to call `programMain()` again, restarting the whole logic. Indeed the `return 1` can exit the loop. Edited.... – Mendes Oct 14 '16 at 14:01
  • It's clearer now. Though I would personally still prefer the approach of having a separate mini-programme to restart fully/cleanly... – Alex Oct 14 '16 at 14:30
2

It sounds to me like you're asking the wrong question because you don't know enough about coding to ask the right question.

What it sounds like you're asking for is how to write some code where, on a missed call, it loops back round to the initial state and restarts the whole call/location sequence. In which case you need to use a state machine. Look up what that is, and how to write one. This is a key software concept, and you should know it if your teachers were any good at their job.

As a side note, if your program takes 5s to initialise all your variables, it's still going to take 5s when you restart it. You can't shortcut that. So from that it should be clear that you don't actually want to kill and restart your program, because then you'll get exactly the behaviour you don't want. With a state machine you could have one initialisation state for cold startup where the system has only just been turned on, and a second initialisation state for a warm restart.

Oh, and 6 threads is not very many! :)

Graham
  • 1,597
  • 6
  • 17
  • 1
    Of course that I have a lot of to learn and improve. I do not want to restart the "whole" call/location sequence, I want to restart whole application, 7 files, sensors bias... I do want to restart my program because this is the behaviour I need. Doing a warm restart costs too much code and effort to me and I do not gain anything with it, just complicate more the code. – Julen Uranga Oct 14 '16 at 14:02
  • You want to close the files, then reopen them and re-initialise variables? Then close the files after your missed call. And use a loop to come back round and do your initialisation stuff again. I'm not trying to be rude, but there is no situation in which restarting an application is a reasonable alternative to a simple loop. If this is a uni project, you ***WILL*** get a lower grade if you demonstrate a lack of technical ability. I'm not trying to be rude, I'm trying to point you in the direction of what gets you a good grade. :) – Graham Oct 14 '16 at 15:10
1

Depending on what you mean by "restarting" the program, I can see few simple solutions.

One is to embed your whole program in some "Program" class, that essentially provides some loop that has your proper program. When you need to restart the program, you call static public method "Restart" that starts the loop again.

You could also try to make system-specific call that would start your program again, and exit. As suggested in other answer, you could create a wrapper program for this sole purpose(and check return code to know whether to quit or restart).

The other simple option is to use goto. I know that people will hate me for even mentioning it, but let's face it: we want to make simple program, not use beautiful boilerplate. Goto going back guarantees destruction, so you could create a program with a label in the beginning, and some function "Restart" that just goes back to the beginning.

Whatever option you choose, document it well, so others(or you in the future) will use one WTF less.

PS. As mentioned by alain, goto will not destroy global nor static objects, same would go for enclosing class. Therefore any approach that does not include starting new program in place of the current one should either refrain from using global/static variables, or take proper actions to re-set them(although that might be tedious, as with addition of each static/global, you need to modify the restart routine).

Community
  • 1
  • 1
MatthewRock
  • 981
  • 12
  • 28