Can't fetch package on Windows
Zig Version
0.16.0-dev.1216+846854972
Steps to Reproduce and Observed Behavior
$ zig-out/bin/zig.exe fetch "git+https://github.com/Vexu/arocc"
error: unable to discover remote git server capabilities: TlsInitializationFailed
A release build just exits with code 1 (or segfaults according to git bash).
Found in https://github.com/ziglang/translate-c/pull/204
Expected Behavior
Download package.
Seems suspiciously similar to https://github.com/ziglang/zig/issues/24911 which was fixed by https://github.com/ziglang/zig/pull/24915
Maybe those changes were accidentally reverted during the std.Io introduction?
After applying this patch:
diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig
index 83d8aa7e5e..32f7041026 100644
--- a/src/Package/Fetch.zig
+++ b/src/Package/Fetch.zig
@@ -1052,6 +1052,9 @@
var transport_uri = uri;
transport_uri.scheme = uri.scheme["git+".len..];
var session = git.Session.init(arena, http_client, transport_uri, reader_buffer) catch |err| {
+ if (@errorReturnTrace()) |trace| {
+ std.debug.dumpStackTrace(trace);
+ }
return f.fail(
f.location_tok,
try eb.printString("unable to discover remote git server capabilities: {t}", .{err}),
I got this stack trace:
~\Documents\code\zig> ~/Downloads/zig-x86_64-windows-0.16.0-dev.1225+bf9082518/zig-x86_64-windows-0.16.0-dev.1225+bf9082518/zig.exe build --zig-lib-dir lib\
~\Documents\code\zig> zig-out\bin\zig.exe fetch "git+https://github.com/Vexu/arocc"
C:\Users\leroy\Documents\code\zig\lib\std\Io\Threaded.zig:2411:33: 0x7ff619f29a49 in dirOpenDirWindows (zig_zcu.obj)
.OBJECT_NAME_INVALID => return error.BadPathName,
^
C:\Users\leroy\Documents\code\zig\lib\std\Io\Threaded.zig:2274:9: 0x7ff619f07a5a in dirOpenDirPosix (zig_zcu.obj)
return dirOpenDirWindows(t, dir, sub_path_w.span(), options);
^
C:\Users\leroy\Documents\code\zig\lib\std\Io\Dir.zig:108:5: 0x7ff61a0bb2f0 in openDir (zig_zcu.obj)
return io.vtable.dirOpenDir(io.userdata, dir, sub_path, options);
^
C:\Users\leroy\Documents\code\zig\lib\std\fs\Dir.zig:1074:29: 0x7ff61a057199 in openDir (zig_zcu.obj)
return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
^
C:\Users\leroy\Documents\code\zig\lib\std\crypto\Certificate.zig:263:13: 0x7ff61afb2c8b in verify (zig_zcu.obj)
return error.CertificateExpired;
^
C:\Users\leroy\Documents\code\zig\lib\std\crypto\tls\Client.zig:644:33: 0x7ff61ab36162 in init (zig_zcu.obj)
try prev_cert.verify(subject, now_sec);
^
C:\Users\leroy\Documents\code\zig\lib\std\http\Client.zig:357:33: 0x7ff61aa9ca83 in create (zig_zcu.obj)
else => |e| return e,
^
C:\Users\leroy\Documents\code\zig\lib\std\http\Client.zig:1457:25: 0x7ff61a77fdb9 in connectTcpOptions (zig_zcu.obj)
else => return error.TlsInitializationFailed,
^
C:\Users\leroy\Documents\code\zig\lib\std\http\Client.zig:1419:5: 0x7ff61a77ff7f in connectTcp (zig_zcu.obj)
return connectTcpOptions(client, .{ .host = host, .port = port, .protocol = protocol });
^
C:\Users\leroy\Documents\code\zig\lib\std\http\Client.zig:1592:14: 0x7ff61a44b19b in connect (zig_zcu.obj)
} orelse return client.connectTcp(host, port, protocol);
^
C:\Users\leroy\Documents\code\zig\lib\std\http\Client.zig:1708:18: 0x7ff61a25c2a1 in request (zig_zcu.obj)
break :c try client.connect(host_name, uriPort(uri, protocol), protocol);
^
C:\Users\leroy\Documents\code\zig\src\Package\Fetch\git.zig:757:24: 0x7ff61a25acbd in getCapabilities (zig_zcu.obj)
.request = try session.transport.request(.GET, info_refs_uri, .{
^
C:\Users\leroy\Documents\code\zig\src\Package\Fetch\git.zig:683:9: 0x7ff61a25d53f in init (zig_zcu.obj)
try session.getCapabilities(&capability_iterator, response_buffer);
^
error: unable to discover remote git server capabilities: TlsInitializationFailed
~\Documents\code\zig>
A release build just exits with code 1
I noticed this behaviour too, on a windows vm/CI or my own machine. This was on trying to fetch a zip file lazily.
Here's a standalone reproduction without the package manager (adapted from #24911):
const std = @import("std");
pub fn main() !void {
var debug_allocator: std.heap.DebugAllocator(.{}) = .{};
defer std.debug.assert(debug_allocator.deinit() == .ok);
const gpa = debug_allocator.allocator();
var threaded: std.Io.Threaded = .init(gpa);
defer threaded.deinit();
const io = threaded.io();
var client: std.http.Client = .{ .io = io, .allocator = gpa };
defer client.deinit();
var body: std.Io.Writer.Allocating = .init(gpa);
defer body.deinit();
const res = try client.fetch(.{
.location = .{ .url = "https://www.ryanliptak.com/misc/notin.html" },
.method = .GET,
.response_writer = &body.writer,
});
std.debug.print("{}\n", .{res.status});
std.debug.print("{s}\n", .{body.written()});
}
error: TlsInitializationFailed
C:\Users\Ryan\Programming\Zig\zig\lib\std\crypto\Certificate.zig:263:13: 0x7ff61e3e952b in verify (httpclient_zcu.obj)
return error.CertificateExpired;
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\crypto\tls\Client.zig:644:33: 0x7ff61e3b68ba in init (httpclient_zcu.obj)
try prev_cert.verify(subject, now_sec);
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\http\Client.zig:357:33: 0x7ff61e31cfe3 in create (httpclient_zcu.obj)
else => |e| return e,
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\http\Client.zig:1457:25: 0x7ff61e30b6c9 in connectTcpOptions (httpclient_zcu.obj)
else => return error.TlsInitializationFailed,
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\http\Client.zig:1419:5: 0x7ff61e30b88f in connectTcp (httpclient_zcu.obj)
return connectTcpOptions(client, .{ .host = host, .port = port, .protocol = protocol });
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\http\Client.zig:1592:14: 0x7ff61e300d4b in connect (httpclient_zcu.obj)
} orelse return client.connectTcp(host, port, protocol);
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\http\Client.zig:1708:18: 0x7ff61e2f7fc7 in request (httpclient_zcu.obj)
break :c try client.connect(host_name, uriPort(uri, protocol), protocol);
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\http\Client.zig:1791:15: 0x7ff61e2ee5d5 in fetch (httpclient_zcu.obj)
var req = try request(client, method, uri, .{
^
C:\Users\Ryan\Programming\Zig\tmp\httpclient.zig:18:17: 0x7ff61e2edec2 in main (httpclient_zcu.obj)
const res = try client.fetch(.{
^
@squeek502 I don't have the time to make a PR right this moment but it seems to be as simple as the Windows now implementation not accounting for the Windows 1601-01-01 epoch.
https://github.com/ziglang/zig/blob/459f3b7edef14da7d9ec29a77329601469f08b36/lib/std/Io/Threaded.zig#L2864-L2868
Change this prong to
.real => {
// RtlGetSystemTimePrecise() has a granularity of 100 nanoseconds
// and uses the NTFS/Windows epoch, which is 1601-01-01.
const epoch_100_ns = std.time.epoch.windows * (std.time.ns_per_s / 100);
return .{ .nanoseconds = @as(i96, windows.ntdll.RtlGetSystemTimePrecise() + epoch_100_ns) * 100 };
},
and your repro works.
However, the docs for std.Io.Clock.read state
The epoch is implementation-defined. For example NTFS/Windows uses 1601-01-01.
which is problematic because there's no way to obtain information about which epoch any given Io implementation uses. Either .real needs to be redefined to be relative to the Unix epoch, Io.VTable needs to add a new function for returning the epoch, or a new clock like .real_unix needs to be added.