diff --git a/src/control/cmd/ddb/main.go b/src/control/cmd/ddb/main.go index 8ee3d94f0d4..3eb81700d5f 100644 --- a/src/control/cmd/ddb/main.go +++ b/src/control/cmd/ddb/main.go @@ -1,5 +1,6 @@ // // (C) Copyright 2022-2024 Intel Corporation. +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -8,6 +9,7 @@ package main import ( "bufio" + "fmt" "os" "path" "path/filepath" @@ -242,6 +244,13 @@ Example Paths: func main() { var opts cliOptions + + // Must be called before any write to stdout. + if err := logging.DisableCStdoutBuffering(); err != nil { + fmt.Fprintf(os.Stderr, "Error disabling stdout buffering: %v\n", err) + os.Exit(1) + } + log := logging.NewCommandLineLogger() if err := parseOpts(os.Args[1:], &opts, log); err != nil { diff --git a/src/control/logging/cstdio.go b/src/control/logging/cstdio.go new file mode 100644 index 00000000000..9cabdadaaa5 --- /dev/null +++ b/src/control/logging/cstdio.go @@ -0,0 +1,39 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package logging + +/* + #include +*/ +import "C" +import "github.com/pkg/errors" + +// DisableCStdoutBuffering disables C code write to stdout buffering and must be called before any write to stdout. +// +// When a Go program's stdout is connected to a pipe (e.g. redirected or piped to another +// process), C stdout becomes fully-buffered by Unix convention instead of line-buffered, +// which can cause output from C functions such as printf() to be lost or delayed. +// Disabling buffering ensures that C stdout output is flushed immediately, consistent +// with the behavior of Go's own stdout. +// +// References: +// - https://stackoverflow.com/questions/42634640/using-cgo-why-does-c-output-not-survive-piping-when-golangs-does +// - https://stackoverflow.com/questions/1716296/why-does-printf-not-flush-after-the-call-unless-a-newline-is-in-the-format-strin +// - https://stackoverflow.com/questions/3723795/is-stdout-line-buffered-unbuffered-or-indeterminate-by-default +// - https://groups.google.com/g/comp.lang.c/c/dvRKt-iuO40# +func DisableCStdoutBuffering() error { + rc, err := C.setvbuf(C.stdout, nil, C._IONBF, 0) + if rc == 0 { + return nil + } + + if err != nil { + return errors.Wrap(err, "failed to disable C stdout buffering") + } + + return errors.Errorf("failed to disable C stdout buffering: rc=%d", int(rc)) +}