]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: send android stderr to /dev/log/main
authorDavid Crawshaw <crawshaw@golang.org>
Wed, 10 Dec 2014 14:29:24 +0000 (09:29 -0500)
committerDavid Crawshaw <crawshaw@golang.org>
Wed, 10 Dec 2014 22:06:13 +0000 (22:06 +0000)
I tried to submit this in Go 1.4 as cl/107540044 but tripped over the
changes for getting C off the G stack. This is a rewritten version that
avoids cgo and works directly with the underlying log device.

Change-Id: I14c227dbb4202690c2c67c5a613d6c6689a6662a
Reviewed-on: https://go-review.googlesource.com/1285
Reviewed-by: Keith Randall <khr@golang.org>
src/runtime/print1.go
src/runtime/print1_write.go [new file with mode: 0644]
src/runtime/print1_write_android.go [new file with mode: 0644]

index 3d812bd04422facaea45ab9a37d402b39362be1b..7bec5599b5ddc8a7485940080f1a47ff2b81e53b 100644 (file)
@@ -75,7 +75,7 @@ func gwrite(b []byte) {
        }
        gp := getg()
        if gp == nil || gp.writebuf == nil {
-               write(2, unsafe.Pointer(&b[0]), int32(len(b)))
+               writeErr(b)
                return
        }
 
diff --git a/src/runtime/print1_write.go b/src/runtime/print1_write.go
new file mode 100644 (file)
index 0000000..5fd7d65
--- /dev/null
@@ -0,0 +1,9 @@
+// +build !android
+
+package runtime
+
+import "unsafe"
+
+func writeErr(b []byte) {
+       write(2, unsafe.Pointer(&b[0]), int32(len(b)))
+}
diff --git a/src/runtime/print1_write_android.go b/src/runtime/print1_write_android.go
new file mode 100644 (file)
index 0000000..d086e84
--- /dev/null
@@ -0,0 +1,44 @@
+package runtime
+
+import "unsafe"
+
+var (
+       writeHeader = []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0}
+       writePath   = []byte("/dev/log/main\x00")
+       writeFD     uintptr
+       writeBuf    [1024]byte
+       writePos    int
+)
+
+func writeErr(b []byte) {
+       // Log format: "<priority 1 byte><tag n bytes>\x00<message m bytes>\x00"
+       // The entire log needs to be delivered in a single syscall (the NDK
+       // does this with writev). Each log is its own line, so we need to
+       // buffer writes until we see a newline.
+       if writeFD == 0 {
+               writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0))
+               if writeFD == 0 {
+                       // It is hard to do anything here. Write to stderr just
+                       // in case user has root on device and has run
+                       //      adb shell setprop log.redirect-stdio true
+                       msg := []byte("runtime: cannot open /dev/log/main\x00")
+                       write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+                       exit(2)
+               }
+               copy(writeBuf[:], writeHeader)
+       }
+       dst := writeBuf[len(writeHeader):]
+       for _, v := range b {
+               if v == 0 { // android logging won't print a zero byte
+                       v = '0'
+               }
+               dst[writePos] = v
+               writePos++
+               if v == '\n' || writePos == len(dst)-1 {
+                       dst[writePos] = 0
+                       write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(len(writeHeader)+writePos))
+                       memclrBytes(dst)
+                       writePos = 0
+               }
+       }
+}