Skip to content

Deadlock in version 1.9.3 and a full test for reproducing the issue #1448

@sillydong

Description

@sillydong

This is related to #1440

I got a simple test function to reproduce the scenario.

package playground_test

import (
	"fmt"
	"testing"
	"time"

	"github.com/sirupsen/logrus"
)

type XXX struct {
	X string `json:"x"`
}

func (x XXX) MarshalJSON() ([]byte, error) {
	fmt.Println("aaa")
	logrus.Info("second")
	return []byte(`{"x":"y"}`), nil
}

func TestLog(t *testing.T) {
	jsonFormatter := &logrus.JSONFormatter{TimestampFormat: time.RFC3339Nano}
	logrus.StandardLogger().SetFormatter(jsonFormatter)

	x := XXX{}

	logrus.WithFields(logrus.Fields{
		"a": "b",
		"c": x,
	}).Info("first")
}

This case is like when we want to log something, the fields contains a value which has its own function for marshaling, and in that marshal function, it logged again. It's like log in log.

From the test output, we can see aaa printed, and second will not be printed.
image
If we comment out line logging second, we can see both aaa and first in output
image

Internally, it is caused in the second time of calling log and it trying to acquire Logger.mu in Entry.log.
image
The lock is held by the first call, so here it will blocked.

Further more, it is caused by the change in write function
image
lock is moved from after format to before format. So when it's running the format function, logger is locked and that time when people want to log another content, it cannot get lock and do logging.

For a log lib, people may want to log anywhere they want. So such case is really a possible daily usage for people. We cannot stop people from call log function inside a log call. We cannot review every structure in log field to ensure it's marshaling function has no log call. So I think this worth be fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions