How can a C/C++ program put itself into background?

20,592

Solution 1

My advice: don't do this, at least not under Linux/UNIX.

GUI programs under Linux/UNIX traditionally do not auto-background themselves. While this may occasionally be annoying to newbies, it has a number of advantages:

  • Makes it easy to capture standard error in case of core dumps / other problems that need debugging.

  • Makes it easy for a shell script to run the program and wait until it's completed.

  • Makes it easy for a shell script to run the program in the background and get its process id:

    gui-program &
    pid=$!
    # do something with $pid later, such as check if the program is still running
    

    If your program forks itself, this behavior will break.

"Scriptability" is useful in so many unexpected circumstances, even with GUI programs, that I would hesitate to explicitly break these behaviors.

Windows is another story. AFAIK, Windows programs automatically run in the background--even when invoked from a command shell--unless they explicitly request access to the command window.

Solution 2

On Linux, daemon() is what you're looking for, if I understand you correctly.

Solution 3

The way it's typically done on Unix-like OSes is to fork() at the beginning and exit from the parent. This won't work on Windows, but is much more elegant than launching another process where forking exists.

Solution 4

Three things need doing,

fork
setsid
redirect STDIN, STDOUT and STDERR to /dev/null

This applies to POSIX systems (all the ones you mention claim to be POSIX (but Windows stops at the claiming bit))

Solution 5

A process cannot put itself into the background, because it isn't the one in charge of background vs. foreground. That would be the shell, which is waiting for process exit. If you launch a process with an ampersand "&" at the end, then the shell does not wait for process exit.

But the only way the process can escape the shell is to fork off another child and then let its original self exit back to the waiting shell.

From the shell, you can background a process with Control-Z, then type "bg".

Share:
20,592
Larry Gritz
Author by

Larry Gritz

Software Engineering Architect, Sony Pictures Imageworks. Professional software engineer and researcher for 25 years, specializing in computer graphics for animation and visual effects. I mainly develop in C++ on Unix variants (Linux and OS X), but occasionally use Windows, Python, Perl, shell scripts, as well as programmable extension languages for a variety of packages.

Updated on November 02, 2020

Comments

  • Larry Gritz
    Larry Gritz over 3 years

    What's the best way for a running C or C++ program that's been launched from the command line to put itself into the background, equivalent to if the user had launched from the unix shell with '&' at the end of the command? (But the user didn't.) It's a GUI app and doesn't need any shell I/O, so there's no reason to tie up the shell after launch. But I want a shell command launch to be auto-backgrounded without the '&' (or on Windows).

    Ideally, I want a solution that would work on any of Linux, OS X, and Windows. (Or separate solutions that I can select with #ifdef.) It's ok to assume that this should be done right at the beginning of execution, as opposed to somewhere in the middle.

    One solution is to have the main program be a script that launches the real binary, carefully putting it into the background. But it seems unsatisfying to need these coupled shell/binary pairs.

    Another solution is to immediately launch another executed version (with 'system' or CreateProcess), with the same command line arguments, but putting the child in the background and then having the parent exit. But this seems clunky compared to the process putting itself into background.

    Edited after a few answers: Yes, a fork() (or system(), or CreateProcess on Windows) is one way to sort of do this, that I hinted at in my original question. But all of these solutions make a SECOND process that is backgrounded, and then terminate the original process. I was wondering if there was a way to put the EXISTING process into the background. One difference is that if the app was launched from a script that recorded its process id (perhaps for later killing or other purpose), the newly forked or created process will have a different id and so will not be controllable by any launching script, if you see what I'm getting at.

    Edit #2:

    fork() isn't a good solution for OS X, where the man page for 'fork' says that it's unsafe if certain frameworks or libraries are being used. I tried it, and my app complains loudly at runtime: "The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec()."

    I was intrigued by daemon(), but when I tried it on OS X, it gave the same error message, so I assume that it's just a fancy wrapper for fork() and has the same restrictions.

    Excuse the OS X centrism, it just happens to be the system in front of me at the moment. But I am indeed looking for a solution to all three platforms.

  • Larry Gritz
    Larry Gritz over 15 years
    This doesn't answer the original question, which was how to background your own process if it WASN'T launched with the '&', and you didn't want a separate shell script to do this.
  • Larry Gritz
    Larry Gritz over 15 years
    Right, I was aware of this. The point of the question was whether the program itself could do something that was the equivalent of the user hitting Ctrl-Z and then running 'bg'.
  • Thorsten79
    Thorsten79 over 15 years
    Really bad code, sorry. You assume that a) you are allowed to close stdin/stdout/stderr, b) that 0=stdin, 1=stdout|stderr, 2=stdout|stderr and c) that open() will fill the file descriptors again from 0 on.
  • Corey
    Corey over 15 years
    You can put a listener for SIGHUP, but not interactively
  • Zan Lynx
    Zan Lynx over 15 years
    No, this is very standard daemonize code. You ARE always allowed to close 0,1,2 in Unix'ish. The open function always returns the first available fd, so if 0,1,2 are closed, the next opens will be 0,1,2. If you insist, you can use dup2() to force the fds to be 0,1,2 but it isn't necessary.
  • Zan Lynx
    Zan Lynx over 15 years
    Answered in the first paragraph and the answer is "No"
  • Larry Gritz
    Larry Gritz over 15 years
    So very close! Looks great for Linux, but on OS X it appears to just wrap fork() and give the same awful runtime error message about how it's not safe to fork when using certain framework libraries.
  • Ishbir
    Ishbir over 15 years
    @Thorsten79: you obviously haven't done any POSIX programming, sorry. You might want to find a way to access a shell on a POSIXish system and try a 'man 2 open'. Typically, the first paragraph of the DESCRIPTION section will be a mind-opening experience.
  • Ishbir
    Ishbir over 15 years
    A process can always send a SUSP signal to itself, but that's only half of what Larry asked ;)
  • wnoise
    wnoise over 15 years
    POSIX does guarantee (a) and (b), but not (c). However, because of code like this almost all systems do in practice obey (c).
  • Ishbir
    Ishbir over 15 years
    @wnoise: “The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process.” conforming to POSIX.1-2001 . File descriptors 0, 1 and 2 have just been closed, no other thread running, ergo…
  • MSalters
    MSalters over 15 years
    Windows console programs do not run in the background. Windows GUI programs don't have a notion of being in the forground or background relative to a console. They're just windows in the Z-order.
  • MSalters
    MSalters over 15 years
    Ctrl-Z and "bg" command? I'ver never bothered to figure out how it works, but it has always worked for me.
  • MSalters
    MSalters over 15 years
    I'd expect it works for POSIX apps on Windows as well. But you have to realize that nobody writes POSIX apps on Windows (i.e. not an OS problem)
  • remmy
    remmy about 10 years
    Most of the time when you run something you're not interested in the output tho, and having to detach it yourself is annoying when the program can just do it by itself and have a --foreground flag if you need it.