@zigc/lib 0.16.0-dev.3059 → 0.16.0-dev.3066

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zigc/lib",
3
- "version": "0.16.0-dev.3059",
3
+ "version": "0.16.0-dev.3066",
4
4
  "description": "Zig standard library and libc headers (shared across all platforms)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -109,6 +109,10 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
109
109
  return config_header;
110
110
  }
111
111
 
112
+ pub fn addIdent(config_header: *ConfigHeader, name: []const u8, value: []const u8) void {
113
+ config_header.values.put(name, .{ .ident = value }) catch @panic("OOM");
114
+ }
115
+
112
116
  pub fn addValue(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) void {
113
117
  return addValueInner(config_header, name, T, value) catch @panic("OOM");
114
118
  }
@@ -13482,21 +13482,80 @@ fn netLookupFallible(
13482
13482
  const name = host_name.bytes;
13483
13483
  assert(name.len <= HostName.max_len);
13484
13484
 
13485
- if (is_windows) {
13486
- if (options.family == null) {
13487
- if (IpAddress.parseIp4(name, options.port)) |addr| {
13488
- if (copyCanon(options.canonical_name_buffer, name)) |canon| {
13489
- try resolved.putAll(t_io, &.{
13490
- .{ .address = addr },
13491
- .{ .canonical_name = canon },
13492
- });
13493
- } else {
13494
- try resolved.putOne(t_io, .{ .address = addr });
13495
- }
13496
- return;
13497
- } else |_| {}
13485
+ // On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.
13486
+ // However, musl's POSIX-compliant getaddrinfo is not, so we bypass it.
13487
+
13488
+ if (builtin.target.isGnuLibC()) {
13489
+ // TODO use getaddrinfo_a / gai_cancel
13490
+ }
13491
+
13492
+ if (native_os == .linux or is_windows) {
13493
+ if (IpAddress.parseIp6(name, options.port)) |addr| {
13494
+ if (options.family == .ip4) return error.UnknownHostName;
13495
+ if (copyCanon(options.canonical_name_buffer, name)) |canon| {
13496
+ try resolved.putAll(t_io, &.{
13497
+ .{ .address = addr },
13498
+ .{ .canonical_name = canon },
13499
+ });
13500
+ } else {
13501
+ try resolved.putOne(t_io, .{ .address = addr });
13502
+ }
13503
+ return;
13504
+ } else |_| {}
13505
+
13506
+ if (IpAddress.parseIp4(name, options.port)) |addr| {
13507
+ if (options.family == .ip6) return error.UnknownHostName;
13508
+ if (copyCanon(options.canonical_name_buffer, name)) |canon| {
13509
+ try resolved.putAll(t_io, &.{
13510
+ .{ .address = addr },
13511
+ .{ .canonical_name = canon },
13512
+ });
13513
+ } else {
13514
+ try resolved.putOne(t_io, .{ .address = addr });
13515
+ }
13516
+ return;
13517
+ } else |_| {}
13518
+
13519
+ if (t.lookupHosts(host_name, resolved, options)) return else |err| switch (err) {
13520
+ error.UnknownHostName => {},
13521
+ else => |e| return e,
13522
+ }
13523
+
13524
+ // RFC 6761 Section 6.3.3
13525
+ // Name resolution APIs and libraries SHOULD recognize
13526
+ // localhost names as special and SHOULD always return the IP
13527
+ // loopback address for address queries and negative responses
13528
+ // for all other query types.
13529
+
13530
+ // Check for equal to "localhost(.)" or ends in ".localhost(.)"
13531
+ const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost";
13532
+ if (std.mem.endsWith(u8, name, localhost) and
13533
+ (name.len == localhost.len or name[name.len - localhost.len] == '.'))
13534
+ {
13535
+ var results_buffer: [3]HostName.LookupResult = undefined;
13536
+ var results_index: usize = 0;
13537
+ if (options.family != .ip4) {
13538
+ results_buffer[results_index] = .{ .address = .{ .ip6 = .loopback(options.port) } };
13539
+ results_index += 1;
13540
+ }
13541
+ if (options.family != .ip6) {
13542
+ results_buffer[results_index] = .{ .address = .{ .ip4 = .loopback(options.port) } };
13543
+ results_index += 1;
13544
+ }
13545
+ if (options.canonical_name_buffer) |buf| {
13546
+ const canon_name = "localhost";
13547
+ const canon_name_dest = buf[0..canon_name.len];
13548
+ canon_name_dest.* = canon_name.*;
13549
+ results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } };
13550
+ results_index += 1;
13551
+ }
13552
+ try resolved.putAll(t_io, results_buffer[0..results_index]);
13553
+ return;
13498
13554
  }
13499
13555
 
13556
+ if (native_os == .linux) return t.lookupDnsSearch(host_name, resolved, options);
13557
+
13558
+ comptime assert(is_windows);
13500
13559
  var DnsQueryEx = t.dl.DnsQueryEx.load(.acquire);
13501
13560
  //var DnsCancelQuery = t.dl.DnsCancelQuery.load(.acquire);
13502
13561
  var DnsFree = t.dl.DnsFree.load(.acquire);
@@ -13540,6 +13599,7 @@ fn netLookupFallible(
13540
13599
  else => |status| return windows.unexpectedStatus(status),
13541
13600
  }
13542
13601
  }
13602
+ try Thread.checkCancel();
13543
13603
  const current_thread = Thread.current;
13544
13604
  var lookup_dns: LookupDnsWindows = .{
13545
13605
  .threaded = t,
@@ -13562,126 +13622,71 @@ fn netLookupFallible(
13562
13622
  }
13563
13623
  ] = 0;
13564
13624
  //var cancel_token: windows.DNS.QUERY.CANCEL = undefined;
13625
+ // Workaround various bugs by attempting a synchronous non-wire query first
13565
13626
  switch (DnsQueryEx.?(&.{
13566
13627
  .Version = 1,
13567
13628
  .QueryName = &host_name_w,
13568
13629
  .QueryType = if (options.family == .ip4) .A else .AAAA,
13569
13630
  .QueryOptions = .{
13631
+ .NO_WIRE_QUERY = true,
13632
+ .NO_HOSTS_FILE = true, // handled above
13570
13633
  .ADDRCONFIG = true,
13571
13634
  .DUAL_ADDR = options.family == null,
13572
- .MULTICAST_WAIT = true,
13573
13635
  },
13574
- .pQueryCompletionCallback = if (current_thread) |_| &LookupDnsWindows.completed else null,
13575
- }, &lookup_dns.results,
13576
- //&cancel_token,
13577
- null)) {
13636
+ }, &lookup_dns.results, null)) {
13637
+ .SUCCESS => try lookup_dns.completedFallible(),
13578
13638
  // We must wait for the APC routine.
13579
- .SUCCESS, .DNS_REQUEST_PENDING => |status| if (current_thread) |_| {
13580
- while (!@atomicLoad(bool, &lookup_dns.done, .acquire)) {
13581
- // Once we get here we must not return from the function until the
13582
- // operation completes, thereby releasing references to `host_name_w`,
13583
- // `lookup_dns.results`, and `cancel_token`.
13584
- const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) {
13585
- error.Canceled => |e| {
13586
- //_ = DnsCancelQuery.?(&cancel_token);
13587
- while (!@atomicLoad(bool, &lookup_dns.done, .acquire)) waitForApcOrAlert();
13588
- return e;
13589
- },
13590
- };
13591
- waitForApcOrAlert();
13592
- alertable_syscall.finish();
13593
- }
13594
- } else switch (status) {
13639
+ .DNS_REQUEST_PENDING => unreachable, // `pQueryCompletionCallback` was `null`
13640
+ .DNS_ERROR_RECORD_DOES_NOT_EXIST => switch (DnsQueryEx.?(&.{
13641
+ .Version = 1,
13642
+ .QueryName = &host_name_w,
13643
+ .QueryType = if (options.family == .ip4) .A else .AAAA,
13644
+ .QueryOptions = .{
13645
+ .NO_HOSTS_FILE = true, // handled above
13646
+ .ADDRCONFIG = true,
13647
+ .DUAL_ADDR = options.family == null,
13648
+ .MULTICAST_WAIT = true,
13649
+ },
13650
+ .pQueryCompletionCallback = if (current_thread) |_| &LookupDnsWindows.completed else null,
13651
+ }, &lookup_dns.results,
13652
+ //&cancel_token,
13653
+ null)) {
13595
13654
  .SUCCESS => try lookup_dns.completedFallible(),
13596
- .DNS_REQUEST_PENDING => unreachable, // `pQueryCompletionCallback` was `null`
13597
- else => unreachable,
13655
+ // We must wait for the APC routine.
13656
+ .DNS_REQUEST_PENDING => {
13657
+ assert(current_thread != null); // `pQueryCompletionCallback` was `null`
13658
+ while (!@atomicLoad(bool, &lookup_dns.done, .acquire)) {
13659
+ // Once we get here we must not return from the function until the
13660
+ // operation completes, thereby releasing references to `host_name_w`,
13661
+ // `lookup_dns.results`, and `cancel_token`.
13662
+ const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) {
13663
+ error.Canceled => |e| {
13664
+ //_ = DnsCancelQuery.?(&cancel_token);
13665
+ while (!@atomicLoad(bool, &lookup_dns.done, .acquire)) waitForApcOrAlert();
13666
+ return e;
13667
+ },
13668
+ };
13669
+ waitForApcOrAlert();
13670
+ alertable_syscall.finish();
13671
+ }
13672
+ },
13673
+ else => |status| lookup_dns.results.QueryStatus = status,
13598
13674
  },
13599
13675
  else => |status| lookup_dns.results.QueryStatus = status,
13600
13676
  }
13601
13677
  switch (lookup_dns.results.QueryStatus) {
13602
13678
  .SUCCESS => return,
13603
13679
  .DNS_REQUEST_PENDING => unreachable, // already handled
13604
- .INVALID_NAME, .DNS_INFO_NO_RECORDS => return error.UnknownHostName,
13680
+ .INVALID_NAME,
13681
+ .DNS_ERROR_RCODE_NAME_ERROR,
13682
+ .DNS_INFO_NO_RECORDS,
13683
+ .DNS_ERROR_INVALID_NAME_CHAR,
13684
+ .DNS_ERROR_RECORD_DOES_NOT_EXIST,
13685
+ => return error.UnknownHostName,
13605
13686
  else => |err| return windows.unexpectedError(err),
13606
13687
  }
13607
13688
  }
13608
13689
 
13609
- // On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.
13610
- // However, musl's POSIX-compliant getaddrinfo is not, so we bypass it.
13611
-
13612
- if (builtin.target.isGnuLibC()) {
13613
- // TODO use getaddrinfo_a / gai_cancel
13614
- }
13615
-
13616
- if (native_os == .linux) {
13617
- if (options.family != .ip4) {
13618
- if (IpAddress.parseIp6(name, options.port)) |addr| {
13619
- if (copyCanon(options.canonical_name_buffer, name)) |canon| {
13620
- try resolved.putAll(t_io, &.{
13621
- .{ .address = addr },
13622
- .{ .canonical_name = canon },
13623
- });
13624
- } else {
13625
- try resolved.putOne(t_io, .{ .address = addr });
13626
- }
13627
- return;
13628
- } else |_| {}
13629
- }
13630
-
13631
- if (options.family != .ip6) {
13632
- if (IpAddress.parseIp4(name, options.port)) |addr| {
13633
- if (copyCanon(options.canonical_name_buffer, name)) |canon| {
13634
- try resolved.putAll(t_io, &.{
13635
- .{ .address = addr },
13636
- .{ .canonical_name = canon },
13637
- });
13638
- } else {
13639
- try resolved.putOne(t_io, .{ .address = addr });
13640
- }
13641
- return;
13642
- } else |_| {}
13643
- }
13644
-
13645
- t.lookupHosts(host_name, resolved, options) catch |err| switch (err) {
13646
- error.UnknownHostName => {},
13647
- else => |e| return e,
13648
- };
13649
-
13650
- // RFC 6761 Section 6.3.3
13651
- // Name resolution APIs and libraries SHOULD recognize
13652
- // localhost names as special and SHOULD always return the IP
13653
- // loopback address for address queries and negative responses
13654
- // for all other query types.
13655
-
13656
- // Check for equal to "localhost(.)" or ends in ".localhost(.)"
13657
- const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost";
13658
- if (std.mem.endsWith(u8, name, localhost) and
13659
- (name.len == localhost.len or name[name.len - localhost.len] == '.'))
13660
- {
13661
- var results_buffer: [3]HostName.LookupResult = undefined;
13662
- var results_index: usize = 0;
13663
- if (options.family != .ip4) {
13664
- results_buffer[results_index] = .{ .address = .{ .ip6 = .loopback(options.port) } };
13665
- results_index += 1;
13666
- }
13667
- if (options.family != .ip6) {
13668
- results_buffer[results_index] = .{ .address = .{ .ip4 = .loopback(options.port) } };
13669
- results_index += 1;
13670
- }
13671
- if (options.canonical_name_buffer) |buf| {
13672
- const canon_name = "localhost";
13673
- const canon_name_dest = buf[0..canon_name.len];
13674
- canon_name_dest.* = canon_name.*;
13675
- results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } };
13676
- results_index += 1;
13677
- }
13678
- try resolved.putAll(t_io, results_buffer[0..results_index]);
13679
- return;
13680
- }
13681
-
13682
- return t.lookupDnsSearch(host_name, resolved, options);
13683
- }
13684
-
13685
13690
  if (native_os == .openbsd) {
13686
13691
  // TODO use getaddrinfo_async / asr_abort
13687
13692
  }
@@ -14510,8 +14515,32 @@ fn lookupHosts(
14510
14515
  resolved: *Io.Queue(HostName.LookupResult),
14511
14516
  options: HostName.LookupOptions,
14512
14517
  ) !void {
14513
- const t_io = io(t);
14514
- const file = Dir.openFileAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) {
14518
+ const path_w = if (is_windows) path_w: {
14519
+ var path_w_buf: [windows.PATH_MAX_WIDE:0]u16 = undefined;
14520
+ const system_dir = windows.getSystemDirectoryWtf16Le();
14521
+ const suffix = [_]u16{
14522
+ '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'e', 't', 'c', '\\', 'h', 'o', 's', 't', 's',
14523
+ };
14524
+ @memcpy(path_w_buf[0..system_dir.len], system_dir);
14525
+ @memcpy(path_w_buf[system_dir.len..][0..suffix.len], &suffix);
14526
+ path_w_buf[system_dir.len + suffix.len] = 0;
14527
+ break :path_w wToPrefixedFileW(null, &path_w_buf, .{}) catch |err| switch (err) {
14528
+ error.FileNotFound,
14529
+ error.AccessDenied,
14530
+ => return error.UnknownHostName,
14531
+
14532
+ error.Canceled => |e| return e,
14533
+
14534
+ else => {
14535
+ // Here we could add more detailed diagnostics to the results queue.
14536
+ return error.DetectingNetworkConfigurationFailed;
14537
+ },
14538
+ };
14539
+ };
14540
+ const file = (if (is_windows)
14541
+ dirOpenFileWtf16(null, path_w.span(), .{})
14542
+ else
14543
+ dirOpenFile(t, .cwd(), "/etc/hosts", .{})) catch |err| switch (err) {
14515
14544
  error.FileNotFound,
14516
14545
  error.NotDir,
14517
14546
  error.AccessDenied,
@@ -14524,10 +14553,10 @@ fn lookupHosts(
14524
14553
  return error.DetectingNetworkConfigurationFailed;
14525
14554
  },
14526
14555
  };
14527
- defer file.close(t_io);
14556
+ defer fileClose(t, &.{file});
14528
14557
 
14529
14558
  var line_buf: [512]u8 = undefined;
14530
- var file_reader = file.reader(t_io, &line_buf);
14559
+ var file_reader = file.reader(t.io(), &line_buf);
14531
14560
  return t.lookupHostsReader(host_name, resolved, options, &file_reader.interface) catch |err| switch (err) {
14532
14561
  error.ReadFailed => switch (file_reader.err.?) {
14533
14562
  error.Canceled => |e| return e,
@@ -14567,14 +14596,17 @@ fn lookupHostsReader(
14567
14596
  error.EndOfStream => break,
14568
14597
  };
14569
14598
  reader.toss(@min(1, reader.bufferedLen()));
14570
- var split_it = std.mem.splitScalar(u8, line, '#');
14599
+ var split_it = std.mem.splitScalar(u8, if (is_windows and std.mem.endsWith(u8, line, "\r"))
14600
+ line[0 .. line.len - 1]
14601
+ else
14602
+ line, '#');
14571
14603
  const no_comment_line = split_it.first();
14572
14604
 
14573
14605
  var line_it = std.mem.tokenizeAny(u8, no_comment_line, " \t");
14574
14606
  const ip_text = line_it.next() orelse continue;
14575
14607
  var first_name_text: ?[]const u8 = null;
14576
14608
  while (line_it.next()) |name_text| {
14577
- if (std.mem.eql(u8, name_text, host_name.bytes)) {
14609
+ if (std.ascii.eqlIgnoreCase(name_text, host_name.bytes)) {
14578
14610
  if (first_name_text == null) first_name_text = name_text;
14579
14611
  break;
14580
14612
  }
package/std/Thread.zig CHANGED
@@ -1147,6 +1147,11 @@ const LinuxThreadImpl = struct {
1147
1147
  /// Ported over from musl libc's pthread detached implementation:
1148
1148
  /// https://github.com/ifduyue/musl/search?q=__unmapself
1149
1149
  fn freeAndExit(self: *ThreadCompletion) noreturn {
1150
+ // If we do not reset the child_tidptr to null here, the kernel would later write the
1151
+ // value zero to that address, which is inside the block we're unmapping below, after
1152
+ // our thread exits. This can sometimes corrupt memory in other mmap blocks from
1153
+ // unrelated concurrent threads.
1154
+ _ = linux.set_tid_address(null);
1150
1155
  // If a signal were delivered between SYS_munmap and SYS_exit, any installed signal
1151
1156
  // handler would immediately segfault due to the stack being unmapped. To avoid this,
1152
1157
  // we need to mask all signals before entering the inline asm.
@@ -1484,7 +1489,7 @@ const LinuxThreadImpl = struct {
1484
1489
  }
1485
1490
 
1486
1491
  // Prepare the TLS segment and prepare a user_desc struct when needed on x86
1487
- var tls_ptr = linux.tls.prepareArea(mapped[tls_offset..]);
1492
+ var tls_ptr = linux.tls.prepareArea(mapped[tls_offset..][0..linux.tls.area_desc.size]);
1488
1493
  var user_desc: if (target.cpu.arch == .x86) linux.user_desc else void = undefined;
1489
1494
  if (target.cpu.arch == .x86) {
1490
1495
  defer tls_ptr = @intFromPtr(&user_desc);
package/std/os/linux.zig CHANGED
@@ -1584,6 +1584,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
1584
1584
  return syscall2(.clone, flags, child_stack_ptr);
1585
1585
  }
1586
1586
 
1587
+ /// This call cannot fail, and the return value is the caller's thread id
1588
+ pub fn set_tid_address(tidptr: ?*pid_t) pid_t {
1589
+ return @intCast(@as(u32, @truncate(syscall1(.set_tid_address, @intFromPtr(tidptr)))));
1590
+ }
1591
+
1587
1592
  pub fn close(fd: fd_t) usize {
1588
1593
  return syscall1(.close, @as(usize, @bitCast(@as(isize, fd))));
1589
1594
  }