Decoded: nohup (coreutils)

[Back to Project Main Page]

Note: This page explores the design of command-line utilities. It is not a user guide.
[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]

Logical flow of nohup command (coreutils)

Summary

nohup - run a command immune to hangups

[Source] [Code Walkthrough]

Lines of code: 233
Principal syscall: execvp()
Support syscalls: dup2(), open()
Options: 0 (version and help are combined with usage())

Alternated between shell script and utility. Included in V7 UNIX (1979) and probably earlier
Added to Shellutils in July 2003 [First version]
Number of revisions: 76 [Code Evolution]

Helpers:
  • None

Setup

In main(), the following variables and flags are defined to assist in flow control:

  • exit_status_failure - Exit status to use in case of failure
  • ignoring_input - Flag to redirect input (set if a tty)
  • out_fd - The output file descriptor after redirection
  • redirecting_stderr - Flag to redirect stderr (set if tty)
  • redirecting_stdout - Flag to redirect output (set if tty)
  • saved_stderr_fd - Saves standard error in case of failure
  • stdout_is_closed - Flag set if output is invalid

In addition to the usual localization, nohup checks for the POSIXLY_CORRECT environment flag to set the proper failure status as required by POSIX 2008


Parsing

Parsing nohup is limited to checking that no options are specified and verifying that some command is provided as an argument. Any argument provided is assumed to be a command. Invalid commands fail during execution

Parsing may fail if the user provides command line options or doesn't provide any command to execution. Usage is displayed in either case.


Execution

Continuing process execution after a session ends is an ancient issue for timesharing systems. The solution is to simply ignore SIGHUP (by default, programs abnormaly raise(SIGHUP)). Disassocating a process from a user involves some extra housekeeping for standard streams. POSIX further requires a distinct failure status that distinguish between nohup failures and target execution failures. The overall flow looks like this:

nohup rewiring a process

  • Redirect tty input to dev/null as write only to force an error on read
  • Redirect tty output to nohup.out
  • Redirect tty error - retained in case of execvp() failure
    • dup2 (out_fd, STDERR_FILENO)
  • Ignore SIGHUP
    • signal (SIGHUP, SIG_IGN);
  • Execute target command
    • execvp (*cmd, cmd);

Under normal circumstances, the utility ends with execvp(). Subsequent lines of code indicate failure.

Failure cases:

  • Unable to redirect input, output, or error for a tty
  • Unable to execute specified command

[Back to Project Main Page]