This repository has been archived by the owner on Oct 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathulimit.go
129 lines (107 loc) · 2.69 KB
/
ulimit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package ulimit
// from go-ipfs
import (
"errors"
"fmt"
"os"
"strconv"
"syscall"
logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("ulimit")
var (
supportsFDManagement = false
// getlimit returns the soft and hard limits of file descriptors counts
getLimit func() (uint64, uint64, error)
// set limit sets the soft and hard limits of file descriptors counts
setLimit func(uint64, uint64) error
)
// minimum file descriptor limit before we complain
const minFds = 2048
var ErrUnsupported = errors.New("unsupported")
func GetLimit() (uint64, uint64, error) {
if getLimit == nil {
return 0, 0, ErrUnsupported
}
return getLimit()
}
// userMaxFDs returns the value of LOTUS_FD_MAX
func userMaxFDs() uint64 {
// check if the LOTUS_FD_MAX is set up and if it does
// not have a valid fds number notify the user
val := os.Getenv("LOTUS_FD_MAX")
if val == "" {
val = os.Getenv("IPFS_FD_MAX")
}
if val != "" {
fds, err := strconv.ParseUint(val, 10, 64)
if err != nil {
log.Errorf("bad value for LOTUS_FD_MAX: %s", err)
return 0
}
return fds
}
return 0
}
// ManageFdLimit raise the current max file descriptor count
// of the process based on the LOTUS_FD_MAX value
func ManageFdLimit(defaultLimit uint64) (changed bool, newLimit uint64, err error) {
if !supportsFDManagement {
return false, 0, nil
}
targetLimit := defaultLimit
userLimit := userMaxFDs()
if userLimit > 0 {
targetLimit = userLimit
}
soft, hard, err := GetLimit()
if err != nil {
return false, 0, err
}
if targetLimit <= soft {
return false, 0, nil
}
// the soft limit is the value that the kernel enforces for the
// corresponding resource
// the hard limit acts as a ceiling for the soft limit
// an unprivileged process may only set it's soft limit to a
// alue in the range from 0 up to the hard limit
err = setLimit(targetLimit, targetLimit)
switch err {
case nil:
newLimit = targetLimit
case syscall.EPERM:
// lower limit if necessary.
if targetLimit > hard {
targetLimit = hard
}
// the process does not have permission so we should only
// set the soft value
err = setLimit(targetLimit, hard)
if err != nil {
err = fmt.Errorf("error setting ulimit wihout hard limit: %s", err)
break
}
newLimit = targetLimit
// Warn on lowered limit.
if newLimit < userLimit {
err = fmt.Errorf(
"failed to raise ulimit to LOTUS_FD_MAX (%d): set to %d",
userLimit,
newLimit,
)
break
}
if userLimit == 0 && newLimit < minFds {
err = fmt.Errorf(
"failed to raise ulimit to minimum %d: set to %d",
minFds,
newLimit,
)
break
}
default:
err = fmt.Errorf("error setting: ulimit: %s", err)
}
return newLimit > 0, newLimit, err
}