Skip to content

Commit

Permalink
executor: fix TempDir permissions bug (pingcap#16823)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsqlu authored May 6, 2020
1 parent b95d857 commit b258ccd
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 15 deletions.
28 changes: 20 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io/ioutil"
"net/url"
"os"
"os/user"
"path/filepath"
"strings"
"sync/atomic"
Expand All @@ -48,8 +49,12 @@ const (
DefMaxOfMaxIndexLength = 3072 * 4
// DefPort is the default port of TiDB
DefPort = 4000
// DefStatusPort is the default status port of TiBD
// DefStatusPort is the default status port of TiDB
DefStatusPort = 10080
// DefHost is the default host of TiDB
DefHost = "0.0.0.0"
// DefStatusHost is the default status host of TiDB
DefStatusHost = "0.0.0.0"
// DefStoreLivenessTimeout is the default value for store liveness timeout.
DefStoreLivenessTimeout = "120s"
)
Expand All @@ -65,7 +70,7 @@ var (
// checkBeforeDropLDFlag is a go build flag.
checkBeforeDropLDFlag = "None"
// tempStorageDirName is the default temporary storage dir name by base64 encoding a string `port/statusPort`
tempStorageDirName = encodeDefTempStorageDir(DefPort, DefStatusPort)
tempStorageDirName = encodeDefTempStorageDir(DefHost, DefStatusHost, DefPort, DefStatusPort)
)

// Config contains configuration options.
Expand Down Expand Up @@ -139,13 +144,20 @@ type Config struct {
// and the `tmp-storage-path` was not specified in the conf.toml or was specified the same as the default value.
func (c *Config) UpdateTempStoragePath() {
if c.TempStoragePath == tempStorageDirName {
c.TempStoragePath = encodeDefTempStorageDir(c.Port, c.Status.StatusPort)
c.TempStoragePath = encodeDefTempStorageDir(c.Host, c.Status.StatusHost, c.Port, c.Status.StatusPort)
}
}

func encodeDefTempStorageDir(port, statusPort uint) string {
dirName := base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v/%v", port, statusPort)))
return filepath.Join(os.TempDir(), "tidb", dirName, "tmp-storage")
func encodeDefTempStorageDir(host, statusHost string, port, statusPort uint) string {
dirName := base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v:%v/%v:%v", host, port, statusHost, statusPort)))
var osUID string
currentUser, err := user.Current()
if err != nil {
osUID = ""
} else {
osUID = currentUser.Uid
}
return filepath.Join(os.TempDir(), osUID+"_tidb", dirName, "tmp-storage")
}

// nullableBool defaults unset bool options to unset instead of false, which enables us to know if the user has set 2
Expand Down Expand Up @@ -531,7 +543,7 @@ type Experimental struct {
}

var defaultConf = Config{
Host: "0.0.0.0",
Host: DefHost,
AdvertiseAddress: "",
Port: DefPort,
Cors: "",
Expand Down Expand Up @@ -581,7 +593,7 @@ var defaultConf = Config{
},
Status: Status{
ReportStatus: true,
StatusHost: "0.0.0.0",
StatusHost: DefStatusHost,
StatusPort: DefStatusPort,
MetricsInterval: 15,
RecordQPSbyDB: false,
Expand Down
4 changes: 2 additions & 2 deletions config/config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ mem-quota-query = 1073741824
oom-use-tmp-storage = true

# Specifies the temporary storage path for some operators when a single SQL statement exceeds the memory quota specified by mem-quota-query.
# It defaults to a generated directory in `<TMPDIR>/tidb/` if it is unset.
# It defaults to a generated directory in `<TMPDIR>/<os/user.Current().Uid>_tidb/` if it is unset.
# It only takes effect when `oom-use-tmp-storage` is `true`.
# tmp-storage-path = "/tmp/tidb/NDAwMC8xMDA4MA==/tmp-storage"
# tmp-storage-path = "/tmp/<os/user.Current().Uid>_tidb/MC4wLjAuMDo0MDAwLzAuMC4wLjA6MTAwODA=/tmp-storage"

# Specifies the maximum use of temporary storage (bytes) for all active queries when `oom-use-tmp-storage` is enabled.
# If the `tmp-storage-quota` exceeds the capacity of the temporary storage directory, tidb-server would return an error and exit.
Expand Down
30 changes: 30 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package config
import (
"encoding/json"
"os"
"os/user"
"path/filepath"
"runtime"
"testing"
Expand Down Expand Up @@ -439,3 +440,32 @@ func (s *testConfigSuite) TestParsePath(c *C) {
c.Assert(err, IsNil)
c.Assert(disableGC, IsTrue)
}

func (s *testConfigSuite) TestEncodeDefTempStorageDir(c *C) {

tests := []struct {
host string
statusHost string
port uint
statusPort uint
expect string
}{
{"0.0.0.0", "0.0.0.0", 4000, 10080, "MC4wLjAuMDo0MDAwLzAuMC4wLjA6MTAwODA="},
{"127.0.0.1", "127.16.5.1", 4000, 10080, "MTI3LjAuMC4xOjQwMDAvMTI3LjE2LjUuMToxMDA4MA=="},
{"127.0.0.1", "127.16.5.1", 4000, 15532, "MTI3LjAuMC4xOjQwMDAvMTI3LjE2LjUuMToxNTUzMg=="},
}

var osUID string
currentUser, err := user.Current()
if err != nil {
osUID = ""
} else {
osUID = currentUser.Uid
}

dirPrefix := filepath.Join(os.TempDir(), osUID+"_tidb")
for _, test := range tests {
tempStorageDir := encodeDefTempStorageDir(test.host, test.statusHost, test.port, test.statusPort)
c.Assert(tempStorageDir, Equals, filepath.Join(dirPrefix, test.expect, "tmp-storage"))
}
}
6 changes: 3 additions & 3 deletions tidb-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ func initializeTempDir() {
if err != nil {
switch err {
case fslock.ErrLockHeld:
fmt.Fprintf(os.Stderr, "The current temporary storage dir(%s) has been occupied by another instance, "+
"check tmp-storage-path config and make sure they are different.", tempDir)
log.Error("The current temporary storage dir has been occupied by another instance, "+
"check tmp-storage-path config and make sure they are different.", zap.String("TempStoragePath", tempDir), zap.Error(err))
default:
fmt.Fprintf(os.Stderr, "Failed to acquire exclusive lock on the temporary storage dir(%s). Error detail: {%s}", tempDir, err)
log.Error("Failed to acquire exclusive lock on the temporary storage dir.", zap.String("TempStoragePath", tempDir), zap.Error(err))
}
os.Exit(1)
}
Expand Down
3 changes: 2 additions & 1 deletion util/chunk/chunk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package chunk
import (
"bytes"
"fmt"
"io/ioutil"
"math"
"os"
"strconv"
Expand All @@ -37,7 +38,7 @@ import (
func TestT(t *testing.T) {
cfg := config.GetGlobalConfig()
conf := *cfg
conf.TempStoragePath = "/tmp/tidb/test-temp-storage"
conf.TempStoragePath, _ = ioutil.TempDir("", "oom-use-tmp-storage")
config.StoreGlobalConfig(&conf)
_ = os.RemoveAll(conf.TempStoragePath) // clean the uncleared temp file during the last run.
_ = os.MkdirAll(conf.TempStoragePath, 0755)
Expand Down
3 changes: 2 additions & 1 deletion util/chunk/disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"fmt"
"math/rand"
"os"
"path/filepath"
"strings"
"testing"

Expand Down Expand Up @@ -72,7 +73,7 @@ func (s *testChunkSuite) TestListInDisk(c *check.C) {
err := l.Add(chk)
c.Check(err, check.IsNil)
}
c.Assert(strings.HasPrefix(l.disk.Name(), "/tmp/tidb/test-temp-storage"), check.Equals, true)
c.Assert(strings.HasPrefix(l.disk.Name(), filepath.Join(os.TempDir(), "oom-use-tmp-storage")), check.Equals, true)
c.Check(l.NumChunks(), check.Equals, numChk)
c.Check(l.GetDiskTracker().BytesConsumed() > 0, check.IsTrue)

Expand Down

0 comments on commit b258ccd

Please sign in to comment.