Last active
March 30, 2025 09:57
-
-
Save DivineDominion/b577cef19218b4b00e4792a3eb45db3e to your computer and use it in GitHub Desktop.
Test writing to macOS pipes exceeding the pipe buffer size
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
while read line | |
do | |
echo "$line" | |
done < "${1:-/dev/stdin}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Pipe { | |
static func naive_stdin(string: String) throws -> Pipe { | |
let data = string.data(using: .utf8)! | |
let stdin = Pipe() | |
try stdin.fileHandleForWriting.write(contentsOf: data) | |
try stdin.fileHandleForWriting.close() | |
return stdin | |
} | |
static func stdin(string: String) throws -> Pipe { | |
let stdin = Pipe() | |
let data = string.data(using: .utf8)! | |
stdin.fileHandleForWriting.writeabilityHandler = { handle in | |
handle.write(data) | |
try! handle.close() | |
handle.writeabilityHandler = nil | |
} | |
return stdin | |
} | |
} | |
let pipeBufferSize = 64 * 1024 // 64KiB | |
let kilobytesToSend = 65 | |
let string = | |
(0 ..< kilobytesToSend).map { thousand in | |
let prefix = "\(thousand)k: " | |
let blockSize = 1024 - prefix.count - 1 /* newline */ | |
let block = (1 ... blockSize).map { _ in "x" }.joined() | |
return prefix + block | |
}.joined(separator: "\n") + "\n" | |
print(string.lengthOfBytes(using: .utf8), "vs", pipeBufferSize) | |
let process = Process() | |
// process.standardInput = try! Pipe.naive_stdin(string: string) // Hard limit at 64KiB | |
process.standardInput = try! Pipe.stdin(string: string) // Can take any input | |
process.executableURL = URL(fileURLWithPath: "/tmp/receive.sh") | |
try! process.run() | |
process.waitUntilExit() | |
print("Done") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I wonder how closing the file handle in the block, a throwing operation, is intended to be done.