@@ -820,6 +820,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
820
820
windowsDestroyPipe (g_hChildStd_ERR_Rd , g_hChildStd_ERR_Wr );
821
821
};
822
822
823
+ var prog_pipe_rd : ? windows.HANDLE = null ;
824
+ var prog_pipe_wr : ? windows.HANDLE = null ;
825
+ if (self .progress_node .index != .none ) {
826
+ try windowsMakeProgressPipe (& prog_pipe_rd , & prog_pipe_wr , & saAttr );
827
+ errdefer windowsDestroyPipe (prog_pipe_rd , prog_pipe_wr );
828
+ }
823
829
var siStartInfo = windows.STARTUPINFOW {
824
830
.cb = @sizeOf (windows .STARTUPINFOW ),
825
831
.hStdError = g_hChildStd_ERR_Wr ,
@@ -847,9 +853,19 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
847
853
defer if (cwd_w ) | cwd | self .allocator .free (cwd );
848
854
const cwd_w_ptr = if (cwd_w ) | cwd | cwd .ptr else null ;
849
855
850
- const maybe_envp_buf = if (self .env_map ) | env_map | try process .createWindowsEnvBlock (self .allocator , env_map ) else null ;
851
- defer if (maybe_envp_buf ) | envp_buf | self .allocator .free (envp_buf );
852
- const envp_ptr = if (maybe_envp_buf ) | envp_buf | envp_buf .ptr else null ;
856
+ const maybe_envp_buf = m : {
857
+ const prog_fd : ? usize = if (prog_pipe_wr ) | h | @intFromPtr (h ) else null ;
858
+ if (self .env_map ) | env_map | {
859
+ break :m try process .createWindowsEnvBlock (self .allocator , env_map , .{ .zig_progress_fd = prog_fd });
860
+ } else {
861
+ const env_map = try process .getEnvMap (self .allocator );
862
+ break :m try process .createWindowsEnvBlock (self .allocator , & env_map , .{ .zig_progress_fd = prog_fd });
863
+ }
864
+ };
865
+ // defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf);
866
+ // const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null;
867
+ defer self .allocator .free (maybe_envp_buf );
868
+ const envp_ptr = maybe_envp_buf .ptr ;
853
869
854
870
const app_name_wtf8 = self .argv [0 ];
855
871
const app_name_is_absolute = fs .path .isAbsolute (app_name_wtf8 );
@@ -998,6 +1014,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
998
1014
if (self .stdout_behavior == StdIo .Pipe ) {
999
1015
posix .close (g_hChildStd_OUT_Wr .? );
1000
1016
}
1017
+ if (prog_pipe_rd ) | fd | self .progress_node .setIpcFd (fd );
1001
1018
}
1002
1019
1003
1020
fn setUpChildIo (stdio : StdIo , pipe_fd : i32 , std_fileno : i32 , dev_null_fd : i32 ) ! void {
@@ -1394,6 +1411,70 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons
1394
1411
wr .* = write_handle ;
1395
1412
}
1396
1413
1414
+ fn windowsMakeProgressPipe (rd : * ? windows.HANDLE , wr : * ? windows.HANDLE , sattr : * const windows.SECURITY_ATTRIBUTES ) ! void {
1415
+ var tmp_bufw : [128 ]u16 = undefined ;
1416
+
1417
+ // NOTE: Only difference with windowsMakeAsyncPipe now is windows.PIPE_NOWAIT flag and
1418
+ // pipe name
1419
+
1420
+ // Anonymous pipes are built upon Named pipes.
1421
+ // https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
1422
+ // Asynchronous (overlapped) read and write operations are not supported by anonymous pipes.
1423
+ // https://docs.microsoft.com/en-us/windows/win32/ipc/anonymous-pipe-operations
1424
+ const pipe_path = blk : {
1425
+ var tmp_buf : [128 ]u8 = undefined ;
1426
+ // Forge a random path for the pipe.
1427
+ const pipe_path = std .fmt .bufPrintZ (
1428
+ & tmp_buf ,
1429
+ "\\\\ .\\ pipe\\ zig-progress-{d}-{d}" ,
1430
+ .{ windows .GetCurrentProcessId (), pipe_name_counter .fetchAdd (1 , .monotonic ) },
1431
+ ) catch unreachable ;
1432
+ const len = std .unicode .wtf8ToWtf16Le (& tmp_bufw , pipe_path ) catch unreachable ;
1433
+ tmp_bufw [len ] = 0 ;
1434
+ break :blk tmp_bufw [0.. len :0 ];
1435
+ };
1436
+
1437
+ // Create the read handle that can be used with overlapped IO ops.
1438
+ const read_handle = windows .kernel32 .CreateNamedPipeW (
1439
+ pipe_path .ptr ,
1440
+ windows .PIPE_ACCESS_INBOUND | windows .FILE_FLAG_OVERLAPPED ,
1441
+ windows .PIPE_TYPE_BYTE | windows .PIPE_NOWAIT ,
1442
+ 1 ,
1443
+ 4096 ,
1444
+ 4096 ,
1445
+ 0 ,
1446
+ sattr ,
1447
+ );
1448
+ if (read_handle == windows .INVALID_HANDLE_VALUE ) {
1449
+ switch (windows .GetLastError ()) {
1450
+ else = > | err | return windows .unexpectedError (err ),
1451
+ }
1452
+ }
1453
+ errdefer posix .close (read_handle );
1454
+
1455
+ var sattr_copy = sattr .* ;
1456
+ const write_handle = windows .kernel32 .CreateFileW (
1457
+ pipe_path .ptr ,
1458
+ windows .GENERIC_WRITE ,
1459
+ 0 ,
1460
+ & sattr_copy ,
1461
+ windows .OPEN_EXISTING ,
1462
+ windows .FILE_ATTRIBUTE_NORMAL ,
1463
+ null ,
1464
+ );
1465
+ if (write_handle == windows .INVALID_HANDLE_VALUE ) {
1466
+ switch (windows .GetLastError ()) {
1467
+ else = > | err | return windows .unexpectedError (err ),
1468
+ }
1469
+ }
1470
+ errdefer posix .close (write_handle );
1471
+
1472
+ try windows .SetHandleInformation (read_handle , windows .HANDLE_FLAG_INHERIT , 0 );
1473
+
1474
+ rd .* = read_handle ;
1475
+ wr .* = write_handle ;
1476
+ }
1477
+
1397
1478
var pipe_name_counter = std .atomic .Value (u32 ).init (1 );
1398
1479
1399
1480
/// File name extensions supported natively by `CreateProcess()` on Windows.
0 commit comments