diff options
Diffstat (limited to 'libphobos/src')
-rw-r--r-- | libphobos/src/MERGE | 2 | ||||
-rw-r--r-- | libphobos/src/std/array.d | 10 | ||||
-rw-r--r-- | libphobos/src/std/datetime/date.d | 40 | ||||
-rw-r--r-- | libphobos/src/std/datetime/systime.d | 18 | ||||
-rw-r--r-- | libphobos/src/std/format/internal/read.d | 4 | ||||
-rw-r--r-- | libphobos/src/std/process.d | 149 | ||||
-rw-r--r-- | libphobos/src/std/uni/package.d | 2 |
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 |