fiber-asan.dhover×67all
#!/usr/bin/env dub
/+ dub.sdl:
    name "fiber_asan"
    platforms "linux"
    dflags "-g"
    dflags "-fsanitize=address" platform="ldc"
    targetPath "build"
+/
/**
 * AddressSanitizer catches a fiber stack-use-after-return: a `scope` delegate
 * whose closure lives in a stack frame is stored for deferred `Fiber` start,
 * and the frame dies before the fiber runs — the bug shape ASan found for
 * real in this repo (`feat/event-horizon` commit `c9537f96`, "storing scope
 * delegates for deferred fiber start is stack-use-after-return").
 *
 * Two child-process demonstrations (the parent re-execs itself and asserts on
 * each child's exit code and stderr report):
 *
 *   1. With `ASAN_OPTIONS=detect_stack_use_after_return=1` the instrumented
 *      frame lives on ASan's *fake stack* and is poisoned when the frame
 *      returns; the fiber's later call through the dead closure dies with
 *      `stack-use-after-return`, symbolized to the closure body's
 *      `file:line`, exit 1. The catch works with the stock (uninstrumented,
 *      no-`SupportSanitizers`) nixpkgs druntime — no fiber annotations are
 *      required for this particular defect because the faulting read
 *      happens in instrumented user code.
 *   2. With `detect_stack_use_after_return=0` the same child reads garbage
 *      from the reused frame and exits 0 — the bug silently corrupts. The
 *      option gate (LDC default `-fsanitize-address-use-after-return=
 *      runtime`) is what makes leg 1 switchable at run time.
 *
 * Companion to docs/research/sanitizers/d-toolchain.md
 *   § "Fibers under ASan: fake stacks and stack-use-after-return".
 *
 * Run with: dub run --single fiber-asan.d
 *
 * Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4), LDC 1.41.0
 * (LLVM 18.1.8). ASan runtime = GCC 15.2.0 `libasan.so.8` via LDC's
 * `linker-gcc.cpp` fallback (nixpkgs LDC ships no compiler-rt); druntime
 * fiber stacks are `mmap`'d with a guard page
 * (`core/thread/fiber/package.d`, `allocStack`).
 *
 * Portability: builds without instrumentation (DMD has no `-fsanitize`; the
 * flag is gated `platform="ldc"`), in which case — detected at compile time
 * via the `LDC_AddressSanitizer` predefined version — the probe prints a
 * `SKIP:` line and exits 0 so CI stays green on any host.
 */
module 
(module) fiber_asan

AddressSanitizer catches a fiber stack-use-after-return: a scope delegate whose closure lives in a stack frame is stored for deferred Fiber start, and the frame dies before the fiber runs — the bug shape ASan found for real in this repo (feat/event-horizon commit c9537f96, "storing scope delegates for deferred fiber start is stack-use-after-return").

Two child-process demonstrations (the parent re-execs itself and asserts on each child's exit code and stderr report):

  1. With ASAN_OPTIONS=detect_stack_use_after_return=1 the instrumented frame lives on ASan's fake stack and is poisoned when the frame returns; the fiber's later call through the dead closure dies with stack-use-after-return, symbolized to the closure body's file:line, exit 1. The catch works with the stock (uninstrumented, no-SupportSanitizers) nixpkgs druntime — no fiber annotations are required for this particular defect because the faulting read happens in instrumented user code.

  2. With detect_stack_use_after_return=0 the same child reads garbage from the reused frame and exits 0 — the bug silently corrupts. The option gate (LDC default -fsanitize-address-use-after-return= runtime) is what makes leg 1 switchable at run time.

Companion to docs/research/sanitizers/d-toolchain.md § "Fibers under ASan: fake stacks and stack-use-after-return".

Run with: dub run --single fiber-asan.d

Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4), LDC 1.41.0 (LLVM 18.1.8). ASan runtime = GCC 15.2.0 libasan.so.8 via LDC's linker-gcc.cpp fallback (nixpkgs LDC ships no compiler-rt); druntime fiber stacks are mmap'd with a guard page (core/thread/fiber/package.d, allocStack).

Portability

builds without instrumentation (DMD has no -fsanitize; the flag is gated platform="ldc"), in which case — detected at compile time via the LDC_AddressSanitizer predefined version — the probe prints a SKIP: line and exits 0 so CI stays green on any host.

fiber_asan
;
import
(package) std
std
.
(module) std.stdio
Category Symbols
File handles _popen File isFileHandle openNetwork stderr stdin stdout
Reading chunks lines readf readfln readln
Writing toFile write writef writefln writeln
Misc KeepTerminator LockType StdioException

Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio is publically imported when importing std.stdio.

There are three layers of I/O:

  1. The lowest layer is the operating system layer. The two main schemes are Windows and Posix.

  2. C's stdio.h which unifies the two operating system schemes.

  3. std.stdio, this module, unifies the various stdio.h implementations into a high level package for D programs.

Source

std/stdio.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Alex Rønne Petersen
stdio
:
(alias template) fiber_asan.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

Equivalent to writef(fmt, args, '\n').

writefln
,
(alias template) fiber_asan.writeln = std.stdio.writeln(T...)(T args)

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
;
version (
LDC_AddressSanitizer
LDC_AddressSanitizer
)
private enum instrumented = true; else private enum
(constant) bool fiber_asan.instrumented = false
instrumented
= false;
/// Name of the env var that arms the faulty child leg. private enum
(constant) string fiber_asan.childVar = "FIBER_ASAN_CHILD"

Name of the env var that arms the faulty child leg.

childVar
= "FIBER_ASAN_CHILD";
private
(class) core.thread.fiber.Fiber

This class provides a cooperative concurrency mechanism integrated with the threading and garbage collection functionality. Calling a fiber may be considered a blocking operation that returns when the fiber yields (via Fiber.yield()). Execution occurs within the context of the calling thread so synchronization is not necessary to guarantee memory visibility so long as the same thread calls the fiber each time. Please note that there is no requirement that a fiber be bound to one specific thread. Rather, fibers may be freely passed between threads so long as they are not currently executing. Like threads, a new fiber thread may be created using either derivation or composition, as in the following example.

Warning

Status registers are not saved by the current implementations. This means floating point exception status bits (overflow, divide by 0), rounding mode and similar stuff is set per-thread, not per Fiber!

Warning

On ARM FPU registers are not saved if druntime was compiled as ARM_SoftFloat. If such a build is used on a ARM_SoftFP system which actually has got a FPU and other libraries are using the FPU registers (other code is compiled as ARM_SoftFP) this can cause problems. Druntime must be compiled as ARM_SoftFP in this case.

@authorsBased on a design by Mikola Lysenko.
Fiber
[]
(thread local global) core.thread.fiber.Fiber[] fiber_asan.pending
pending
;
import
(package) core
core
.
(package) core.thread
thread
.
(module) core.thread.fiber

The fiber module provides lightweight threads aka fibers.

Source

core/thread/fiber/package.d

@copyrightCopyright Sean Kelly 2005 - 2012.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
fiber
:
(class) core.thread.fiber.Fiber

This class provides a cooperative concurrency mechanism integrated with the threading and garbage collection functionality. Calling a fiber may be considered a blocking operation that returns when the fiber yields (via Fiber.yield()). Execution occurs within the context of the calling thread so synchronization is not necessary to guarantee memory visibility so long as the same thread calls the fiber each time. Please note that there is no requirement that a fiber be bound to one specific thread. Rather, fibers may be freely passed between threads so long as they are not currently executing. Like threads, a new fiber thread may be created using either derivation or composition, as in the following example.

Warning

Status registers are not saved by the current implementations. This means floating point exception status bits (overflow, divide by 0), rounding mode and similar stuff is set per-thread, not per Fiber!

Warning

On ARM FPU registers are not saved if druntime was compiled as ARM_SoftFloat. If such a build is used on a ARM_SoftFP system which actually has got a FPU and other libraries are using the FPU registers (other code is compiled as ARM_SoftFP) this can cause problems. Druntime must be compiled as ARM_SoftFP in this case.

@authorsBased on a design by Mikola Lysenko.
Fiber
;
/// Stores a `scope` delegate for *deferred* start — the escape the compiler /// trusted us not to make. With `scope`, the closure may stay in the caller's /// stack frame instead of being GC-heap-allocated; keeping it past the /// frame's death is the bug. private void
void fiber_asan.spawnDeferred(scope void delegate() dg) @system

Stores a scope delegate for deferred start — the escape the compiler trusted us not to make. With scope, the closure may stay in the caller's stack frame instead of being GC-heap-allocated; keeping it past the frame's death is the bug.

spawnDeferred
(scope void delegate()
(parameter) void delegate() dg
dg
) @system
{
(thread local global) core.thread.fiber.Fiber[] fiber_asan.pending
pending
~= new
(immutable global) immutable(ulong) core.memory.pageSize

The size of a system page in bytes.

This value is set at startup time of the application. It's safe to use early in the start process, like in shared module constructors and initialization of the D runtime itself.

Examples

ubyte[] buffer = new ubyte[pageSize];
Fiber
(
(parameter) void delegate() dg
dg
);
} /// The frame that dies: `local` (captured by the nested function's closure) /// lives here, and `spawnDeferred` keeps a delegate to it. private void
void fiber_asan.scopeBody() @system

The frame that dies: local (captured by the nested function's closure) lives here, and spawnDeferred keeps a delegate to it.

scopeBody
() @system
{ int
(local variable) int local
local
= 41;
void
void fiber_asan.scopeBody.child() @safe
child
()
{ ++
(local variable) int local
local
; // read+write through the dead frame once the fiber runs
void std.stdio.writefln!(char, int)(in char[] fmt, int __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("fiber sees local = %s",
(local variable) int local
local
);
}
void fiber_asan.spawnDeferred(scope void delegate() dg) @system

Stores a scope delegate for deferred start — the escape the compiler trusted us not to make. With scope, the closure may stay in the caller's stack frame instead of being GC-heap-allocated; keeping it past the frame's death is the bug.

spawnDeferred
(&
void fiber_asan.scopeBody.child() @safe
child
);
} // scopeBody's frame is gone; pending[0] still points into it /// Child: run the deferred fiber after the owning frame returned. private int
int fiber_asan.runChildLeg()

Child

run the deferred fiber after the owning frame returned.

runChildLeg
()
{
void fiber_asan.scopeBody() @system

The frame that dies: local (captured by the nested function's closure) lives here, and spawnDeferred keeps a delegate to it.

scopeBody
();
foreach (
(parameter) core.thread.fiber.Fiber f
f
;
(thread local global) core.thread.fiber.Fiber[] fiber_asan.pending
pending
)
(local variable) core.thread.fiber.Fiber f
f
.
object.Throwable core.thread.fiber.base.FiberBase.call(core.thread.fiber.base.FiberBase.Rethrow rethrow = Rethrow.yes)

Transfers execution to this fiber object. The calling context will be suspended until the fiber calls Fiber.yield() or until it terminates via an unhandled exception.

In

This fiber must be in state HOLD.

@paramrethrow Rethrow any unhandled exception which may have caused this fiber to terminate.@throwsAny exception not handled by the joined thread.@returnsAny exception not handled by this fiber if rethrow = false, null otherwise.
call
(); // stack-use-after-return happens inside the fiber
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("child leg: fiber ran to completion (bug undetected)");
return 0; } /// Re-execs this binary with the leg armed and `detect_stack_use_after_return` /// set as given; returns (exitCode, combined output). private auto
std.typecons.Tuple!(int, "status", string, "output") fiber_asan.runChild(bool detectUar) @safe

Re-execs this binary with the leg armed and detect_stack_use_after_return set as given; returns (exitCode, combined output).

runChild
(bool
(parameter) bool detectUar
detectUar
)
{ import
(package) std
std
.
(module) std.file

Utilities for manipulating files and scanning directories. Functions in this module handle files as a unit, e.g., read or write one file at a time. For opening files and manipulating them via handles refer to module std.stdio.

Category Functions
General exists isDir isFile isSymlink rename thisExePath
Directories chdir dirEntries getcwd mkdir mkdirRecurse rmdir rmdirRecurse tempDir
Files append copy read readText remove slurp write
Symlinks symlink readLink
Attributes attrIsDir attrIsFile attrIsSymlink getAttributes getLinkAttributes getSize setAttributes
Timestamp getTimes getTimesWin setTimes timeLastModified timeLastAccessed timeStatusChanged
Other DirEntry FileException PreserveAttributes SpanMode getAvailableDiskSpace

Source

std/file.d

@copyrightCopyright The D Language Foundation 2007 - 2011.@seeThe official tutorial for an introduction to working with files in D, module std.stdio for opening files and manipulating them via handles, and module std.path for manipulating path strings.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis
file
:
(alias) thisExePath = string std.file.thisExePath() @trusted

Returns the full path of the current executable.

Returns: The path of the executable as a string.

Throws: $(REF1 Exception, object)

thisExePath
;
import
(package) std
std
.
(module) std.process

Functions for starting and interacting with other processes, and for working with the current process' execution environment.

Process handling

  • `spawnProcess` spawns a new `process`, optionally assigning it an
        

    arbitrary set of standard input, output, and error streams. The function returns immediately, leaving the child process to execute in parallel with its parent. All other functions in this module that spawn processes are built around spawnProcess.

  • `wait` makes the parent `process` wait for a child `process` to
        

    terminate. In general one should always do this, to avoid child processes becoming "zombies" when the parent process exits. Scope guards are perfect for this – see the spawnProcess documentation for examples. tryWait is similar to wait, but does not block if the process has not yet terminated.

  • `pipeProcess` also spawns a child `process` which runs
        

    in parallel with its parent. However, instead of taking arbitrary streams, it automatically creates a set of pipes that allow the parent to communicate with the child through the child's standard input, output, and/or error streams. This function corresponds roughly to C's popen function.

  • `execute` starts a new `process` and waits for it
        

    to complete before returning. Additionally, it captures the process' standard output and error streams and returns the output of these as a string.

  • `spawnShell`, `pipeShell` and `executeShell` work like
        

    spawnProcess, pipeProcess and execute, respectively, except that they take a single command string and run it through the current user's default command interpreter. executeShell corresponds roughly to C's system function.

  • `kill` attempts to terminate a running `process`.
    
    

The following table compactly summarises the different process creation functions and how they relate to each other:

Runs program directly
Runs shell command
Low-level process creation
spawnProcess
spawnShell
Automatic input/output redirection using pipes
pipeProcess
pipeShell
Execute and wait for completion, collect output
execute
executeShell

Other functionality

  • `pipe` is used to create unidirectional pipes.
    
  • `environment` is an interface through which the current `process`'
        

    environment variables can be read and manipulated.

  • `escapeShellCommand` and `escapeShellFileName` are useful
        

    for constructing shell command lines in a portable way.

Source

std/process.d

Note

Most of the functionality in this module is not available on iOS, tvOS and watchOS. The only functions available on those platforms are: environment, thisProcessID and thisThreadID.

@authorsLars Tandle Kyllingstad, Steven Schveighoffer, Vladimir Panteleev@copyrightCopyright (c) 2013, the authors. All rights reserved.@licenseBoost License 1.0.
process
:
(alias) escapeShellCommand = string std.process.escapeShellCommand(const(char[])[] args...) pure @safe

Escapes an argv-style argument array to be used with $(LREF spawnShell), $(LREF pipeShell) or $(LREF executeShell).

string url = "http://dlang.org/"; executeShell(escapeShellCommand("wget", url, "-O", "dlang-index.html"));

Concatenate multiple escapeShellCommand and $(LREF escapeShellFileName) results to use shell redirection or piping operators.

executeShell( escapeShellCommand("curl", "http://dlang.org/download.html") ~ "|" ~ escapeShellCommand("grep", "-o", http://\S*\.zip) ~ ">" ~ escapeShellFileName("D download links.txt"));

Throws: $(OBJECTREF Exception) if any part of the command line contains unescapable characters (NUL on all platforms, as well as CR and LF on Windows).

escapeShellCommand
,
(alias) executeShell = std.typecons.Tuple!(int, "status", string, "output") std.process.executeShell(scope const(char)[] command, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), ulong maxOutput = 18446744073709551615LU, scope const(char)[] workDir = null, string shellPath = nativeShell()) @safe
executeShell
;
const
(local variable) const(string[string]) env
env
= [
(constant) string fiber_asan.childVar = "FIBER_ASAN_CHILD"

Name of the env var that arms the faulty child leg.

childVar
: "1",
// detect_leaks=0 keeps the asserted exit codes purely about the // demonstrated defect; the UAR toggle is the experiment's variable. "ASAN_OPTIONS": "detect_stack_use_after_return=" ~ (
(parameter) bool detectUar
detectUar
? "1" : "0") ~ ":detect_leaks=0",
]; return
std.typecons.Tuple!(int, "status", string, "output") std.process.executeShell(scope const(char)[] command, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), ulong maxOutput = 18446744073709551615LU, scope const(char)[] workDir = null, string shellPath = nativeShell()) @safe
executeShell
(
string std.process.escapeShellCommand(const(char[])[] args...) pure @safe

Escapes an argv-style argument array to be used with spawnShell, pipeShell or executeShell.

string url = "http://dlang.org/";
executeShell(escapeShellCommand("wget", url, "-O", "dlang-index.html"));

Concatenate multiple escapeShellCommand and escapeShellFileName results to use shell redirection or piping operators.

executeShell(
    escapeShellCommand("curl", "http://dlang.org/download.html") ~
    "|" ~
    escapeShellCommand("grep", "-o", `http://\S*\.zip`) ~
    ">" ~
    escapeShellFileName("D download links.txt"));
@throwsException if any part of the command line contains unescapable characters (NUL on all platforms, as well as CR and LF on Windows).
escapeShellCommand
(
string std.file.thisExePath() @trusted

Returns the full path of the current executable.

Examples

import std.path : isAbsolute;
auto path = thisExePath();

assert(path.exists);
assert(path.isAbsolute);
assert(path.isFile);
@returnsThe path of the executable as a string.@throwsException
thisExePath
) ~ " 2>&1",
(local variable) const(string[string]) env
env
);
} version (
linux
linux
) private int
int fiber_asan.run()
run
()
{ import
(package) std
std
.
(package) std.algorithm
algorithm
.
(module) std.algorithm.searching

This is a submodule of std.algorithm. It contains generic searching algorithms.

Function Name Description
all all!"a > 0"([1, 2, 3, 4]) returns true because all elements are positive
any any!"a > 0"([1, 2, -3, -4]) returns true because at least one element is positive
balancedParens balancedParens("((1 + 1) / 2)", '(', ')') returns true because the string has balanced parentheses.
boyerMooreFinder find("hello world", boyerMooreFinder("or")) returns "orld" using the Boyer-Moore algorithm.
canFind canFind("hello world", "or") returns true.
count Counts all elements or elements matching a predicate, specific element or sub-range.

count([1, 2, 1]) returns 3, count([1, 2, 1], 1) returns 2 and count!"a < 0"([1, -3, 0]) returns 1. | | countUntil | countUntil(a, b) returns the number of steps taken in a to reach b; for example, countUntil("hello!", "o") returns 4. | | commonPrefix | commonPrefix("parakeet", "parachute") returns "para". | | endsWith | endsWith("rocks", "ks") returns true. | | extrema | extrema([2, 1, 3, 5, 4]) returns [1, 5]. | | find | find("hello world", "or") returns "orld" using linear search. (For binary search refer to SortedRange.) | | findAdjacent | findAdjacent([1, 2, 3, 3, 4]) returns the subrange starting with two equal adjacent elements, i.e. [3, 3, 4]. | | findAmong | findAmong("abcd", "qcx") returns "cd" because 'c' is among "qcx". | | findSkip | If a = "abcde", then findSkip(a, "x") returns false and leaves a unchanged, whereas findSkip(a, "c") advances a to "de" and returns true. | | findSplit | findSplit("abcdefg", "de") returns a tuple of three ranges "abc", "de", and "fg". | | findSplitAfter | findSplitAfter("abcdefg", "de") returns a tuple of two ranges "abcde" and "fg". | | findSplitBefore | findSplitBefore("abcdefg", "de") returns a tuple of two ranges "abc" and "defg". | | minCount | minCount([2, 1, 1, 4, 1]) returns tuple(1, 3). | | maxCount | maxCount([2, 4, 1, 4, 1]) returns tuple(4, 2). | | minElement | Selects the minimal element of a range. minElement([3, 4, 1, 2]) returns 1. | | maxElement | Selects the maximal element of a range. maxElement([3, 4, 1, 2]) returns 4. | | minIndex | Index of the minimal element of a range. minIndex([3, 4, 1, 2]) returns 2. | | maxIndex | Index of the maximal element of a range. maxIndex([3, 4, 1, 2]) returns 1. | | minPos | minPos([2, 3, 1, 3, 4, 1]) returns the subrange [1, 3, 4, 1], i.e., positions the range at the first occurrence of its minimal element. | | maxPos | maxPos([2, 3, 1, 3, 4, 1]) returns the subrange [4, 1], i.e., positions the range at the first occurrence of its maximal element. | | skipOver | Assume a = "blah". Then skipOver(a, "bi") leaves a unchanged and returns false, whereas skipOver(a, "bl") advances a to refer to "ah" and returns true. | | startsWith | startsWith("hello, world", "hello") returns true. | | until | Lazily iterates a range until a specific value is found. |

Source

std/algorithm/searching.d

@copyrightAndrei Alexandrescu 2008-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu
searching
:
(alias template) canFind = std.algorithm.searching.canFind(alias pred = "a == b")

Convenience function. Like find, but only returns whether or not the search was successful.

For more information about pred see $(LREF find).

See_Also: $(REF among, std,algorithm,comparison) for checking a value against multiple arguments.

canFind
;
import
(package) std
std
.
(module) std.process

Functions for starting and interacting with other processes, and for working with the current process' execution environment.

Process handling

  • `spawnProcess` spawns a new `process`, optionally assigning it an
        

    arbitrary set of standard input, output, and error streams. The function returns immediately, leaving the child process to execute in parallel with its parent. All other functions in this module that spawn processes are built around spawnProcess.

  • `wait` makes the parent `process` wait for a child `process` to
        

    terminate. In general one should always do this, to avoid child processes becoming "zombies" when the parent process exits. Scope guards are perfect for this – see the spawnProcess documentation for examples. tryWait is similar to wait, but does not block if the process has not yet terminated.

  • `pipeProcess` also spawns a child `process` which runs
        

    in parallel with its parent. However, instead of taking arbitrary streams, it automatically creates a set of pipes that allow the parent to communicate with the child through the child's standard input, output, and/or error streams. This function corresponds roughly to C's popen function.

  • `execute` starts a new `process` and waits for it
        

    to complete before returning. Additionally, it captures the process' standard output and error streams and returns the output of these as a string.

  • `spawnShell`, `pipeShell` and `executeShell` work like
        

    spawnProcess, pipeProcess and execute, respectively, except that they take a single command string and run it through the current user's default command interpreter. executeShell corresponds roughly to C's system function.

  • `kill` attempts to terminate a running `process`.
    
    

The following table compactly summarises the different process creation functions and how they relate to each other:

Runs program directly
Runs shell command
Low-level process creation
spawnProcess
spawnShell
Automatic input/output redirection using pipes
pipeProcess
pipeShell
Execute and wait for completion, collect output
execute
executeShell

Other functionality

  • `pipe` is used to create unidirectional pipes.
    
  • `environment` is an interface through which the current `process`'
        

    environment variables can be read and manipulated.

  • `escapeShellCommand` and `escapeShellFileName` are useful
        

    for constructing shell command lines in a portable way.

Source

std/process.d

Note

Most of the functionality in this module is not available on iOS, tvOS and watchOS. The only functions available on those platforms are: environment, thisProcessID and thisThreadID.

@authorsLars Tandle Kyllingstad, Steven Schveighoffer, Vladimir Panteleev@copyrightCopyright (c) 2013, the authors. All rights reserved.@licenseBoost License 1.0.
process
:
(class) std.process.environment

Manipulates environment variables using an associative-array-like interface.

This class contains only static methods, and cannot be instantiated. See below for examples of use.

environment
;
if (
(class) std.process.environment

Manipulates environment variables using an associative-array-like interface.

This class contains only static methods, and cannot be instantiated. See below for examples of use.

environment
.
string std.process.environment.get(scope const(char)[] name, string defaultValue = null) @safe

Retrieves the value of the environment variable with the given name, or a default value if the variable doesn't exist.

Unlike environment.opIndex, this function never throws on Posix.

auto sh = environment.get("SHELL", "/bin/sh");

This function is also useful in checking for the existence of an environment variable.

auto myVar = environment.get("MYVAR");
if (myVar is null)
{
    // Environment variable doesn't exist.
    // Note that we have to use 'is' for the comparison, since
    // myVar == null is also true if the variable exists but is
    // empty.
}
@paramname name of the environment variable to retrieve@paramdefaultValue default value to return if the environment variable doesn't exist.@returnsthe value of the environment variable if found, otherwise null if the environment doesn't exist.@throwsUTFException if the variable contains invalid UTF-16 characters (Windows only).
get
(
(constant) string fiber_asan.childVar = "FIBER_ASAN_CHILD"

Name of the env var that arms the faulty child leg.

childVar
) !is null)
return
int fiber_asan.runChildLeg()

Child

run the deferred fiber after the owning frame returned.

runChildLeg
();
static if (!instrumented) {
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("SKIP: built without AddressSanitizer instrumentation ",
"(DMD has no -fsanitize; LDC-only dflags are platform-gated)"); return 0; } else { const caught = runChild(true); assert(caught.status != 0, "expected ASan to abort the deferred-fiber child"); assert(caught.output.canFind("stack-use-after-return"), "expected a stack-use-after-return report; got:\n" ~ caught.output); writefln("proved: deferred fiber start through a scope delegate is " ~ "stack-use-after-return (child exit %s)", caught.status); const silent = runChild(false); assert(silent.status == 0, "expected the bug to go undetected with the fake stack disabled"); assert(!silent.output.canFind("AddressSanitizer"), "expected no ASan report with detect_stack_use_after_return=0"); writeln("proved: detect_stack_use_after_return=0 turns the same run " ~ "into silent corruption"); writeln("OK: ASan's fake stack catches the fiber " ~ "stack-use-after-return that killed event-horizon's M5 gate"); return 0; } } int
int D main()
main
()
{ version (
linux
linux
)
return
int fiber_asan.run()
run
();
else { writeln("SKIP: this probe records Linux behavior (platforms \"linux\")"); return 0; } }