@@ -28,6 +28,7 @@ import (
2828 "os"
2929 "runtime"
3030 "runtime/debug"
31+ "sync/atomic"
3132 "time"
3233
3334 x "github.com/celzero/firestack/intra/backend"
@@ -103,6 +104,7 @@ func SetupConsole(console Console) {
103104
104105 logfd := <- logch
105106 crashfd := <- crashch
107+ crashpiped .Store (crashfd )
106108
107109 log .ConsoleReady (ctx )
108110
@@ -315,14 +317,15 @@ func Crash(afterMs int64) {
315317
316318// global references to keep go's finalizer from cleaning up the FDs
317319var crashReader , crashWriter , crashRWErr = os .Pipe ()
320+ var crashpiped atomic.Bool
318321
319322func pipeCrashOutput (c Console ) (ok bool ) {
320323 if crashRWErr != nil {
321324 log .E ("tun: err crash output pipe: %v" , crashRWErr )
322325 return false
323326 }
324- pipeBuffer64k (crashWriter )
325- pipeBuffer64k (crashReader )
327+ pipeBuffer256k (crashWriter )
328+ pipeBuffer256k (crashReader )
326329 // defer core.Close(crashReader) // close iff r is dup'd by client code
327330 defer core .Close (crashWriter ) // always close as w is dup'd by the runtime
328331 if setCrashFd (crashWriter ) && c .CrashFD (int (crashReader .Fd ())) {
@@ -336,27 +339,51 @@ func pipeCrashOutput(c Console) (ok bool) {
336339func setCrashFd (f * os.File ) (ok bool ) {
337340 // f is dup()ed by debug.SetCrashOutput before use
338341 err := debug .SetCrashOutput (f , debug.CrashOptions {})
339- logei (err )("tun: crash output file %s, err? %v" , f . Name ( ), err )
342+ logei (err )("tun: crash output file %s, err? %v" , fname ( f ), err )
340343 return err == nil
341344}
342345
343- func pipeBuffer64k (f * os.File ) bool {
344- const b64k = 64 * 1024
346+ // SetCrashOutput will set the crash output file to dup(fd), and return true if successful.
347+ // Disables crash output if fd is less than 3.
348+ func SetCrashOutput (fd int ) bool {
349+ p := crashpiped .Swap (false )
350+ ok := setCrashFd (nil )
351+ // defer core.Close(crashReader) if fd not owned by the client
352+ log .I ("tun: closing crash out... ok? %t; was piped? %t; new fd: %d" , ok , p , fd )
353+ if fd >= 2 {
354+ return setCrashFd (os .NewFile (uintptr (fd ), "ktcfd" ))
355+ }
356+ return false
357+ }
358+
359+ func pipeBuffer256k (f * os.File ) bool {
360+ if f == nil {
361+ return false
362+ }
363+ const b256k = 4 * 64 * 1024
345364 fd := f .Fd ()
365+ nom := f .Name ()
346366 // kernel may round this up to the nearest page size multiple?
347- x , err := unix .FcntlInt (fd , unix .F_SETPIPE_SZ , b64k )
367+ x , err := unix .FcntlInt (fd , unix .F_SETPIPE_SZ , b256k )
348368 if err != nil {
349- log .W ("tun: err set pipe(% d) size %d: %v" , fd , x , err )
369+ log .W ("tun: pipe: (%s % d) err set size %d: %v" , nom , fd , x , err )
350370 return false
351371 }
352372
353373 x , err = unix .FcntlInt (fd , unix .F_GETPIPE_SZ , 0 )
354374 if err != nil {
355- log .W ("tun: err get pipe(% d) size: %v" , fd , err )
375+ log .W ("tun: pipe: (%s % d) err get size: %v" , nom , fd , err )
356376 return false
357377 }
358378
359379 runtime .KeepAlive (f )
360- log .W ("tun: pipe(% d) buffer %s" , fd , core .FmtBytes (uint64 (x )))
380+ log .W ("tun: pipe: (%s % d) buffer %s" , nom , fd , core .FmtBytes (uint64 (x )))
361381 return true
362382}
383+
384+ func fname (f * os.File ) string {
385+ if f == nil {
386+ return "<nil file>"
387+ }
388+ return f .Name ()
389+ }
0 commit comments