lsan-gc-interplay.dhover×209all
#!/usr/bin/env dub
/+ dub.sdl:
    name "sanitizers_lsan_gc_interplay"
    platforms "linux"
    targetPath "build"
    dflags "-g"
    dflags "-fsanitize=leak" platform="ldc"
+/
/**
 * Standalone LeakSanitizer vs the D garbage collector, four quadrants — the
 * blind spots a `--sanitize=leak` runner mode must document:
 *
 *   1. Q1 `malloc(1001)`, unreachable            -> reported (true leak).
 *   2. Q2 `malloc(2002)` referenced ONLY from a GC array -> reported anyway:
 *      a FALSE POSITIVE. LSan's flood fill follows pointers only through its
 *      own allocator's chunks (compiler-rt `lsan_common.cpp`,
 *      `ClassifyAllChunks`); the D GC's mmap'd pools are not chunks, so
 *      pointers stored in GC memory are invisible to the scan.
 *   3. Q3 `new ubyte[4004]` dropped              -> NOT reported: GC
 *      allocations don't come from the intercepted `malloc`, so true GC
 *      leaks are invisible to LSan.
 *   4. Q4 `malloc(5005)` referenced from a `__gshared` global -> silent:
 *      the root scan does cover D's `.data`/`.bss`.
 *
 * Also demonstrated, correcting a natural assumption: `detect_leaks=0`
 * disables the MANUAL check entry points too (`__lsan_do_leak_check` is
 * gated on the flag, compiler-rt `lsan_common.cpp:1193-1197`) — the
 * composable recipe for per-test checking is `leak_check_at_exit=0` plus
 * repeated `__lsan_do_recoverable_leak_check()`. Standalone LSan exits with
 * code 23 on leaks (`lsan.cpp:61`).
 *
 * No `LDC_LeakSanitizer` version identifier exists (LDC predefines them only
 * for address/memory/thread — `driver/main.cpp:1030-1041` @ v1.41.0), so
 * this probe detects instrumentation at RUNTIME via
 * `dlsym(RTLD_DEFAULT, "__lsan_do_leak_check")`; all `__lsan_*` calls go
 * through the resolved pointers so uninstrumented builds still link.
 *
 * Companion to docs/research/sanitizers/asan.md
 *   § "LeakSanitizer and the D GC".
 *
 * Run with: dub run --single lsan-gc-interplay.d
 *
 * Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX, LDC 1.41.0
 * (LLVM 18.1.8), GCC 15.2 `liblsan.so.0` runtime via LDC's gcc link fallback.
 *
 * Portability: uninstrumented builds (DMD; the dflag is LDC-gated) find no
 * `__lsan_*` symbols, print a `SKIP:` line and exit 0.
 */
module 
(module) sanitizers_lsan_gc_interplay

Standalone LeakSanitizer vs the D garbage collector, four quadrants — the blind spots a --sanitize=leak runner mode must document:

  1. Q1 malloc(1001), unreachable -> reported (true leak).

  2. Q2 malloc(2002) referenced ONLY from a GC array -> reported anyway: a FALSE POSITIVE. LSan's flood fill follows pointers only through its own allocator's chunks (compiler-rt lsan_common.cpp, ClassifyAllChunks); the D GC's mmap'd pools are not chunks, so pointers stored in GC memory are invisible to the scan.

  3. Q3 new ubyte[4004] dropped -> NOT reported: GC allocations don't come from the intercepted malloc, so true GC leaks are invisible to LSan.

  4. Q4 malloc(5005) referenced from a __gshared global -> silent: the root scan does cover D's .data/.bss.

Also demonstrated, correcting a natural assumption: detect_leaks=0 disables the MANUAL check entry points too (__lsan_do_leak_check is gated on the flag, compiler-rt lsan_common.cpp:1193-1197) — the composable recipe for per-test checking is leak_check_at_exit=0 plus repeated __lsan_do_recoverable_leak_check(). Standalone LSan exits with code 23 on leaks (lsan.cpp:61).

No LDC_LeakSanitizer version identifier exists (LDC predefines them only for address/memory/thread — driver/main.cpp:1030-1041 @ v1.41.0), so this probe detects instrumentation at RUNTIME via dlsym(RTLD_DEFAULT, "__lsan_do_leak_check"); all __lsan_* calls go through the resolved pointers so uninstrumented builds still link.

Companion to docs/research/sanitizers/asan.md § "LeakSanitizer and the D GC".

Run with: dub run --single lsan-gc-interplay.d

Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX, LDC 1.41.0 (LLVM 18.1.8), GCC 15.2 liblsan.so.0 runtime via LDC's gcc link fallback.

Portability

uninstrumented builds (DMD; the dflag is LDC-gated) find no __lsan_* symbols, print a SKIP: line and exit 0.

sanitizers_lsan_gc_interplay
;
version (
linux
linux
)
{ 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) sanitizers_lsan_gc_interplay.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

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

writefln
;
enum
(constant) string sanitizers_lsan_gc_interplay.childEnvVar = "SANITIZERS_PROBE_CHILD"
childEnvVar
= "SANITIZERS_PROBE_CHILD";
alias
(alias) sanitizers_lsan_gc_interplay.FatalCheckFn = extern (C) void function()
FatalCheckFn
= extern (C) void function();
alias
(alias) sanitizers_lsan_gc_interplay.RecoverableCheckFn = extern (C) int function()
RecoverableCheckFn
= extern (C) int function();
/// Runtime instrumentation detection: resolve the LSan entry points via /// `dlsym` so an uninstrumented binary still links (and SKIPs). bool
bool sanitizers_lsan_gc_interplay.lsanLive(out extern (C) void function() fatal, out extern (C) int function() recoverable)

Runtime instrumentation detection: resolve the LSan entry points via dlsym so an uninstrumented binary still links (and SKIPs).

lsanLive
(out
(alias) sanitizers_lsan_gc_interplay.FatalCheckFn = extern (C) void function()
FatalCheckFn
(parameter) extern (C) void function() fatal
fatal
, out
(alias) sanitizers_lsan_gc_interplay.RecoverableCheckFn = extern (C) int function()
RecoverableCheckFn
(parameter) extern (C) int function() recoverable
recoverable
)
{ import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.linux
linux
.
(module) core.sys.linux.dlfcn

D header file for GNU/Linux

glibc dlfcn/dlfcn.h

dlfcn
:
(alias) dlsym = void* core.sys.posix.dlfcn.dlsym(void*, scope const(char*)) nothrow @nogc
dlsym
,
(alias constant) RTLD_DEFAULT = void* core.sys.linux.dlfcn.RTLD_DEFAULT = cast(void*)cast(size_t)0LU
RTLD_DEFAULT
;
(parameter) extern (C) void function() fatal
fatal
= cast(
(alias) sanitizers_lsan_gc_interplay.FatalCheckFn = extern (C) void function()
FatalCheckFn
)
void* core.sys.posix.dlfcn.dlsym(void*, scope const(char*)) nothrow @nogc
dlsym
(
(constant) void* core.sys.linux.dlfcn.RTLD_DEFAULT = cast(void*)cast(size_t)0LU
RTLD_DEFAULT
, "__lsan_do_leak_check");
(parameter) extern (C) int function() recoverable
recoverable
= cast(
(alias) sanitizers_lsan_gc_interplay.RecoverableCheckFn = extern (C) int function()
RecoverableCheckFn
)
void* core.sys.posix.dlfcn.dlsym(void*, scope const(char*)) nothrow @nogc
dlsym
(
(constant) void* core.sys.linux.dlfcn.RTLD_DEFAULT = cast(void*)cast(size_t)0LU
RTLD_DEFAULT
,
"__lsan_do_recoverable_leak_check"); return
(parameter) extern (C) void function() fatal
fatal
!is null &&
(parameter) extern (C) int function() recoverable
recoverable
!is null;
} __gshared void*[]
(__gshared global) void*[] sanitizers_lsan_gc_interplay.gcKeeper

keeps the Q2 GC array alive via a data root

gcKeeper
; /// keeps the Q2 GC array alive via a data root
__gshared void*
(__gshared global) void* sanitizers_lsan_gc_interplay.mallocKeeper

Q4

a reachable malloc block

mallocKeeper
; /// Q4: a reachable malloc block
void
void sanitizers_lsan_gc_interplay.makeLeaks()
makeLeaks
()
{ import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) malloc = void* core.stdc.stdlib.malloc(ulong size) nothrow @nogc
malloc
;
void*
(local variable) void* q1
q1
=
void* core.stdc.stdlib.malloc(ulong size) nothrow @nogc
malloc
(1001); // Q1: unreachable malloc -> true leak
(local variable) void* q1
q1
= null;
auto
(local variable) void*[] arr
arr
= new void*[4]; // a GC allocation (mmap'd pool)
(local variable) void*[] arr
arr
[0] =
void* core.stdc.stdlib.malloc(ulong size) nothrow @nogc
malloc
(2002); // Q2: only reference lives in GC memory
(__gshared global) void*[] sanitizers_lsan_gc_interplay.gcKeeper

keeps the Q2 GC array alive via a data root

gcKeeper
=
(local variable) void*[] arr
arr
;
auto
(local variable) ubyte[] q3
q3
= new ubyte[4004]; // Q3: dropped GC allocation
(local variable) ubyte[] q3
q3
= null;
(__gshared global) void* sanitizers_lsan_gc_interplay.mallocKeeper

Q4

a reachable malloc block

mallocKeeper
=
void* core.stdc.stdlib.malloc(ulong size) nothrow @nogc
malloc
(5005); // Q4: reachable from .data — no leak
} /// Scrub a few KB of stack so dead pointer copies from `makeLeaks` don't /// make Q1/Q2 spuriously reachable to LSan's conservative scan. void
void sanitizers_lsan_gc_interplay.scrubStack()

Scrub a few KB of stack so dead pointer copies from makeLeaks don't make Q1/Q2 spuriously reachable to LSan's conservative scan.

scrubStack
()
{ import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
;
ubyte[8192]
(local variable) ubyte[8192] pad
pad
= 0;
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("",
(local variable) ubyte[8192] pad
pad
.
(constant) ubyte* ubyte[8192].ptr = &pad
ptr
);
} void
void sanitizers_lsan_gc_interplay.childDemo(extern (C) void function() fatal, extern (C) int function() recoverable)
childDemo
(
(alias) sanitizers_lsan_gc_interplay.FatalCheckFn = extern (C) void function()
FatalCheckFn
(parameter) extern (C) void function() fatal
fatal
,
(alias) sanitizers_lsan_gc_interplay.RecoverableCheckFn = extern (C) int function()
RecoverableCheckFn
(parameter) extern (C) int function() recoverable
recoverable
)
{ import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) fprintf = int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogc
fprintf
,
(alias shared global) stderr = shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderr
stderr
;
void sanitizers_lsan_gc_interplay.makeLeaks()
makeLeaks
();
void sanitizers_lsan_gc_interplay.scrubStack()

Scrub a few KB of stack so dead pointer copies from makeLeaks don't make Q1/Q2 spuriously reachable to LSan's conservative scan.

scrubStack
();
const
(local variable) const(int) n
n
=
(parameter) extern (C) int function() recoverable
recoverable
(); // prints a report, does NOT die
int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogc
fprintf
(
(shared global) shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderr
stderr
, "recoverable returned %d\n",
(local variable) const(int) n
n
);
(parameter) extern (C) void function() fatal
fatal
(); // dies with exit code 23 when leaks were found ...
int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogc
fprintf
(
(shared global) shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderr
stderr
, "survived both manual checks\n"); // ... else reached
} int
int sanitizers_lsan_gc_interplay.spawnChild(string[string] extraEnv, out string output)
spawnChild
(
(alias) object.string = string
string
[
(alias) object.string = string
string
]
(parameter) string[string] extraEnv
extraEnv
, out
(alias) object.string = string
string
(parameter) string output
output
)
{ import
(package) std
std
.
(module) std.array

Functions and types that manipulate built-in arrays and associative arrays.

This module provides all kinds of functions to create, manipulate or convert arrays:

Function Name Description

| array | Returns a copy of the input in a newly allocated dynamic array. | | appender | Returns a new Appender or RefAppender initialized with a given array. | | assocArray | Returns a newly allocated associative array from a range/ranges of keys and values. | | byPair | Construct a range iterating over an associative array by key/value tuples. | | insertInPlace | Inserts into an existing array at a given position. | | join | Concatenates a range of ranges into one array. | | minimallyInitializedArray | Returns a new array of type T. | | replace | Returns a new array with all occurrences of a certain subrange replaced. | | replaceFirst | Returns a new array with the first occurrence of a certain subrange replaced. | | replaceInPlace | Replaces all occurrences of a certain subrange and puts the result into a given array. | | replaceInto | Replaces all occurrences of a certain subrange and puts the result into an output range. | | replaceLast | Returns a new array with the last occurrence of a certain subrange replaced. | | replaceSlice | Returns a new array with a given slice replaced. | | replicate | Creates a new array out of several copies of an input array or range. | | sameHead | Checks if the initial segments of two arrays refer to the same place in memory. | | sameTail | Checks if the final segments of two arrays refer to the same place in memory. | | split | Eagerly split a range or string into an array. | | staticArray | Creates a new static array from given data. | | uninitializedArray | Returns a new array of type T without initializing its elements. |

Source

std/array.d

@copyrightCopyright Andrei Alexandrescu 2008- and Jonathan M Davis 2011-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu and Jonathan M Davis
array
:
(alias template) array = std.array.array(Range)(Range r) if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range)

Allocates an array and initializes it with copies of the elements of range r.

Narrow strings are handled as follows:

  • If autodecoding is turned on (default), then they are handled as a separate overload.

  • If autodecoding is turned off, then this is equivalent to duplicating the array.

Params: r = range (or aggregate with opApply function) whose elements are copied into the allocated array Returns: allocated and initialized array

array
,
(alias template) join = std.array.join(RoR, R)(RoR ror, R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && (is(immutable(ElementType!(ElementType!RoR)) == immutable(ElementType!R)) || isSomeChar!(ElementType!(ElementType!RoR)) && isSomeChar!(ElementType!R)))

Eagerly concatenates all of the ranges in ror together (with the GC) into one array using sep as the separator if present.

Params: ror = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of input ranges sep = An input range, or a single element, to join the ranges on

Returns: An array of elements

See_Also: For a lazy version, see $(REF joiner, std,algorithm,iteration)

join
;
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) pipeProcess = std.process.ProcessPipes std.process.pipeProcess(scope const(char[])[] args, std.process.Redirect redirect = Redirect.all, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), scope const(char)[] workDir = null) @safe

Starts a new process, creating pipes to redirect its standard input, output and/or error streams.

pipeProcess and pipeShell are convenient wrappers around $(LREF spawnProcess) and $(LREF spawnShell), respectively, and automate the task of redirecting one or more of the child process' standard streams through pipes. Like the functions they wrap, these functions return immediately, leaving the child process to execute in parallel with the invoking process. It is recommended to always call $(LREF wait) on the returned $(LREF ProcessPipes.pid), as detailed in the documentation for wait.

The args/program/command, env and config parameters are forwarded straight to the underlying spawn functions, and we refer to their documentation for details.

Params: args = An array which contains the program name as the zeroth element and any command-line arguments in the following elements. (See $(LREF spawnProcess) for details.) program = The program name, $(I without) command-line arguments. (See $(LREF spawnProcess) for details.) command = A shell command which is passed verbatim to the command interpreter. (See $(LREF spawnShell) for details.) redirect = Flags that determine which streams are redirected, and how. See $(LREF Redirect) for an overview of available flags. env = Additional environment variables for the child process. (See $(LREF spawnProcess) for details.) config = Flags that control process creation. See $(LREF Config) for an overview of available flags, and note that the `retainStd...` flags have no effect in this function. workDir = The working directory for the new process. By default the child process inherits the parent's working directory. shellPath = The path to the shell to use to run the specified program. By default this is $(LREF nativeShell).

Returns: A $(LREF ProcessPipes) object which contains $(REF File, std,stdio) handles that communicate with the redirected streams of the child process, along with a $(LREF Pid) object that corresponds to the spawned process.

Throws: $(LREF ProcessException) on failure to start the process.$(BR) $(REF StdioException, std,stdio) on failure to redirect any of the streams.$(BR)

Example:

// my_application writes to stdout and might write to stderr auto pipes = pipeProcess("my_application", Redirect.stdout | Redirect.stderr); scope(exit) wait(pipes.pid);

// Store lines of output. string[] output; foreach (line; pipes.stdout.byLine) output ~= line.idup;

// Store lines of errors. string[] errors; foreach (line; pipes.stderr.byLine) errors ~= line.idup;

// sendmail expects to read from stdin pipes = pipeProcess("/usr/bin/sendmail", "-t", Redirect.stdin); pipes.stdin.writeln("To: you"); pipes.stdin.writeln("From: me"); pipes.stdin.writeln("Subject: dlang"); pipes.stdin.writeln(""); pipes.stdin.writeln(message);

// a single period tells sendmail we are finished pipes.stdin.writeln(".");

// but at this point sendmail might not see it, we need to flush pipes.stdin.flush();

// sendmail happens to exit on ".", but some you have to close the file: pipes.stdin.close();

// otherwise this wait will wait forever wait(pipes.pid);

---

pipeProcess
,
(enum) std.process.Redirect

Flags that can be passed to pipeProcess and pipeShell to specify which of the child process' standard streams are redirected. Use bitwise OR to combine flags.

Redirect
,
(alias) wait = int std.process.wait(std.process.Pid pid) @safe

Waits for the process associated with pid to terminate, and returns its exit status.

In general one should always _wait for child processes to terminate before exiting the parent process unless the process was spawned as detached (that was spawned with Config.detached flag). Otherwise, they may become "$(HTTP en.wikipedia.org/wiki/Zombie_process,zombies)" – processes that are defunct, yet still occupy a slot in the OS process table. You should not and must not wait for detached processes, since you don't own them.

If the process has already terminated, this function returns directly. The exit code is cached, so that if wait() is called multiple times on the same $(LREF Pid) it will always return the same value.

POSIX_specific: If the process is terminated by a signal, this function returns a negative number whose absolute value is the signal number. Since POSIX restricts normal exit codes to the range 0-255, a negative return value will always indicate termination by signal. Signal codes are defined in the core.sys.posix.signal module (which corresponds to the signal.h POSIX header).

Throws: $(LREF ProcessException) on failure or on attempt to wait for detached process.

Example: See the $(LREF spawnProcess) documentation.

See_also: $(LREF tryWait), for a non-blocking function.

wait
;
auto
(local variable) std.process.ProcessPipes p
p
=
std.process.ProcessPipes std.process.pipeProcess(scope const(char[])[] args, std.process.Redirect redirect = Redirect.all, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), scope const(char)[] workDir = null) @safe

Starts a new process, creating pipes to redirect its standard input, output and/or error streams.

pipeProcess and pipeShell are convenient wrappers around spawnProcess and spawnShell, respectively, and automate the task of redirecting one or more of the child process' standard streams through pipes. Like the functions they wrap, these functions return immediately, leaving the child process to execute in parallel with the invoking process. It is recommended to always call wait on the returned ProcessPipes.pid, as detailed in the documentation for wait.

The args/program/command, env and config parameters are forwarded straight to the underlying spawn functions, and we refer to their documentation for details.

Example

// my_application writes to stdout and might write to stderr
auto pipes = pipeProcess("my_application", Redirect.stdout | Redirect.stderr);
scope(exit) wait(pipes.pid);

// Store lines of output.
string[] output;
foreach (line; pipes.stdout.byLine) output ~= line.idup;

// Store lines of errors.
string[] errors;
foreach (line; pipes.stderr.byLine) errors ~= line.idup;


// sendmail expects to read from stdin
pipes = pipeProcess(["/usr/bin/sendmail", "-t"], Redirect.stdin);
pipes.stdin.writeln("To: you");
pipes.stdin.writeln("From: me");
pipes.stdin.writeln("Subject: dlang");
pipes.stdin.writeln("");
pipes.stdin.writeln(message);

// a single period tells sendmail we are finished
pipes.stdin.writeln(".");

// but at this point sendmail might not see it, we need to flush
pipes.stdin.flush();

// sendmail happens to exit on ".", but some you have to close the file:
pipes.stdin.close();

// otherwise this wait will wait forever
wait(pipes.pid);

@paramargs An array which contains the program name as the zeroth element and any command-line arguments in the following elements. (See spawnProcess for details.)@paramprogram The program name, without command-line arguments. (See spawnProcess for details.)@paramcommand A shell command which is passed verbatim to the command interpreter. (See spawnShell for details.)@paramredirect Flags that determine which streams are redirected, and how. See Redirect for an overview of available flags.@paramenv Additional environment variables for the child process. (See spawnProcess for details.)@paramconfig Flags that control process creation. See Config for an overview of available flags, and note that the retainStd... flags have no effect in this function.@paramworkDir The working directory for the new process. By default the child process inherits the parent's working directory.@paramshellPath The path to the shell to use to run the specified program. By default this is nativeShell.@returnsA ProcessPipes object which contains File handles that communicate with the redirected streams of the child process, along with a Pid object that corresponds to the spawned process.@throws

ProcessException on failure to start the process.

StdioException on failure to redirect any of the streams.

pipeProcess
([
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
],
(enum) std.process.Redirect

Flags that can be passed to pipeProcess and pipeShell to specify which of the child process' standard streams are redirected. Use bitwise OR to combine flags.

Redirect
.
(enum value) std.process.Redirect.stdout = 2

Redirect the standard input, output or error streams, respectively.

stdout
|
(enum) std.process.Redirect

Flags that can be passed to pipeProcess and pipeShell to specify which of the child process' standard streams are redirected. Use bitwise OR to combine flags.

Redirect
.
(enum value) std.process.Redirect.stderrToStdout = 8

Redirect the standard error stream into the standard output stream. This can not be combined with Redirect.stderr.

stderrToStdout
,
(parameter) string[string] extraEnv
extraEnv
);
(parameter) string output
output
=
(local variable) std.process.ProcessPipes p
p
.
std.stdio.File std.process.ProcessPipes.stdout() nothrow @property @safe

An File that allows reading from the child process' standard output stream.

@throwsError if the child process' standard output stream hasn't been redirected.
stdout
.
std.stdio.File.ByLineCopy!(immutable(char), char) std.stdio.File.byLineCopy!(char, immutable(char))(std.typecons.Flag!"keepTerminator" keepTerminator = Flag.no, char terminator = '\n') @system

Returns an input range set up to read from the file handle one line at a time. Each line will be newly allocated. front will cache its value to allow repeated calls without unnecessary allocations.

Note

Due to caching byLineCopy can be more memory-efficient than File.byLine.map!idup.

The element type for the range will be Char[]. Range primitives may throw StdioException on I/O error.

Example

import std.algorithm, std.array, std.stdio;
// Print sorted lines of a file.
void main()
{
    auto sortedLines = File("file.txt")   // Open for reading
                       .byLineCopy()      // Read persistent lines
                       .array()           // into an array
                       .sort();           // then sort them
    foreach (line; sortedLines)
        writeln(line);
}
@paramChar Character type for each line, defaulting to immutable char.@paramkeepTerminator Use Yes.keepTerminator`` to include the terminator at the end of each line.@paramterminator Line separator ('\n' by default). Use newline for portability (unless the file was opened in text mode).@seereadText
byLineCopy
.
string[] std.array.array!(std.stdio.File.ByLineCopy!(immutable(char), char))(std.stdio.File.ByLineCopy!(immutable(char), char) r) @system

Allocates an array and initializes it with copies of the elements of range r.

Narrow strings are handled as follows:

  • If autodecoding is turned on (default), then they are handled as a separate overload.

  • If autodecoding is turned off, then this is equivalent to duplicating the array.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
.
string std.array.join!(string[], string)(string[] ror, string sep) pure nothrow @safe

Eagerly concatenates all of the ranges in ror together (with the GC) into one array using sep as the separator if present.

@paramror An input range of input ranges@paramsep An input range, or a single element, to join the ranges on@returnsAn array of elements@seeFor a lazy version, see joiner
join
("\n");
return
int std.process.wait(std.process.Pid pid) @safe

Waits for the process associated with pid to terminate, and returns its exit status.

In general one should always wait for child processes to terminate before exiting the parent process unless the process was spawned as detached (that was spawned with Config.detached flag). Otherwise, they may become "zombies" – processes that are defunct, yet still occupy a slot in the OS process table. You should not and must not wait for detached processes, since you don't own them.

If the process has already terminated, this function returns directly. The exit code is cached, so that if wait() is called multiple times on the same Pid it will always return the same value.

POSIX specific

If the process is terminated by a signal, this function returns a negative number whose absolute value is the signal number. Since POSIX restricts normal exit codes to the range 0-255, a negative return value will always indicate termination by signal. Signal codes are defined in the core.sys.posix.signal module (which corresponds to the signal.h POSIX header).

Example

See the spawnProcess documentation.

@throwsProcessException on failure or on attempt to wait for detached process.@seetryWait, for a non-blocking function.
wait
(
(local variable) std.process.ProcessPipes p
p
.
std.process.Pid std.process.ProcessPipes.pid() nothrow @property @safe

The Pid of the child process.

pid
);
} int
int sanitizers_lsan_gc_interplay.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
;
(alias) sanitizers_lsan_gc_interplay.FatalCheckFn = extern (C) void function()
FatalCheckFn
(local variable) extern (C) void function() fatal
fatal
;
(alias) sanitizers_lsan_gc_interplay.RecoverableCheckFn = extern (C) int function()
RecoverableCheckFn
(local variable) extern (C) int function() recoverable
recoverable
;
if (!
bool sanitizers_lsan_gc_interplay.lsanLive(out extern (C) void function() fatal, out extern (C) int function() recoverable)

Runtime instrumentation detection: resolve the LSan entry points via dlsym so an uninstrumented binary still links (and SKIPs).

lsanLive
(
(local variable) extern (C) void function() fatal
fatal
,
(local variable) extern (C) int function() recoverable
recoverable
))
{
void std.stdio.writefln!char(in char[] fmt) @safe

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

writefln
("SKIP: no __lsan_* entry points in this binary "
~ "(built without -fsanitize=leak; e.g. a DMD build)"); return 0; } 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 sanitizers_lsan_gc_interplay.childEnvVar = "SANITIZERS_PROBE_CHILD"
childEnvVar
) == "leaks")
{
void sanitizers_lsan_gc_interplay.childDemo(extern (C) void function() fatal, extern (C) int function() recoverable)
childDemo
(
(local variable) extern (C) void function() fatal
fatal
,
(local variable) extern (C) int function() recoverable
recoverable
);
return 0; } void
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(bool
(parameter) bool cond
cond
,
(alias) object.string = string
string
(parameter) string what
what
,
(alias) object.string = string
string
(parameter) string output
output
)
{ if (!
(parameter) bool cond
cond
)
{
void std.stdio.writefln!(char, string, string)(in char[] fmt, string __param_1, string __param_2) @safe

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

writefln
("FAIL: %s\n--- child output ---\n%s",
(parameter) string what
what
,
(parameter) string output
output
);
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) exit = noreturn core.stdc.stdlib.exit(int status) nothrow @nogc
exit
;
noreturn core.stdc.stdlib.exit(int status) nothrow @nogc
exit
(1);
} } // Child A: default options — quadrants + manual checks.
(alias) object.string = string
string
(local variable) string outA
outA
;
const
(local variable) const(int) codeA
codeA
=
int sanitizers_lsan_gc_interplay.spawnChild(string[string] extraEnv, out string output)
spawnChild
([
(constant) string sanitizers_lsan_gc_interplay.childEnvVar = "SANITIZERS_PROBE_CHILD"
childEnvVar
: "leaks"],
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) const(int) codeA
codeA
== 23, "leaking child should exit 23 (standalone LSan)",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("LeakSanitizer: detected memory leaks"), "child A "
~ "should report leaks",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("recoverable returned 1"),
"__lsan_do_recoverable_leak_check should return 1 and not die",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("Direct leak of 1001 byte"),
"Q1: the unreachable malloc must be reported",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("Direct leak of 2002 byte"),
"Q2: the GC-referenced malloc is a (known) FALSE POSITIVE — " ~ "LSan cannot see D GC pools",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(!
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("4004 byte"),
"Q3: dropped GC allocations are invisible to LSan",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(!
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("5005 byte"),
"Q4: a malloc reachable from __gshared data must NOT be reported",
(local variable) string outA
outA
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(!
(local variable) string outA
outA
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("survived both manual checks"),
"__lsan_do_leak_check must be fatal when leaks were found",
(local variable) string outA
outA
);
// Child B: detect_leaks=0 — the manual entry points become no-ops.
(alias) object.string = string
string
(local variable) string outB
outB
;
const
(local variable) const(int) codeB
codeB
=
int sanitizers_lsan_gc_interplay.spawnChild(string[string] extraEnv, out string output)
spawnChild
(
[
(constant) string sanitizers_lsan_gc_interplay.childEnvVar = "SANITIZERS_PROBE_CHILD"
childEnvVar
: "leaks", "LSAN_OPTIONS": "detect_leaks=0"],
(local variable) string outB
outB
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) const(int) codeB
codeB
== 0, "child B should run to completion (exit 0)",
(local variable) string outB
outB
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(
(local variable) string outB
outB
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("recoverable returned 0")
&&
(local variable) string outB
outB
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("survived both manual checks"),
"detect_leaks=0 must disable the manual checks too",
(local variable) string outB
outB
);
void sanitizers_lsan_gc_interplay.run.check(bool cond, string what, string output) @system
check
(!
(local variable) string outB
outB
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

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

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("LeakSanitizer"),
"no report of any kind under detect_leaks=0",
(local variable) string outB
outB
);
void std.stdio.writefln!char(in char[] fmt) @safe

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

writefln
("PASS: LSan vs the D GC — true malloc leak reported, "
~ "GC-referenced malloc falsely reported (blind spot), GC leak " ~ "invisible, global-rooted malloc silent; exit 23; " ~ "detect_leaks=0 disables manual checks"); return 0; } } int
int D main()
main
()
{ version (
linux
linux
)
return
int sanitizers_lsan_gc_interplay.run()
run
();
else { import std.stdio : writefln; writefln("SKIP: this LSan probe is Linux-only"); return 0; } }