spawn()

Updated: October 28, 2024

Create and execute a new child process

Synopsis:

#include <spawn.h>

pid_t spawn( const char * path,
             int fd_count,
             const int fd_map[],
             const struct inheritance * inherit,
             char * const argv[],
             char * const envp[] );

Arguments:

path
The full path name of the executable.
fd_count
The number of entries in the fd_map array. If fd_count is 0, fd_map is ignored, and the child process inherits all file descriptors (except for the ones modified with fcntl()'s F_SETFD flag).
fd_map
An array of file descriptors that you want the child process to inherit. If fd_count isn't 0, fd_map must contain at least fd_count file descriptors, up to a maximum of OPEN_MAX. The first three entries (if specified) become the child process's standard input, standard output, and standard error (stdin, stdout, and stderr).

If you set fdmap[X] to SPAWN_FDCLOSED instead of to a valid file descriptor, the file descriptor X is closed in the child process.

For more information, see Mapping file descriptors,” below.

Note: When using the fd_map parameter to spawn(), the O_CLOEXEC flag is ignored by any file descriptors referenced in the fd_map so that they can still be accessed and given to the spawned process.
inherit
A pointer to a struct inheritance that indicates what you want the child process to inherit from the parent in addition to the default attributes listed below. For more information, see inheritance structure,” below. This argument can be NULL if you want the child to inherit only the default attributes.
argv
A pointer to an argument vector. The value in argv[0] can't be NULL, and should represent the filename of the program being loaded. The last member of argv must be a NULL pointer. The value of argv can't be NULL.
envp
A pointer to an array of character pointers, each pointing to a string defining an environment variable. The array is terminated with a NULL pointer. Each pointer points to a character string of the form:
variable=value

that's used to define an environment variable. If the value of envp is NULL, then the child process inherits the environment of the parent process.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The spawn() function creates and executes a new child process, named in path.

Note:
  • In order to create a child process, your process must have the PROCMGR_AID_SPAWN ability enabled. In order to create a new application ID for the child process, your process must have the PROCMGR_AID_CHILD_NEWAPP ability enabled.
  • If the new child process is a shell script, the first line must start with #!, followed by the path of the program to run to interpret the script, optionally followed by one argument. The script must also be marked as executable. For more information, see The first line in the Writing Shell Scripts chapter of the QNX Neutrino User's Guide.
  • If the child will link a library at load time or at run time (i.e., with dlopen()), the child must be given the PROCMGR_AID_PROT_EXEC and PROCMGR_AID_MAP_FIXED abilities. For more information, see procmgr_ability().

The spawn() function is provided for backwards compatibility with older versions of QNX Neutrino. Instead, use posix_spawn(). The C library also includes other specialized spawn*() convenience functions. Their names consist of spawn followed by a letter or letters.

The child process inherits the following attributes of the parent process or thread (as appropriate):

The child process has several differences from the parent process or thread (as appropriate):

The child process also has these differences from the parent process if you haven't set the SPAWN_EXEC flag:

The child process can access its environment by using the environ global variable (found in <unistd.h>).

If the path is on a filesystem mounted with the ST_NOSUID flag set, the effective user ID, effective group ID, saved set-user ID and saved set-group ID are unchanged for the child process. Otherwise, if the set-user ID mode bit is set, the effective user ID of the child process is set to the owner ID of path. Similarly, if the set-group ID mode bit is set, the effective group ID of the child process is set to the group ID of path.

The real user ID, real group ID and supplementary group IDs of the child process remain the same as those of the parent process. The effective user ID and effective group ID of the child process are saved as the saved set-user ID and the saved set-group ID used by the setuid().

Note: A parent/child relationship doesn't imply that the child process dies when the parent process dies.

Mapping file descriptors

As described above, you can use the fd_count and fd_map arguments to specify which file descriptors you want the child process to inherit.

The number used for a file descriptor in the child process depends on its position in fd_map, not on the actual file descriptor in the parent. For example, suppose the parent has file descriptors valued 1, 3, and 5 that you want to have in the child process. If you specify:
int fd_map = { 1, 3, 5 };
then the mapping is as follows:
In the child, this fd: Is the same as this fd in the parent:
0 1
1 3
2 5
If 1, 3, and 5 are the only file descriptors open in the parent, and you specify an fd_count of 0, the function duplicates all the file descriptors:
In the child, this fd: Is the same as this fd in the parent:
1 1
3 3
5 5

and file descriptors 0, 2, 4, and 6 (and higher) are closed.

If you're using an explicit fd_map, then in order to get numerically matching file descriptors in the child and the parent, you must fill the holes in the map with SPAWN_FDCLOSED:
int fd_map = { SPAWN_FDCLOSED, 1, SPAWN_FDCLOSED, 3, SPAWN_FDCLOSED, 5 };
Note: Be careful if you use SPAWN_FDCLOSED for file descriptors 0, 1, and 2. If the child process calls open(), the function assigns the lowest numbered unused file descriptor. If, for example, you set stdout or 1 to SPAWN_FDCLOSED, the next open() in the spawned application is assigned file descriptor 1. In this case, printf() would write to whatever resource was opened, which may or may not be what you intended.

It's safer to set 0, 1 and 2 to be the file descriptor from an open() of a known resource (such as /dev/null) in the parent, and then pass those file descriptors to the child.

inheritance structure

The inheritance structure contains at least these members:

uint32_t flags
Zero or more of the following bits:
  • SPAWN_ALIGN_DEFAULT — use the system's default settings for alignment.
  • SPAWN_ALIGN_FAULT — try to always fault data misalignment references.
  • SPAWN_ALIGN_NOFAULT — don't fault on misalignment; attempt to fix it (this may be slow).
  • SPAWN_ASLR_INVERT — toggle the Address Space Layout Randomization bit. If the parent has ASLR enabled, turn it off for the child; if the parent's bit is off, turn it on for the child.
  • SPAWN_CHECK_SCRIPT — if unable to run path in any other way, start a shell, passing path as a script.
  • SPAWN_CRITICAL (QNX Neutrino 7.0.4 or later) — indicate that the new process is critical to system functionality, meaning if the process dies, the system will crash. To create a critical process with SPAWN_CRITICAL, your process needs the PROCMGR_AID_REBOOT ability. For more information, see procmgr_ability().
  • SPAWN_DEBUG — debug process (this is used only for debugging the kernel itself).
  • SPAWN_EXEC — cause the spawn to act like exec*(): replace the calling program in memory with the newly loaded program. If successful, no return is made to the calling program.
  • SPAWN_EXPLICIT_CPU — (QNX Neutrino Core OS 6.3.2 or later) Set the runmask and inherit mask equal to the runmask member of the inheritance structure. If this flag isn't set, the child inherits the inherit mask of the calling thread.
  • SPAWN_EXPLICIT_SCHED — set the scheduling policy to the value of the policy member, and the scheduling parameters to the value of the param member.
  • SPAWN_HOLD — hold a process for debugging (i.e., send the SIGSTOP signal to the process before it executes its first instruction).
  • SPAWN_NEWAPP — assign a new application ID to the process. If you don't set this flag, the process inherits the parent's application ID. For more information, see "Application groups" in the QNX Neutrino System Security Guide.
  • SPAWN_NOZOMBIE — prevent the child process from becoming a zombie on its death. No child return or exit information will be available.
  • SPAWN_SETGROUP — set the child's process group to the value in the pgroup member. If this flag isn't set, the child process is part of the current process group.
  • SPAWN_SETSID — make the new process a session leader.
  • SPAWN_SETSIGDEF — use the sigdefault member to specify the child process's set of defaulted signals. If you don't specify this flag, the child process inherits the parent process's signal actions.
  • SPAWN_SETSIGIGN — set the handling for signals defined in the sigignore member to SIG_IGN.
  • SPAWN_SETSIGMASK — use the sigmask member to specify the child process's signal mask.
  • SPAWN_SETSTACKMAX — set the maximum stack size to the value of the stack_max member.
  • SPAWN_TCSETPGROUP — start a new terminal group.

The <spawn.h> file also defines SPAWN_ALIGN_MASK. It's a mask for the alignment flags listed above.

pid_t pgroup
The child process's group if you specify SPAWN_SETGROUP in the flags member.

If SPAWN_SETGROUP is set in inherit->flags and inherit->pgroup is set to SPAWN_NEWPGROUP, the child process starts a new process group with the process group ID set to its process ID.

uint32_t runmask
(QNX Neutrino Core OS 6.3.2 or later) If you specify SPAWN_EXPLICIT_CPU in the flags member, the child process's runmask and inherit mask are set to the value of this member. For more information, see the Multicore Processing chapter of the QNX Neutrino Programmer's Guide.
sigset_t sigmask
The child process's signal mask if you specify SPAWN_SETSIGMASK in the flags member.
sigset_t sigdefault
The child process's set of defaulted signals if you specify SPAWN_SETSIGDEF in the flags member.
sigset_t sigignore
The child process's set of ignored signals if you specify SPAWN_SETSIGIGN in the flags member.
uint32_t stack_max
The maximum stack size for the child process, if you set SPAWN_SETSTACKMAX in the flags member.
int32_t policy
The scheduling policy for the child process, if you set SPAWN_EXPLICIT_SCHED in the flags member. The policy must be one of the following:
  • SCHED_FIFO — a fixed-priority scheduler in which the highest priority ready thread runs until it blocks or is preempted by a higher priority thread.
  • SCHED_RR — similar to SCHED_FIFO, except that threads at the same priority level timeslice (round robin) every 4 × the clock period (see ClockPeriod()).
  • SCHED_OTHER — currently the same as SCHED_RR.
  • SCHED_SPORADIC — sporadic scheduling.
struct sched_param param
Scheduling parameters for the child process, if you set SPAWN_EXPLICIT_SCHED in the flags member. For more information, see the documentation for sched_param.
Note: In order to create a thread whose priority is above the maximum permitted for unprivileged processes, your process must have the PROCMGR_AID_PRIORITY ability enabled. For more information, see procmgr_ability().

Returns:

The process ID of the child process, or -1 if an error occurs (errno is set).

Note: If you set SPAWN_EXEC in the flags member of the inheritance structure, spawn() doesn't return, unless an error occurred.

Errors:

E2BIG
The number of bytes used by the argument list and environment list of the new child process is greater than ARG_MAX bytes.
EACCES
The calling process doesn't have permission to search a directory listed in path, or it doesn't have permission to execute path, or path's filesystem was mounted with the ST_NOEXEC flag.
EAGAIN
Insufficient resources available to create the child process.
EBADF
An entry in fd_map refers to an invalid file descriptor, or an error occurred duplicating open file descriptors to the new process.
EFAULT
One of the buffers specified in the function call is invalid.
EINTR
The function was interrupted by a signal.
EINVAL
An argument is invalid (e.g., argv[0] is NULL).
ELOOP
Too many levels of symbolic links or prefixes.
EMFILE
Insufficient resources available to load the new executable image or to remap file descriptors in the child process.
ENAMETOOLONG
The length of path exceeds PATH_MAX.
ENOENT
The file identified by the path argument is empty, or one or more components of the pathname of the child process don't exist.
ENOEXEC
The child process's file has the correct permissions, but isn't in the correct format for an executable. (This error doesn't occur if SPAWN_CHECK_SCRIPT is set in the flags member of the inheritance structure.)
ENOMEM
Insufficient memory available to create the child process.
ENOSYS
The spawn() function isn't implemented for the filesystem underlying the path specified in path.
ENOTDIR
A component of the path prefix of the child process isn't a directory.
EPERM
The calling process doesn't have the required permission (see procmgr_ability()), or an underlying call to mmap() failed because it attempted to set PROT_EXEC for a region of memory covered by an untrusted memory-mapped file.
ETXTBSY
The text file that you're trying to execute is busy (e.g., it might be open for writing).

See also the errors for ConnectAttach() and MsgSendvnc().

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes