aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos/src')
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/std/array.d10
-rw-r--r--libphobos/src/std/datetime/date.d40
-rw-r--r--libphobos/src/std/datetime/systime.d18
-rw-r--r--libphobos/src/std/format/internal/read.d4
-rw-r--r--libphobos/src/std/process.d149
-rw-r--r--libphobos/src/std/uni/package.d2
7 files changed, 146 insertions, 79 deletions
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 76975e0..4fac724 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-ebd24da8add9243c52e5cb346dcdf7acf3e6cbac
+48d581a1f509a7a302ea893e28939edb5b130622
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index 1ce4a64..27d2167 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -3586,11 +3586,14 @@ if (isDynamicArray!A)
return _data ? _data.capacity : 0;
}
+ /// Returns: The number of elements appended.
+ @property size_t length() const => _data ? _data.arr.length : 0;
+
/**
* Use opSlice() from now on.
* Returns: The managed array.
*/
- @property inout(T)[] data() inout @trusted
+ @property inout(T)[] data() inout
{
return this[];
}
@@ -3921,6 +3924,7 @@ if (isDynamicArray!A)
int[] a = [ 1, 2 ];
auto app2 = appender(a);
app2.put(3);
+ assert(app2.length == 3);
app2.put([ 4, 5, 6 ]);
assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
}
@@ -4134,6 +4138,9 @@ if (isDynamicArray!A)
return impl.capacity;
}
+ /// Returns: The number of elements appended.
+ @property size_t length() const => impl.length;
+
/* Use opSlice() instead.
* Returns: the managed array.
*/
@@ -4160,6 +4167,7 @@ unittest
assert(app2[] == [1, 2]);
assert(a == [1, 2]);
app2 ~= 3;
+ assert(app2.length == 3);
app2 ~= [4, 5, 6];
assert(app2[] == [1, 2, 3, 4, 5, 6]);
assert(a == [1, 2, 3, 4, 5, 6]);
diff --git a/libphobos/src/std/datetime/date.d b/libphobos/src/std/datetime/date.d
index 7526f2d..c757b1e 100644
--- a/libphobos/src/std/datetime/date.d
+++ b/libphobos/src/std/datetime/date.d
@@ -3161,10 +3161,10 @@ public:
auto str = strip(isoString);
- enforce(str.length >= 15, new DateTimeException(format("Invalid ISO String: %s", isoString)));
+ enforce!DateTimeException(str.length >= 15, format("Invalid format for DateTime.fromISOString %s", isoString));
auto t = str.byCodeUnit.countUntil('T');
- enforce(t != -1, new DateTimeException(format("Invalid ISO String: %s", isoString)));
+ enforce!DateTimeException(t != -1, format("Invalid format for DateTime.fromISOString: %s", isoString));
immutable date = Date.fromISOString(str[0 .. t]);
immutable tod = TimeOfDay.fromISOString(str[t+1 .. $]);
@@ -3262,10 +3262,11 @@ public:
auto str = strip(isoExtString);
- enforce(str.length >= 15, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
+ enforce!DateTimeException(str.length >= 15,
+ format("Invalid format for DateTime.fromISOExtString: %s", isoExtString));
auto t = str.byCodeUnit.countUntil('T');
- enforce(t != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
+ enforce!DateTimeException(t != -1, format("Invalid format for DateTime.fromISOExtString: %s", isoExtString));
immutable date = Date.fromISOExtString(str[0 .. t]);
immutable tod = TimeOfDay.fromISOExtString(str[t+1 .. $]);
@@ -3362,10 +3363,11 @@ public:
auto str = strip(simpleString);
- enforce(str.length >= 15, new DateTimeException(format("Invalid string format: %s", simpleString)));
+ enforce!DateTimeException(str.length >= 15,
+ format("Invalid format for DateTime.fromSimpleString: %s", simpleString));
auto t = str.byCodeUnit.countUntil(' ');
- enforce(t != -1, new DateTimeException(format("Invalid string format: %s", simpleString)));
+ enforce!DateTimeException(t != -1, format("Invalid format for DateTime.fromSimpleString: %s", simpleString));
immutable date = Date.fromSimpleString(str[0 .. t]);
immutable tod = TimeOfDay.fromISOExtString(str[t+1 .. $]);
@@ -7628,7 +7630,7 @@ public:
auto str = isoString.strip;
- enforce!DateTimeException(str.length >= 8, text("Invalid ISO String: ", isoString));
+ enforce!DateTimeException(str.length >= 8, text("Invalid format for Date.fromISOString: ", isoString));
int day, month, year;
auto yearStr = str[0 .. $ - 4];
@@ -7643,7 +7645,7 @@ public:
if (yearStr.length > 4)
{
enforce!DateTimeException(yearStr.startsWith('-', '+'),
- text("Invalid ISO String: ", isoString));
+ text("Invalid format for Date.fromISOString: ", isoString));
year = to!int(yearStr);
}
else
@@ -7653,7 +7655,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(text("Invalid ISO String: ", isoString));
+ throw new DateTimeException(text("Invalid format for Date.fromISOString: ", isoString));
}
return Date(year, month, day);
@@ -7774,13 +7776,13 @@ public:
ubyte month, day;
if (str.length < 10 || str[$-3] != '-' || str[$-6] != '-')
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for Date.fromISOExtString: %s", isoExtString));
auto yearStr = str[0 .. $-6];
auto signAtBegining = cast(bool) yearStr.startsWith('-', '+');
if ((yearStr.length > 4) != signAtBegining)
{
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for Date.fromISOExtString: %s", isoExtString));
}
try
@@ -7791,7 +7793,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for Date.fromISOExtString: %s", isoExtString));
}
return Date(year, month, day);
@@ -7910,7 +7912,7 @@ public:
auto str = strip(simpleString);
if (str.length < 11 || str[$-3] != '-' || str[$-7] != '-')
- throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
+ throw new DateTimeException(format!"Invalid format for Date.fromSimpleString: %s"(simpleString));
int year;
uint day;
@@ -7919,7 +7921,7 @@ public:
auto signAtBegining = cast(bool) yearStr.startsWith('-', '+');
if ((yearStr.length > 4) != signAtBegining)
{
- throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
+ throw new DateTimeException(format!"Invalid format for Date.fromSimpleString: %s"(simpleString));
}
try
@@ -7929,7 +7931,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
+ throw new DateTimeException(format!"Invalid format for Date.fromSimpleString: %s"(simpleString));
}
return Date(year, month, day);
@@ -9208,7 +9210,7 @@ public:
int hours, minutes, seconds;
auto str = strip(isoString);
- enforce!DateTimeException(str.length == 6, text("Invalid ISO String: ", isoString));
+ enforce!DateTimeException(str.length == 6, text("Invalid format for TimeOfDay.fromISOString: ", isoString));
try
{
@@ -9220,7 +9222,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(text("Invalid ISO String: ", isoString));
+ throw new DateTimeException(text("Invalid format for TimeOfDay.fromISOString: ", isoString));
}
return TimeOfDay(hours, minutes, seconds);
@@ -9333,7 +9335,7 @@ public:
int hours, minutes, seconds;
if (str.length != 8 || str[2] != ':' || str[5] != ':')
- throw new DateTimeException(text("Invalid ISO Extended String: ", isoExtString));
+ throw new DateTimeException(text("Invalid format for TimeOfDay.fromISOExtString: ", isoExtString));
try
{
@@ -9345,7 +9347,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(text("Invalid ISO Extended String: ", isoExtString));
+ throw new DateTimeException(text("Invalid format for TimeOfDay.fromISOExtString: ", isoExtString));
}
return TimeOfDay(hours, minutes, seconds);
diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d
index a1d8ef3..a2e52ae 100644
--- a/libphobos/src/std/datetime/systime.d
+++ b/libphobos/src/std/datetime/systime.d
@@ -8879,7 +8879,7 @@ public:
return retval;
}
catch (DateTimeException dte)
- throw new DateTimeException(format("Invalid ISO String: %s", isoString));
+ throw new DateTimeException(format("Invalid format for SysTime.fromISOString: %s", isoString));
}
///
@@ -9109,7 +9109,8 @@ public:
auto str = strip(isoExtString);
auto tIndex = str.indexOf('T');
- enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
+ enforce!DateTimeException(tIndex != -1,
+ format("Invalid format for SysTime.fromISOExtString: %s", isoExtString));
auto found = str[tIndex + 1 .. $].find('.', 'Z', '+', '-');
auto dateTimeStr = str[0 .. $ - found[0].length];
@@ -9157,7 +9158,7 @@ public:
return retval;
}
catch (DateTimeException dte)
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for SysTime.fromISOExtString: %s", isoExtString));
}
///
@@ -9359,7 +9360,8 @@ public:
auto str = strip(simpleString);
auto spaceIndex = str.indexOf(' ');
- enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
+ enforce!DateTimeException(spaceIndex != -1,
+ format("Invalid format for SysTime.fromSimpleString: %s", simpleString));
auto found = str[spaceIndex + 1 .. $].find('.', 'Z', '+', '-');
auto dateTimeStr = str[0 .. $ - found[0].length];
@@ -9407,7 +9409,7 @@ public:
return retval;
}
catch (DateTimeException dte)
- throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
+ throw new DateTimeException(format("Invalid format for SysTime.fromSimpleString: %s", simpleString));
}
///
@@ -11170,6 +11172,7 @@ if (isSomeString!S)
import std.algorithm.searching : all;
import std.ascii : isDigit;
import std.conv : to;
+ import std.format : format;
import std.string : representation;
if (isoString.empty)
@@ -11177,10 +11180,11 @@ if (isSomeString!S)
auto str = isoString.representation;
- enforce(str[0] == '.', new DateTimeException("Invalid ISO String"));
+ enforce!DateTimeException(str[0] == '.', format("Invalid format for fracSecsFromISOString: %s", isoString));
str.popFront();
- enforce(!str.empty && all!isDigit(str), new DateTimeException("Invalid ISO String"));
+ enforce!DateTimeException(!str.empty && all!isDigit(str),
+ format("Invalid format for fracSecsFromISOString: %s", isoString));
dchar[7] fullISOString = void;
foreach (i, ref dchar c; fullISOString)
diff --git a/libphobos/src/std/format/internal/read.d b/libphobos/src/std/format/internal/read.d
index 597898c..05d6adc 100644
--- a/libphobos/src/std/format/internal/read.d
+++ b/libphobos/src/std/format/internal/read.d
@@ -25,7 +25,6 @@ package(std.format):
void skipData(Range, Char)(ref Range input, scope const ref FormatSpec!Char spec)
{
import std.ascii : isDigit;
- import std.conv : text;
import std.range.primitives : empty, front, popFront;
switch (spec.spec)
@@ -38,8 +37,7 @@ void skipData(Range, Char)(ref Range input, scope const ref FormatSpec!Char spec
while (!input.empty && isDigit(input.front)) input.popFront();
break;
default:
- assert(false,
- text("Format specifier not understood: %", spec.spec));
+ assert(0, "Format specifier not understood: %" ~ spec.spec);
}
}
diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d
index d178374..41f788d 100644
--- a/libphobos/src/std/process.d
+++ b/libphobos/src/std/process.d
@@ -880,6 +880,7 @@ version (Posix) private enum InternalError : ubyte
doubleFork,
malloc,
preExec,
+ closefds_dup2,
}
/*
@@ -1008,7 +1009,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
if (config.flags & Config.Flags.detached)
close(pidPipe[0]);
close(forkPipe[0]);
- immutable forkPipeOut = forkPipe[1];
+ auto forkPipeOut = forkPipe[1];
immutable pidPipeOut = pidPipe[1];
// Set the working directory.
@@ -1042,56 +1043,106 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
if (!(config.flags & Config.Flags.inheritFDs))
{
- // NOTE: malloc() and getrlimit() are not on the POSIX async
- // signal safe functions list, but practically this should
- // not be a problem. Java VM and CPython also use malloc()
- // in its own implementation via opendir().
- import core.stdc.stdlib : malloc;
- import core.sys.posix.poll : pollfd, poll, POLLNVAL;
- import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;
-
- // Get the maximum number of file descriptors that could be open.
- rlimit r;
- if (getrlimit(RLIMIT_NOFILE, &r) != 0)
- {
- abortOnError(forkPipeOut, InternalError.getrlimit, .errno);
- }
- immutable maxDescriptors = cast(int) r.rlim_cur;
-
- // The above, less stdin, stdout, and stderr
- immutable maxToClose = maxDescriptors - 3;
+ version (FreeBSD)
+ import core.sys.freebsd.unistd : closefrom;
+ else version (OpenBSD)
+ import core.sys.openbsd.unistd : closefrom;
- // Call poll() to see which ones are actually open:
- auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
- if (pfds is null)
- {
- abortOnError(forkPipeOut, InternalError.malloc, .errno);
- }
- foreach (i; 0 .. maxToClose)
+ static if (!__traits(compiles, closefrom))
{
- pfds[i].fd = i + 3;
- pfds[i].events = 0;
- pfds[i].revents = 0;
- }
- if (poll(pfds, maxToClose, 0) >= 0)
- {
- foreach (i; 0 .. maxToClose)
- {
- // don't close pipe write end
- if (pfds[i].fd == forkPipeOut) continue;
- // POLLNVAL will be set if the file descriptor is invalid.
- if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
- }
- }
- else
- {
- // Fall back to closing everything.
- foreach (i; 3 .. maxDescriptors)
- {
- if (i == forkPipeOut) continue;
- close(i);
+ // FIXME: This implementation crashes the system when RLIMIT_NOFILE
+ // has a big value. For a possible solution see:
+ // https://github.com/dlang/phobos/pull/8990
+ void fallback (int lowfd) {
+ // NOTE: malloc() and getrlimit() are not on the POSIX async
+ // signal safe functions list, but practically this should
+ // not be a problem. Java VM and CPython also use malloc()
+ // in its own implementation via opendir().
+ import core.stdc.stdlib : malloc;
+ import core.sys.posix.poll : pollfd, poll, POLLNVAL;
+ import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;
+
+ // Get the maximum number of file descriptors that could be open.
+ rlimit r;
+ if (getrlimit(RLIMIT_NOFILE, &r) != 0)
+ {
+ abortOnError(forkPipeOut, InternalError.getrlimit, .errno);
+ }
+ immutable maxDescriptors = cast(int) r.rlim_cur;
+
+ immutable maxToClose = maxDescriptors - lowfd;
+
+ // Call poll() to see which ones are actually open:
+ auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
+ if (pfds is null)
+ {
+ abortOnError(forkPipeOut, InternalError.malloc, .errno);
+ }
+ foreach (i; 0 .. maxToClose)
+ {
+ pfds[i].fd = i + lowfd;
+ pfds[i].events = 0;
+ pfds[i].revents = 0;
+ }
+ if (poll(pfds, maxToClose, 0) >= 0)
+ {
+ foreach (i; 0 .. maxToClose)
+ {
+ // POLLNVAL will be set if the file descriptor is invalid.
+ if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
+ }
+ }
+ else
+ {
+ // Fall back to closing everything.
+ foreach (i; lowfd .. maxDescriptors)
+ {
+ close(i);
+ }
+ }
}
+
+ // closefrom may not be available on the version of glibc we build against.
+ // Until we find a way to perform this check we will try to use dlsym to
+ // check for the function. See: https://github.com/dlang/phobos/pull/9048
+ version (CRuntime_Glibc)
+ void closefrom (int lowfd) {
+ static bool tryGlibcClosefrom (int lowfd) {
+ import core.sys.posix.dlfcn : dlopen, dlclose, dlsym, dlerror, RTLD_LAZY;
+
+ void *handle = dlopen("libc.so.6", RTLD_LAZY);
+ if (!handle)
+ return false;
+ scope(exit) dlclose(handle);
+
+ // Clear errors
+ dlerror();
+ alias closefromT = extern(C) void function(int) @nogc @system nothrow;
+ auto closefrom = cast(closefromT) dlsym(handle, "closefrom");
+ if (dlerror())
+ return false;
+
+ closefrom(lowfd);
+ return true;
+ }
+
+ if (!tryGlibcClosefrom(lowfd))
+ fallback(lowfd);
+ }
+ else
+ alias closefrom = fallback;
}
+
+ // We need to close all open file descriptors excluding std{in,out,err}
+ // and forkPipeOut because we still need it.
+ // Since the various libc's provide us with `closefrom` move forkPipeOut
+ // to position 3, right after STDERR_FILENO, and close all FDs following that.
+ if (dup2(forkPipeOut, 3) == -1)
+ abortOnError(forkPipeOut, InternalError.closefds_dup2, .errno);
+ forkPipeOut = 3;
+ // forkPipeOut needs to be closed after we call `exec`.
+ setCLOEXEC(forkPipeOut, true);
+ closefrom(forkPipeOut + 1);
}
else // This is already done if we don't inherit descriptors.
{
@@ -1205,6 +1256,10 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
case InternalError.preExec:
errorMsg = "Failed to execute preExecFunction or preExecDelegate";
break;
+ case InternalError.closefds_dup2:
+ assert(!(config.flags & Config.Flags.inheritFDs));
+ errorMsg = "Failed to close inherited file descriptors";
+ break;
case InternalError.noerror:
assert(false);
}
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 632704b..b6d31a8 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -3349,7 +3349,7 @@ struct CowArray(SP=GcPolicy)
data[$-val.length-1 .. $-1] = val[];
}
- bool opEquals()(auto const ref CowArray rhs)const
+ bool opEquals()(auto ref const CowArray rhs) const
{
if (empty ^ rhs.empty)
return false; // one is empty and the other isn't