mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 17:05:38 +00:00
app/internal/log: add synchronized logger on Android
By default, the standard library log package outputs to stderr. However, stderr is redirected through a pipe to the Android logger, so recent writes may be not have been sent when os.Exit is called. The log.Fatal family of functions does just that: write to the log and call os.Exit. To ensure all messages are sent, register a synchronized logger at startup. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -19,13 +19,39 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 1024 is the truncation limit from android/log.h, plus a \n.
|
||||||
|
const logLineLimit = 1024
|
||||||
|
|
||||||
|
var logTag = C.CString("gio")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Android's logcat already includes timestamps.
|
// Android's logcat already includes timestamps.
|
||||||
log.SetFlags(log.Flags() &^ log.LstdFlags)
|
log.SetFlags(log.Flags() &^ log.LstdFlags)
|
||||||
|
log.SetOutput(new(androidLogWriter))
|
||||||
|
|
||||||
|
// Redirect stdout and stderr to the Android logger.
|
||||||
logFd(os.Stdout.Fd())
|
logFd(os.Stdout.Fd())
|
||||||
logFd(os.Stderr.Fd())
|
logFd(os.Stderr.Fd())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type androidLogWriter struct {
|
||||||
|
// buf has room for the maximum log line, plus a terminating '\0'.
|
||||||
|
buf [logLineLimit + 1]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *androidLogWriter) Write(data []byte) (int, error) {
|
||||||
|
// Truncate the buffer, leaving space for the '\0'.
|
||||||
|
if max := len(w.buf) - 1; len(data) > max {
|
||||||
|
data = data[:max]
|
||||||
|
}
|
||||||
|
buf := w.buf[:len(data)+1]
|
||||||
|
copy(buf, data)
|
||||||
|
// Terminating '\0'.
|
||||||
|
buf[len(data)] = 0
|
||||||
|
C.__android_log_write(C.ANDROID_LOG_INFO, logTag, (*C.char)(unsafe.Pointer(&buf[0])))
|
||||||
|
return len(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
func logFd(fd uintptr) {
|
func logFd(fd uintptr) {
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -35,10 +61,7 @@ func logFd(fd uintptr) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
tag := C.CString("gio")
|
lineBuf := bufio.NewReaderSize(r, logLineLimit)
|
||||||
defer C.free(unsafe.Pointer(tag))
|
|
||||||
// 1024 is the truncation limit from android/log.h, plus a \n.
|
|
||||||
lineBuf := bufio.NewReaderSize(r, 1024)
|
|
||||||
// The buffer to pass to C, including the terminating '\0'.
|
// The buffer to pass to C, including the terminating '\0'.
|
||||||
buf := make([]byte, lineBuf.Size()+1)
|
buf := make([]byte, lineBuf.Size()+1)
|
||||||
cbuf := (*C.char)(unsafe.Pointer(&buf[0]))
|
cbuf := (*C.char)(unsafe.Pointer(&buf[0]))
|
||||||
@@ -49,7 +72,7 @@ func logFd(fd uintptr) {
|
|||||||
}
|
}
|
||||||
copy(buf, line)
|
copy(buf, line)
|
||||||
buf[len(line)] = 0
|
buf[len(line)] = 0
|
||||||
C.__android_log_write(C.ANDROID_LOG_INFO, tag, cbuf)
|
C.__android_log_write(C.ANDROID_LOG_INFO, logTag, cbuf)
|
||||||
}
|
}
|
||||||
// The garbage collector doesn't know that w's fd was dup'ed.
|
// The garbage collector doesn't know that w's fd was dup'ed.
|
||||||
// Avoid finalizing w, and thereby avoid its finalizer closing its fd.
|
// Avoid finalizing w, and thereby avoid its finalizer closing its fd.
|
||||||
|
|||||||
Reference in New Issue
Block a user