You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
in Go, pipes have a fixed buffer size. If the amount of data written to the pipe exceeds the buffer's capacity and there is no concurrent reader, the write operation will block until space becomes available in the buffer. This behavior can cause your program to hang if the buffer is full and the reading end (the other side of the pipe) is not actively reading the data.
This manifests as the k6 process hanging if you have somewhat large k6 javascript/typescript test files to be processed by xk6-ts loader.go file
To reproduce this simply, you can create a contrived k6 test file which is quite long (the contents of which are unimportant, I use an empty function here), simulating what it might be like in a larger codebase with multiple files and imports:
// helloworld.jsexportconstoptions={scenarios: {per_vu_scenario: {executor: "per-vu-iterations",vus: 10,iterations: 10,startTime: "10s",},},};functionnoop(){}exportdefaultfunction(){noop();noop();noop();// truncating for brevity, but repeat this function call 1500 times or so to make the file sufficiently long.// this must be explicit function calls, not a loop calling the function 1500 times.}
Build k6 with xk6-ts, and run this example:
xk6 build v0.50.0 --output "./k6" --with github.com/szkiba/xk6-ts@latest
./k6 run helloworld.js
And k6 will hang indefinitely.
To fix this, use concurrent Goroutines for reading and writing. Ensure that reading from and writing to the pipe happen concurrently. This approach prevents the buffer from filling up by continuously emptying it while writing. I propose a fix similar to this as a starting point, but I am not a golang expert, so was hoping @szkiba could assist
funcredirectStdin() {
ifos.Getenv("XK6_TS") =="false" {
return
}
isRun, scriptIndex:=isRunCommand(os.Args)
if!isRun {
return
}
filename:=os.Args[scriptIndex]
iffilename=="-" {
return
}
opts:=&k6pack.Options{
Filename: filename,
SourceMap: os.Getenv("XK6_TS_SOURCEMAP") !="false",
}
source, err:=os.ReadFile(filepath.Clean(filename))
iferr!=nil {
logrus.WithError(err).Fatal()
return
}
packStarted:=time.Now()
jsScript, err:=k6pack.Pack(string(source), opts)
iferr!=nil {
logrus.WithError(err).Fatal()
return
}
ifos.Getenv("XK6_TS_BENCHMARK") =="true" {
duration:=time.Since(packStarted)
logrus.WithField("extension", "xk6-ts").WithField("duration", duration).Info("Bundling completed in ", duration)
}
reader, writer, err:=os.Pipe()
iferr!=nil {
logrus.WithError(err).Fatal()
return
}
// Set up os.Stdin to be the reader before any writing happensoriginalStdin:=os.Stdinos.Stdin=reader// cleanup after function exitdeferfunc() {
os.Stdin=originalStdin// Ensure the writer and reader is closed when donewriter.Close()
reader.Close()
}()
// Write to the pipe in a goroutinegofunc() {
// Close writer after writing to signal EOFdeferwriter.Close()
_, writeErr:=writer.Write(jsScript)
ifwriteErr!=nil {
logrus.WithError(writeErr).Error("Failed to write JS script to pipe")
}
}()
}
The text was updated successfully, but these errors were encountered:
When using
in Go, pipes have a fixed buffer size. If the amount of data written to the pipe exceeds the buffer's capacity and there is no concurrent reader, the write operation will block until space becomes available in the buffer. This behavior can cause your program to hang if the buffer is full and the reading end (the other side of the pipe) is not actively reading the data.
This manifests as the k6 process hanging if you have somewhat large k6 javascript/typescript test files to be processed by xk6-ts
loader.go
fileTo reproduce this simply, you can create a contrived k6 test file which is quite long (the contents of which are unimportant, I use an empty function here), simulating what it might be like in a larger codebase with multiple files and imports:
Build k6 with xk6-ts, and run this example:
xk6 build v0.50.0 --output "./k6" --with github.com/szkiba/xk6-ts@latest ./k6 run helloworld.js
And k6 will hang indefinitely.
To fix this, use concurrent Goroutines for reading and writing. Ensure that reading from and writing to the pipe happen concurrently. This approach prevents the buffer from filling up by continuously emptying it while writing. I propose a fix similar to this as a starting point, but I am not a golang expert, so was hoping @szkiba could assist
The text was updated successfully, but these errors were encountered: