Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

log4go block the caller when write to file failed #22

Open
FateTHarlaown opened this issue Apr 22, 2020 · 2 comments
Open

log4go block the caller when write to file failed #22

FateTHarlaown opened this issue Apr 22, 2020 · 2 comments

Comments

@FateTHarlaown
Copy link

our service uses log4go,we found it will block our program when it got a error because writing file failed. For example, when disk was full, we got an error "FileLogWriter("../log/syncer.log"): write ../log/syncer.log: no space left on device" in stderr and our code was blocked when it try to log. the stack like this

         1   runtime.gopark
             runtime.goparkunlock
             runtime.chansend
             runtime.chansend1
             github.com/jeanphorn/log4go.(*FileLogWriter).LogWrite
             github.com/jeanphorn/log4go.Logger.intLogf
             github.com/jeanphorn/log4go.Info
             teledb/pkg/syncer.(*Controller).coordinator
             teledb/pkg/syncer.(*Controller).Run
             main.main.func2

maybe that is because the background goroutine will return when it meet a error

go func() {
		defer func() {
			if w.file != nil {
				fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()}))
				w.file.Close()
			}
		}()

		for {
			select {
			case <-w.rot:
				if err := w.intRotate(); err != nil {
					fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err)
					return
				}
			case rec, ok := <-w.rec:
				if !ok {
					return
				}
				now := time.Now()
				if (w.maxlines > 0 && w.maxlines_curlines >= w.maxlines) ||
					(w.maxsize > 0 && w.maxsize_cursize >= w.maxsize) ||
					(w.daily && now.Day() != w.daily_opendate) {
					if err := w.intRotate(); err != nil {
						fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err)
						return
					}
				}

				// Sanitize newlines
				if w.sanitize {
					rec.Message = strings.Replace(rec.Message, "\n", "\\n", -1)
				}

				// Perform the write
				n, err := fmt.Fprint(w.file, FormatLogRecord(w.format, rec))
				if err != nil {
					fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err)
					return
				}

				// Update the counts
				w.maxlines_curlines++
				w.maxsize_cursize += n
			}
		}
	}()

and then the channel w.rec will soon be full, and block the writer

// This is the FileLogWriter's output method
func (w *FileLogWriter) LogWrite(rec *LogRecord) {
	w.rec <- rec
}

can we find a better way that will not make our service block ?

@amao5466
Copy link

I met the same trouble with you

1 similar comment
@jlulxy
Copy link

jlulxy commented Aug 25, 2022

I met the same trouble with you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants