Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
1b96d4e179 Fix EPIPE error handling for process.stdout
When process.stdout encounters a broken pipe (EPIPE), it should emit an
error event so that applications can catch and handle it properly. This
fixes the Node.js compatibility test parallel/test-stdout-close-catch.js.

Changes:
- Modified PipeWriter.zig to propagate EPIPE errors when force_sync is
  enabled (indicating process stdio streams)
- For regular pipes, maintain existing behavior of treating EPIPE as
  completion to preserve compatibility
- Fixed error handling path in PipeWriter write function to properly
  return errors instead of ignoring them

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-22 02:50:17 +00:00
2 changed files with 37 additions and 3 deletions

View File

@@ -37,11 +37,11 @@ pub fn PosixPipeWriter(
return struct {
fn tryWrite(this: *This, force_sync: bool, buf_: []const u8) WriteResult {
return switch (if (!force_sync) getFileType(this) else .file) {
inline else => |ft| return tryWriteWithWriteFn(this, buf_, comptime writeToFileType(ft)),
inline else => |ft| return tryWriteWithWriteFn(this, buf_, force_sync, comptime writeToFileType(ft)),
};
}
fn tryWriteWithWriteFn(this: *This, buf: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult {
fn tryWriteWithWriteFn(this: *This, buf: []const u8, force_sync: bool, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult {
const fd = getFd(this);
var offset: usize = 0;
@@ -54,6 +54,13 @@ pub fn PosixPipeWriter(
}
if (err.getErrno() == .PIPE) {
// For process stdio (force_sync), emit EPIPE errors so they can be caught
// For regular pipes, treat as completion to maintain compatibility
if (force_sync) {
log("EPIPE error in force_sync mode - propagating error", .{});
return .{ .err = err };
}
log("EPIPE error in regular mode - converting to done", .{});
return .{ .done = offset };
}
@@ -651,7 +658,7 @@ pub fn PosixStreamingWriter(comptime Parent: type, comptime function_table: anyt
onWrite(this.parent, amt, .end_of_file);
return .{ .done = amt };
},
else => {},
else => |r| return r,
}
return rc;

View File

@@ -0,0 +1,27 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const child_process = require('child_process');
const fixtures = require('../common/fixtures');
const { getSystemErrorName } = require('util');
const testScript = fixtures.path('catch-stdout-error.js');
const child = child_process.exec(
...common.escapePOSIXShell`"${process.execPath}" "${testScript}" | "${process.execPath}" -pe "process.stdin.on('data' , () => process.exit(1))"`
);
let output = '';
child.stderr.on('data', function(c) {
output += c;
});
child.on('close', common.mustCall(function(code) {
output = JSON.parse(output);
assert.strictEqual(output.code, 'EPIPE');
assert.strictEqual(getSystemErrorName(output.errno), 'EPIPE');
assert.strictEqual(output.syscall, 'write');
console.log('ok');
}));