Skip to content

Instantly share code, notes, and snippets.

@PetarKirov
Created October 14, 2018 16:51
Show Gist options
  • Save PetarKirov/536eb8b456cc365b7ee05133ec452627 to your computer and use it in GitHub Desktop.
Save PetarKirov/536eb8b456cc365b7ee05133ec452627 to your computer and use it in GitHub Desktop.
Example usage of posix_spawn in D
import core.sys.posix.sys.types : mode_t, pid_t;
import core.sys.posix.signal : sigset_t;
import core.sys.posix.sched : sched_param;
import core.stdc.stdio : perror, printf;
import core.stdc.errno : errno;
import core.stdc.stdlib : exit, EXIT_FAILURE;
void checkErrno(int err, const char* msg)
{
if (!err) return;
errno = err;
perror(msg);
exit(EXIT_FAILURE);
}
void ensure(bool cond, const char* msg)
{
if (cond) return;
printf("%s\n", msg);
exit(EXIT_FAILURE);
}
extern (C) extern __gshared char** environ;
extern (C) void main(int argc, const char** argv)
{
import core.sys.posix.unistd : getopt, optind, STDOUT_FILENO;
int s;
posix_spawnattr_t attr;
posix_spawnattr_t* attrp;
posix_spawn_file_actions_t file_actions;
posix_spawn_file_actions_t* file_actionsp;
/* Parse command-line options, which can be used to specify an
attributes object and file actions object for the child. */
while (true)
{
int opt = getopt(argc, argv, "sc");
if (opt == -1) break;
switch (opt)
{
default:
break;
case 'c': // -c: close standard output in child
/* Create a file actions object and add a "close"
action to it */
s = posix_spawn_file_actions_init(&file_actions);
checkErrno(s, "posix_spawn_file_actions_init");
s = posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO);
checkErrno(s, "posix_spawn_file_actions_addclose");
file_actionsp = &file_actions;
break;
case 's': // -s: block all signals in child
/* Create an attributes object and add a "set signal mask"
action to it */
s = posix_spawnattr_init(&attr);
checkErrno(s, "posix_spawnattr_init");
s = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK);
checkErrno(s, "posix_spawnattr_setflags");
import core.sys.posix.sys.wait : sigfillset;
sigset_t mask;
sigfillset(&mask);
s = posix_spawnattr_setsigmask(&attr, &mask);
checkErrno(s, "posix_spawnattr_setsigmask");
attrp = &attr;
break;
}
}
ensure(optind < argc, "Program to execute not specified");
/* Spawn the child. The name of the program to execute and the
command-line arguments are taken from the command-line arguments
of this program. The environment of the program execed in the
child is made the same as the parent's environment. */
pid_t child_pid;
s = posix_spawnp(&child_pid, argv[optind],
file_actionsp,
attrp,
&argv[optind], environ);
checkErrno(s, "posix_spawn");
/* Destroy any objects that we created earlier */
if (attrp != null)
{
s = posix_spawnattr_destroy(attrp);
checkErrno(s, "posix_spawnattr_destroy");
}
if (file_actionsp != null)
{
s = posix_spawn_file_actions_destroy(file_actionsp);
checkErrno(s, "posix_spawn_file_actions_destroy");
}
printf("PID of child: %ld\n", cast(long)child_pid);
/* Monitor status of the child until it terminates */
import core.sys.posix.sys.wait : waitpid,
WUNTRACED, WCONTINUED, WIFEXITED, WEXITSTATUS,
WIFSIGNALED, WTERMSIG, WIFSTOPPED, WSTOPSIG, WIFCONTINUED;
int status;
do
{
s = waitpid(child_pid, &status, WUNTRACED | WCONTINUED);
ensure(s != -1, "waitpid failed");
printf("Child status: ");
if (WIFEXITED(status))
printf("exited, status=%d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("killed by signal %d\n", WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("stopped by signal %d\n", WSTOPSIG(status));
else if (WIFCONTINUED(status))
printf("continued\n");
}
while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
version (Posix):
extern(C):
@nogc:
nothrow:
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t*, int);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, int, int);
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t*, int, const char*, int, mode_t);
int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t*);
int posix_spawn_file_actions_init(posix_spawn_file_actions_t*);
int posix_spawnattr_destroy(posix_spawnattr_t*);
int posix_spawnattr_getflags(const posix_spawnattr_t*, short*);
int posix_spawnattr_getpgroup(const posix_spawnattr_t*, pid_t*);
int posix_spawnattr_getschedparam(const posix_spawnattr_t*, sched_param*);
int posix_spawnattr_getschedpolicy(const posix_spawnattr_t*, int*);
int posix_spawnattr_getsigdefault(const posix_spawnattr_t*, sigset_t*);
int posix_spawnattr_getsigmask(const posix_spawnattr_t*, sigset_t*);
int posix_spawnattr_init(posix_spawnattr_t*);
int posix_spawnattr_setflags(posix_spawnattr_t*, short);
int posix_spawnattr_setpgroup(posix_spawnattr_t*, pid_t);
int posix_spawnattr_setschedparam(posix_spawnattr_t*, const sched_param*);
int posix_spawnattr_setschedpolicy(posix_spawnattr_t*, int);
int posix_spawnattr_setsigdefault(posix_spawnattr_t*, const sigset_t*);
int posix_spawnattr_setsigmask(posix_spawnattr_t*, const sigset_t*);
int posix_spawn(pid_t*pid, const char* path,
const posix_spawn_file_actions_t* file_actions,
const posix_spawnattr_t* attrp,
const char** argv, const char** envp);
int posix_spawnp(pid_t* pid, const char* file,
const posix_spawn_file_actions_t* file_actions,
const posix_spawnattr_t* attrp,
const char** argv, const char** envp);
enum
{
POSIX_SPAWN_RESETIDS = 0x01,
POSIX_SPAWN_SETPGROUP = 0x02,
POSIX_SPAWN_SETSIGDEF = 0x04,
POSIX_SPAWN_SETSIGMASK = 0x08,
POSIX_SPAWN_SETSCHEDPARAM = 0x10,
POSIX_SPAWN_SETSCHEDULER = 0x20,
}
version (CRuntime_Glibc):
enum
{
POSIX_SPAWN_USEVFORK = 0x40,
POSIX_SPAWN_SETSID = 0x80
}
struct __spawn_action
{
enum tag_t
{
spawn_do_close,
spawn_do_dup2,
spawn_do_open
}
struct close_action_t
{
int fd;
}
struct dup2_action_t
{
int fd;
int newfd;
}
struct open_action_t
{
int fd;
char*path;
int oflag;
mode_t mode;
}
tag_t tag;
union
{
close_action_t close_action;
dup2_action_t dup2_action;
open_action_t open_action;
}
}
struct posix_spawn_file_actions_t
{
int __allocated;
int __used;
__spawn_action* __actions;
int[16] __pad;
}
struct posix_spawnattr_t
{
short __flags;
pid_t __pgrp;
sigset_t __sd;
sigset_t __ss;
sched_param __sp;
int __policy;
int[16] __pad;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment