TUN-4356: Set AUTOMAXPROCS to the CPU limit when running in a Linux container
This commit is contained in:
parent
209091da39
commit
07af2a33b7
|
@ -10,6 +10,7 @@ import (
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
_ "go.uber.org/automaxprocs"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/access"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/access"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -43,6 +43,7 @@ require (
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/stretchr/testify v1.6.0
|
github.com/stretchr/testify v1.6.0
|
||||||
github.com/urfave/cli/v2 v2.2.0
|
github.com/urfave/cli/v2 v2.2.0
|
||||||
|
go.uber.org/automaxprocs v1.4.0
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -609,6 +609,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0=
|
||||||
|
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
coverage:
|
||||||
|
range: 80..100
|
||||||
|
round: down
|
||||||
|
precision: 2
|
||||||
|
|
||||||
|
status:
|
||||||
|
project: # measuring the overall project coverage
|
||||||
|
default: # context, you can create multiple ones with custom titles
|
||||||
|
enabled: yes # must be yes|true to enable this status
|
||||||
|
target: 90% # specify the target coverage for each commit status
|
||||||
|
# option: "auto" (must increase from parent commit or pull request base)
|
||||||
|
# option: "X%" a static target percentage to hit
|
||||||
|
if_not_found: success # if parent is not found report status as success, error, or failure
|
||||||
|
if_ci_failed: error # if ci fails report status as success, error, or failure
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
vendor
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
*.pprof
|
||||||
|
*.out
|
||||||
|
*.log
|
||||||
|
coverage.txt
|
||||||
|
|
||||||
|
/bin
|
||||||
|
cover.out
|
||||||
|
cover.html
|
|
@ -0,0 +1,24 @@
|
||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
go_import_path: go.uber.org/automaxprocs
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- GO111MODULE=on
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- go: oldstable
|
||||||
|
- go: stable
|
||||||
|
env: LINT=1
|
||||||
|
|
||||||
|
install:
|
||||||
|
- make install
|
||||||
|
|
||||||
|
script:
|
||||||
|
- test -z "$LINT" || make lint
|
||||||
|
- make test
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- make cover
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v1.4.0 (2021-02-01)
|
||||||
|
|
||||||
|
- Support colons in cgroup names.
|
||||||
|
- Remove linters from runtime dependencies.
|
||||||
|
|
||||||
|
## v1.3.0 (2020-01-23)
|
||||||
|
|
||||||
|
- Migrate to Go modules.
|
||||||
|
|
||||||
|
## v1.2.0 (2018-02-22)
|
||||||
|
|
||||||
|
- Fixed quota clamping to always round down rather than up; Rather than
|
||||||
|
guaranteeing constant throttling at saturation, instead assume that the
|
||||||
|
fractional CPU was added as a hedge for factors outside of Go's scheduler.
|
||||||
|
|
||||||
|
## v1.1.0 (2017-11-10)
|
||||||
|
|
||||||
|
- Log the new value of `GOMAXPROCS` rather than the current value.
|
||||||
|
- Make logs more explicit about whether `GOMAXPROCS` was modified or not.
|
||||||
|
- Allow customization of the minimum `GOMAXPROCS`, and modify default from 2 to 1.
|
||||||
|
|
||||||
|
## v1.0.0 (2017-08-09)
|
||||||
|
|
||||||
|
- Initial release.
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to making participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age,
|
||||||
|
body size, disability, ethnicity, gender identity and expression, level of
|
||||||
|
experience, nationality, personal appearance, race, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community. Examples of
|
||||||
|
representing a project or community include using an official project e-mail
|
||||||
|
address, posting via an official social media account, or acting as an
|
||||||
|
appointed representative at an online or offline event. Representation of a
|
||||||
|
project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at oss-conduct@uber.com. The project
|
||||||
|
team will review and investigate all complaints, and will respond in a way
|
||||||
|
that it deems appropriate to the circumstances. The project team is obligated
|
||||||
|
to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 1.4, available at
|
||||||
|
[http://contributor-covenant.org/version/1/4][version].
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
|
@ -0,0 +1,81 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
We'd love your help improving this package!
|
||||||
|
|
||||||
|
If you'd like to add new exported APIs, please [open an issue][open-issue]
|
||||||
|
describing your proposal — discussing API changes ahead of time makes
|
||||||
|
pull request review much smoother. In your issue, pull request, and any other
|
||||||
|
communications, please remember to treat your fellow contributors with
|
||||||
|
respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously.
|
||||||
|
|
||||||
|
Note that you'll need to sign [Uber's Contributor License Agreement][cla]
|
||||||
|
before we can accept any of your contributions. If necessary, a bot will remind
|
||||||
|
you to accept the CLA when you open your pull request.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
[Fork][fork], then clone the repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir -p $GOPATH/src/go.uber.org
|
||||||
|
cd $GOPATH/src/go.uber.org
|
||||||
|
git clone git@github.com:your_github_username/automaxprocs.git
|
||||||
|
cd automaxprocs
|
||||||
|
git remote add upstream https://github.com/uber-go/automaxprocs.git
|
||||||
|
git fetch upstream
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the test dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
make dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure that the tests and the linters pass:
|
||||||
|
|
||||||
|
```
|
||||||
|
make test
|
||||||
|
make lint
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're not using the minor version of Go specified in the Makefile's
|
||||||
|
`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is
|
||||||
|
fine, but it means that you'll only discover lint failures after you open your
|
||||||
|
pull request.
|
||||||
|
|
||||||
|
## Making Changes
|
||||||
|
|
||||||
|
Start by creating a new branch for your changes:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd $GOPATH/src/go.uber.org/automaxprocs
|
||||||
|
git checkout master
|
||||||
|
git fetch upstream
|
||||||
|
git rebase upstream/master
|
||||||
|
git checkout -b cool_new_feature
|
||||||
|
```
|
||||||
|
|
||||||
|
Make your changes, then ensure that `make lint` and `make test` still pass. If
|
||||||
|
you're satisfied with your changes, push them to your fork.
|
||||||
|
|
||||||
|
```
|
||||||
|
git push origin cool_new_feature
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use the GitHub UI to open a pull request.
|
||||||
|
|
||||||
|
At this point, you're waiting on us to review your changes. We *try* to respond
|
||||||
|
to issues and pull requests within a few business days, and we may suggest some
|
||||||
|
improvements or alternatives. Once your changes are approved, one of the
|
||||||
|
project maintainers will merge them.
|
||||||
|
|
||||||
|
We're much more likely to approve your changes if you:
|
||||||
|
|
||||||
|
* Add tests for new functionality.
|
||||||
|
* Write a [good commit message][commit-message].
|
||||||
|
* Maintain backward compatibility.
|
||||||
|
|
||||||
|
[fork]: https://github.com/uber-go/automaxprocs/fork
|
||||||
|
[open-issue]: https://github.com/uber-go/automaxprocs/issues/new
|
||||||
|
[cla]: https://cla-assistant.io/uber-go/automaxprocs
|
||||||
|
[commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,46 @@
|
||||||
|
export GOBIN ?= $(shell pwd)/bin
|
||||||
|
|
||||||
|
GO_FILES := $(shell \
|
||||||
|
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
|
||||||
|
-o -name '*.go' -print | cut -b3-)
|
||||||
|
|
||||||
|
GOLINT = $(GOBIN)/golint
|
||||||
|
STATICCHECK = $(GOBIN)/staticcheck
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
go build ./...
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install:
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -race ./...
|
||||||
|
|
||||||
|
.PHONY: cover
|
||||||
|
cover:
|
||||||
|
go test -coverprofile=cover.out -covermode=atomic -coverpkg=./... ./...
|
||||||
|
go tool cover -html=cover.out -o cover.html
|
||||||
|
|
||||||
|
$(GOLINT): tools/go.mod
|
||||||
|
cd tools && go install golang.org/x/lint/golint
|
||||||
|
|
||||||
|
$(STATICCHECK): tools/go.mod
|
||||||
|
cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: $(GOLINT) $(STATICCHECK)
|
||||||
|
@rm -rf lint.log
|
||||||
|
@echo "Checking gofmt"
|
||||||
|
@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
|
||||||
|
@echo "Checking go vet"
|
||||||
|
@go vet ./... 2>&1 | tee -a lint.log
|
||||||
|
@echo "Checking golint"
|
||||||
|
@$(GOLINT) ./... | tee -a lint.log
|
||||||
|
@echo "Checking staticcheck"
|
||||||
|
@$(STATICCHECK) ./... 2>&1 | tee -a lint.log
|
||||||
|
@echo "Checking for license headers..."
|
||||||
|
@./.build/check_license.sh | tee -a lint.log
|
||||||
|
@[ ! -s lint.log ]
|
|
@ -0,0 +1,46 @@
|
||||||
|
# automaxprocs [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
|
||||||
|
|
||||||
|
Automatically set `GOMAXPROCS` to match Linux container CPU quota.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
`go get -u go.uber.org/automaxprocs`
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```go
|
||||||
|
import _ "go.uber.org/automaxprocs"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Your application logic here.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Status: Stable
|
||||||
|
|
||||||
|
All APIs are finalized, and no breaking changes will be made in the 1.x series
|
||||||
|
of releases. Users of semver-aware dependency management systems should pin
|
||||||
|
automaxprocs to `^1`.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We encourage and support an active, healthy community of contributors —
|
||||||
|
including you! Details are in the [contribution guide](CONTRIBUTING.md) and
|
||||||
|
the [code of conduct](CODE_OF_CONDUCT.md). The automaxprocs maintainers keep
|
||||||
|
an eye on issues and pull requests, but you can also report any negative
|
||||||
|
conduct to oss-conduct@uber.com. That email list is a private, safe space;
|
||||||
|
even the automaxprocs maintainers don't have access, so don't hesitate to hold
|
||||||
|
us to a high standard.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
Released under the [MIT License](LICENSE).
|
||||||
|
|
||||||
|
[doc-img]: https://godoc.org/go.uber.org/automaxprocs?status.svg
|
||||||
|
[doc]: https://godoc.org/go.uber.org/automaxprocs
|
||||||
|
[ci-img]: https://travis-ci.com/uber-go/automaxprocs.svg?branch=master
|
||||||
|
[ci]: https://travis-ci.com/uber-go/automaxprocs
|
||||||
|
[cov-img]: https://codecov.io/gh/uber-go/automaxprocs/branch/master/graph/badge.svg
|
||||||
|
[cov]: https://codecov.io/gh/uber-go/automaxprocs
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// Package automaxprocs automatically sets GOMAXPROCS to match the Linux
|
||||||
|
// container CPU quota, if any.
|
||||||
|
package automaxprocs // import "go.uber.org/automaxprocs"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"go.uber.org/automaxprocs/maxprocs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
maxprocs.Set(maxprocs.Logger(log.Printf))
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package: go.uber.org/automaxprocs
|
||||||
|
import: []
|
||||||
|
testImport:
|
||||||
|
- package: github.com/stretchr/testify
|
||||||
|
version: ^1.1.4
|
||||||
|
subpackages:
|
||||||
|
- assert
|
|
@ -0,0 +1,9 @@
|
||||||
|
module go.uber.org/automaxprocs
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
|
)
|
|
@ -0,0 +1,18 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package cgroups
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CGroup represents the data structure for a Linux control group.
|
||||||
|
type CGroup struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCGroup returns a new *CGroup from a given path.
|
||||||
|
func NewCGroup(path string) *CGroup {
|
||||||
|
return &CGroup{path: path}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path returns the path of the CGroup*.
|
||||||
|
func (cg *CGroup) Path() string {
|
||||||
|
return cg.path
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamPath returns the path of the given cgroup param under itself.
|
||||||
|
func (cg *CGroup) ParamPath(param string) string {
|
||||||
|
return filepath.Join(cg.path, param)
|
||||||
|
}
|
||||||
|
|
||||||
|
// readFirstLine reads the first line from a cgroup param file.
|
||||||
|
func (cg *CGroup) readFirstLine(param string) (string, error) {
|
||||||
|
paramFile, err := os.Open(cg.ParamPath(param))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer paramFile.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(paramFile)
|
||||||
|
if scanner.Scan() {
|
||||||
|
return scanner.Text(), nil
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "", io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
|
||||||
|
// readInt parses the first line from a cgroup param file as int.
|
||||||
|
func (cg *CGroup) readInt(param string) (int, error) {
|
||||||
|
text, err := cg.readFirstLine(param)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return strconv.Atoi(text)
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package cgroups
|
||||||
|
|
||||||
|
const (
|
||||||
|
// _cgroupFSType is the Linux CGroup file system type used in
|
||||||
|
// `/proc/$PID/mountinfo`.
|
||||||
|
_cgroupFSType = "cgroup"
|
||||||
|
// _cgroupSubsysCPU is the CPU CGroup subsystem.
|
||||||
|
_cgroupSubsysCPU = "cpu"
|
||||||
|
// _cgroupSubsysCPUAcct is the CPU accounting CGroup subsystem.
|
||||||
|
_cgroupSubsysCPUAcct = "cpuacct"
|
||||||
|
// _cgroupSubsysCPUSet is the CPUSet CGroup subsystem.
|
||||||
|
_cgroupSubsysCPUSet = "cpuset"
|
||||||
|
// _cgroupSubsysMemory is the Memory CGroup subsystem.
|
||||||
|
_cgroupSubsysMemory = "memory"
|
||||||
|
|
||||||
|
// _cgroupCPUCFSQuotaUsParam is the file name for the CGroup CFS quota
|
||||||
|
// parameter.
|
||||||
|
_cgroupCPUCFSQuotaUsParam = "cpu.cfs_quota_us"
|
||||||
|
// _cgroupCPUCFSPeriodUsParam is the file name for the CGroup CFS period
|
||||||
|
// parameter.
|
||||||
|
_cgroupCPUCFSPeriodUsParam = "cpu.cfs_period_us"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_procPathCGroup = "/proc/self/cgroup"
|
||||||
|
_procPathMountInfo = "/proc/self/mountinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CGroups is a map that associates each CGroup with its subsystem name.
|
||||||
|
type CGroups map[string]*CGroup
|
||||||
|
|
||||||
|
// NewCGroups returns a new *CGroups from given `mountinfo` and `cgroup` files
|
||||||
|
// under for some process under `/proc` file system (see also proc(5) for more
|
||||||
|
// information).
|
||||||
|
func NewCGroups(procPathMountInfo, procPathCGroup string) (CGroups, error) {
|
||||||
|
cgroupSubsystems, err := parseCGroupSubsystems(procPathCGroup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroups := make(CGroups)
|
||||||
|
newMountPoint := func(mp *MountPoint) error {
|
||||||
|
if mp.FSType != _cgroupFSType {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range mp.SuperOptions {
|
||||||
|
subsys, exists := cgroupSubsystems[opt]
|
||||||
|
if !exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroupPath, err := mp.Translate(subsys.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cgroups[opt] = NewCGroup(cgroupPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := parseMountInfo(procPathMountInfo, newMountPoint); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cgroups, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCGroupsForCurrentProcess returns a new *CGroups instance for the current
|
||||||
|
// process.
|
||||||
|
func NewCGroupsForCurrentProcess() (CGroups, error) {
|
||||||
|
return NewCGroups(_procPathMountInfo, _procPathCGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPUQuota returns the CPU quota applied with the CPU cgroup controller.
|
||||||
|
// It is a result of `cpu.cfs_quota_us / cpu.cfs_period_us`. If the value of
|
||||||
|
// `cpu.cfs_quota_us` was not set (-1), the method returns `(-1, nil)`.
|
||||||
|
func (cg CGroups) CPUQuota() (float64, bool, error) {
|
||||||
|
cpuCGroup, exists := cg[_cgroupSubsysCPU]
|
||||||
|
if !exists {
|
||||||
|
return -1, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cfsQuotaUs, err := cpuCGroup.readInt(_cgroupCPUCFSQuotaUsParam)
|
||||||
|
if defined := cfsQuotaUs > 0; err != nil || !defined {
|
||||||
|
return -1, defined, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfsPeriodUs, err := cpuCGroup.readInt(_cgroupCPUCFSPeriodUsParam)
|
||||||
|
if err != nil {
|
||||||
|
return -1, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return float64(cfsQuotaUs) / float64(cfsPeriodUs), true, nil
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// Package cgroups provides utilities to access Linux control group (CGroups)
|
||||||
|
// parameters (CPU quota, for example) for a given process.
|
||||||
|
package cgroups
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package cgroups
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type cgroupSubsysFormatInvalidError struct {
|
||||||
|
line string
|
||||||
|
}
|
||||||
|
|
||||||
|
type mountPointFormatInvalidError struct {
|
||||||
|
line string
|
||||||
|
}
|
||||||
|
|
||||||
|
type pathNotExposedFromMountPointError struct {
|
||||||
|
mountPoint string
|
||||||
|
root string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err cgroupSubsysFormatInvalidError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid format for CGroupSubsys: %q", err.line)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err mountPointFormatInvalidError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid format for MountPoint: %q", err.line)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err pathNotExposedFromMountPointError) Error() string {
|
||||||
|
return fmt.Sprintf("path %q is not a descendant of mount point root %q and cannot be exposed from %q", err.path, err.root, err.mountPoint)
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package cgroups
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_mountInfoSep = " "
|
||||||
|
_mountInfoOptsSep = ","
|
||||||
|
_mountInfoOptionalFieldsSep = "-"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_miFieldIDMountID = iota
|
||||||
|
_miFieldIDParentID
|
||||||
|
_miFieldIDDeviceID
|
||||||
|
_miFieldIDRoot
|
||||||
|
_miFieldIDMountPoint
|
||||||
|
_miFieldIDOptions
|
||||||
|
_miFieldIDOptionalFields
|
||||||
|
|
||||||
|
_miFieldCountFirstHalf
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_miFieldOffsetFSType = iota
|
||||||
|
_miFieldOffsetMountSource
|
||||||
|
_miFieldOffsetSuperOptions
|
||||||
|
|
||||||
|
_miFieldCountSecondHalf
|
||||||
|
)
|
||||||
|
|
||||||
|
const _miFieldCountMin = _miFieldCountFirstHalf + _miFieldCountSecondHalf
|
||||||
|
|
||||||
|
// MountPoint is the data structure for the mount points in
|
||||||
|
// `/proc/$PID/mountinfo`. See also proc(5) for more information.
|
||||||
|
type MountPoint struct {
|
||||||
|
MountID int
|
||||||
|
ParentID int
|
||||||
|
DeviceID string
|
||||||
|
Root string
|
||||||
|
MountPoint string
|
||||||
|
Options []string
|
||||||
|
OptionalFields []string
|
||||||
|
FSType string
|
||||||
|
MountSource string
|
||||||
|
SuperOptions []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMountPointFromLine parses a line read from `/proc/$PID/mountinfo` and
|
||||||
|
// returns a new *MountPoint.
|
||||||
|
func NewMountPointFromLine(line string) (*MountPoint, error) {
|
||||||
|
fields := strings.Split(line, _mountInfoSep)
|
||||||
|
|
||||||
|
if len(fields) < _miFieldCountMin {
|
||||||
|
return nil, mountPointFormatInvalidError{line}
|
||||||
|
}
|
||||||
|
|
||||||
|
mountID, err := strconv.Atoi(fields[_miFieldIDMountID])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
parentID, err := strconv.Atoi(fields[_miFieldIDParentID])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, field := range fields[_miFieldIDOptionalFields:] {
|
||||||
|
if field == _mountInfoOptionalFieldsSep {
|
||||||
|
fsTypeStart := _miFieldIDOptionalFields + i + 1
|
||||||
|
|
||||||
|
if len(fields) != fsTypeStart+_miFieldCountSecondHalf {
|
||||||
|
return nil, mountPointFormatInvalidError{line}
|
||||||
|
}
|
||||||
|
|
||||||
|
miFieldIDFSType := _miFieldOffsetFSType + fsTypeStart
|
||||||
|
miFieldIDMountSource := _miFieldOffsetMountSource + fsTypeStart
|
||||||
|
miFieldIDSuperOptions := _miFieldOffsetSuperOptions + fsTypeStart
|
||||||
|
|
||||||
|
return &MountPoint{
|
||||||
|
MountID: mountID,
|
||||||
|
ParentID: parentID,
|
||||||
|
DeviceID: fields[_miFieldIDDeviceID],
|
||||||
|
Root: fields[_miFieldIDRoot],
|
||||||
|
MountPoint: fields[_miFieldIDMountPoint],
|
||||||
|
Options: strings.Split(fields[_miFieldIDOptions], _mountInfoOptsSep),
|
||||||
|
OptionalFields: fields[_miFieldIDOptionalFields:(fsTypeStart - 1)],
|
||||||
|
FSType: fields[miFieldIDFSType],
|
||||||
|
MountSource: fields[miFieldIDMountSource],
|
||||||
|
SuperOptions: strings.Split(fields[miFieldIDSuperOptions], _mountInfoOptsSep),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, mountPointFormatInvalidError{line}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate converts an absolute path inside the *MountPoint's file system to
|
||||||
|
// the host file system path in the mount namespace the *MountPoint belongs to.
|
||||||
|
func (mp *MountPoint) Translate(absPath string) (string, error) {
|
||||||
|
relPath, err := filepath.Rel(mp.Root, absPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if relPath == ".." || strings.HasPrefix(relPath, "../") {
|
||||||
|
return "", pathNotExposedFromMountPointError{
|
||||||
|
mountPoint: mp.MountPoint,
|
||||||
|
root: mp.Root,
|
||||||
|
path: absPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(mp.MountPoint, relPath), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseMountInfo parses procPathMountInfo (usually at `/proc/$PID/mountinfo`)
|
||||||
|
// and yields parsed *MountPoint into newMountPoint.
|
||||||
|
func parseMountInfo(procPathMountInfo string, newMountPoint func(*MountPoint) error) error {
|
||||||
|
mountInfoFile, err := os.Open(procPathMountInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer mountInfoFile.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(mountInfoFile)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
mountPoint, err := NewMountPointFromLine(scanner.Text())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := newMountPoint(mountPoint); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scanner.Err()
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package cgroups
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_cgroupSep = ":"
|
||||||
|
_cgroupSubsysSep = ","
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_csFieldIDID = iota
|
||||||
|
_csFieldIDSubsystems
|
||||||
|
_csFieldIDName
|
||||||
|
_csFieldCount
|
||||||
|
)
|
||||||
|
|
||||||
|
// CGroupSubsys represents the data structure for entities in
|
||||||
|
// `/proc/$PID/cgroup`. See also proc(5) for more information.
|
||||||
|
type CGroupSubsys struct {
|
||||||
|
ID int
|
||||||
|
Subsystems []string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCGroupSubsysFromLine returns a new *CGroupSubsys by parsing a string in
|
||||||
|
// the format of `/proc/$PID/cgroup`
|
||||||
|
func NewCGroupSubsysFromLine(line string) (*CGroupSubsys, error) {
|
||||||
|
fields := strings.SplitN(line, _cgroupSep, _csFieldCount)
|
||||||
|
|
||||||
|
if len(fields) != _csFieldCount {
|
||||||
|
return nil, cgroupSubsysFormatInvalidError{line}
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.Atoi(fields[_csFieldIDID])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroup := &CGroupSubsys{
|
||||||
|
ID: id,
|
||||||
|
Subsystems: strings.Split(fields[_csFieldIDSubsystems], _cgroupSubsysSep),
|
||||||
|
Name: fields[_csFieldIDName],
|
||||||
|
}
|
||||||
|
|
||||||
|
return cgroup, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseCGroupSubsystems parses procPathCGroup (usually at `/proc/$PID/cgroup`)
|
||||||
|
// and returns a new map[string]*CGroupSubsys.
|
||||||
|
func parseCGroupSubsystems(procPathCGroup string) (map[string]*CGroupSubsys, error) {
|
||||||
|
cgroupFile, err := os.Open(procPathCGroup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cgroupFile.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(cgroupFile)
|
||||||
|
subsystems := make(map[string]*CGroupSubsys)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
cgroup, err := NewCGroupSubsysFromLine(scanner.Text())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, subsys := range cgroup.Subsystems {
|
||||||
|
subsystems[subsys] = cgroup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return subsystems, nil
|
||||||
|
}
|
49
vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go
generated
vendored
Normal file
49
vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
cg "go.uber.org/automaxprocs/internal/cgroups"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CPUQuotaToGOMAXPROCS converts the CPU quota applied to the calling process
|
||||||
|
// to a valid GOMAXPROCS value.
|
||||||
|
func CPUQuotaToGOMAXPROCS(minValue int) (int, CPUQuotaStatus, error) {
|
||||||
|
cgroups, err := cg.NewCGroupsForCurrentProcess()
|
||||||
|
if err != nil {
|
||||||
|
return -1, CPUQuotaUndefined, err
|
||||||
|
}
|
||||||
|
|
||||||
|
quota, defined, err := cgroups.CPUQuota()
|
||||||
|
if !defined || err != nil {
|
||||||
|
return -1, CPUQuotaUndefined, err
|
||||||
|
}
|
||||||
|
|
||||||
|
maxProcs := int(math.Floor(quota))
|
||||||
|
if minValue > 0 && maxProcs < minValue {
|
||||||
|
return minValue, CPUQuotaMinUsed, nil
|
||||||
|
}
|
||||||
|
return maxProcs, CPUQuotaUsed, nil
|
||||||
|
}
|
30
vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go
generated
vendored
Normal file
30
vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
// CPUQuotaToGOMAXPROCS converts the CPU quota applied to the calling process
|
||||||
|
// to a valid GOMAXPROCS value. This is Linux-specific and not supported in the
|
||||||
|
// current OS.
|
||||||
|
func CPUQuotaToGOMAXPROCS(_ int) (int, CPUQuotaStatus, error) {
|
||||||
|
return -1, CPUQuotaUndefined, nil
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
// CPUQuotaStatus presents the status of how CPU quota is used
|
||||||
|
type CPUQuotaStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CPUQuotaUndefined is returned when CPU quota is undefined
|
||||||
|
CPUQuotaUndefined CPUQuotaStatus = iota
|
||||||
|
// CPUQuotaUsed is returned when a valid CPU quota can be used
|
||||||
|
CPUQuotaUsed
|
||||||
|
// CPUQuotaMinUsed is return when CPU quota is smaller than the min value
|
||||||
|
CPUQuotaMinUsed
|
||||||
|
)
|
|
@ -0,0 +1,130 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// Package maxprocs lets Go programs easily configure runtime.GOMAXPROCS to
|
||||||
|
// match the configured Linux CPU quota. Unlike the top-level automaxprocs
|
||||||
|
// package, it lets the caller configure logging and handle errors.
|
||||||
|
package maxprocs // import "go.uber.org/automaxprocs/maxprocs"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
iruntime "go.uber.org/automaxprocs/internal/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
const _maxProcsKey = "GOMAXPROCS"
|
||||||
|
|
||||||
|
func currentMaxProcs() int {
|
||||||
|
return runtime.GOMAXPROCS(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
printf func(string, ...interface{})
|
||||||
|
procs func(int) (int, iruntime.CPUQuotaStatus, error)
|
||||||
|
minGOMAXPROCS int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *config) log(fmt string, args ...interface{}) {
|
||||||
|
if c.printf != nil {
|
||||||
|
c.printf(fmt, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Option alters the behavior of Set.
|
||||||
|
type Option interface {
|
||||||
|
apply(*config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logger uses the supplied printf implementation for log output. By default,
|
||||||
|
// Set doesn't log anything.
|
||||||
|
func Logger(printf func(string, ...interface{})) Option {
|
||||||
|
return optionFunc(func(cfg *config) {
|
||||||
|
cfg.printf = printf
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Min sets the minimum GOMAXPROCS value that will be used.
|
||||||
|
// Any value below 1 is ignored.
|
||||||
|
func Min(n int) Option {
|
||||||
|
return optionFunc(func(cfg *config) {
|
||||||
|
if n >= 1 {
|
||||||
|
cfg.minGOMAXPROCS = n
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type optionFunc func(*config)
|
||||||
|
|
||||||
|
func (of optionFunc) apply(cfg *config) { of(cfg) }
|
||||||
|
|
||||||
|
// Set GOMAXPROCS to match the Linux container CPU quota (if any), returning
|
||||||
|
// any error encountered and an undo function.
|
||||||
|
//
|
||||||
|
// Set is a no-op on non-Linux systems and in Linux environments without a
|
||||||
|
// configured CPU quota.
|
||||||
|
func Set(opts ...Option) (func(), error) {
|
||||||
|
cfg := &config{
|
||||||
|
procs: iruntime.CPUQuotaToGOMAXPROCS,
|
||||||
|
minGOMAXPROCS: 1,
|
||||||
|
}
|
||||||
|
for _, o := range opts {
|
||||||
|
o.apply(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
undoNoop := func() {
|
||||||
|
cfg.log("maxprocs: No GOMAXPROCS change to reset")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Honor the GOMAXPROCS environment variable if present. Otherwise, amend
|
||||||
|
// `runtime.GOMAXPROCS()` with the current process' CPU quota if the OS is
|
||||||
|
// Linux, and guarantee a minimum value of 1. The minimum guaranteed value
|
||||||
|
// can be overriden using `maxprocs.Min()`.
|
||||||
|
if max, exists := os.LookupEnv(_maxProcsKey); exists {
|
||||||
|
cfg.log("maxprocs: Honoring GOMAXPROCS=%q as set in environment", max)
|
||||||
|
return undoNoop, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
maxProcs, status, err := cfg.procs(cfg.minGOMAXPROCS)
|
||||||
|
if err != nil {
|
||||||
|
return undoNoop, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == iruntime.CPUQuotaUndefined {
|
||||||
|
cfg.log("maxprocs: Leaving GOMAXPROCS=%v: CPU quota undefined", currentMaxProcs())
|
||||||
|
return undoNoop, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
prev := currentMaxProcs()
|
||||||
|
undo := func() {
|
||||||
|
cfg.log("maxprocs: Resetting GOMAXPROCS to %v", prev)
|
||||||
|
runtime.GOMAXPROCS(prev)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch status {
|
||||||
|
case iruntime.CPUQuotaMinUsed:
|
||||||
|
cfg.log("maxprocs: Updating GOMAXPROCS=%v: using minimum allowed GOMAXPROCS", maxProcs)
|
||||||
|
case iruntime.CPUQuotaUsed:
|
||||||
|
cfg.log("maxprocs: Updating GOMAXPROCS=%v: determined from CPU quota", maxProcs)
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.GOMAXPROCS(maxProcs)
|
||||||
|
return undo, nil
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
package maxprocs
|
||||||
|
|
||||||
|
// Version is the current package version.
|
||||||
|
const Version = "1.4.0"
|
|
@ -250,6 +250,12 @@ github.com/stretchr/testify/require
|
||||||
## explicit
|
## explicit
|
||||||
github.com/urfave/cli/v2
|
github.com/urfave/cli/v2
|
||||||
github.com/urfave/cli/v2/altsrc
|
github.com/urfave/cli/v2/altsrc
|
||||||
|
# go.uber.org/automaxprocs v1.4.0
|
||||||
|
## explicit
|
||||||
|
go.uber.org/automaxprocs
|
||||||
|
go.uber.org/automaxprocs/internal/cgroups
|
||||||
|
go.uber.org/automaxprocs/internal/runtime
|
||||||
|
go.uber.org/automaxprocs/maxprocs
|
||||||
# golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
# golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
## explicit
|
## explicit
|
||||||
golang.org/x/crypto/blake2b
|
golang.org/x/crypto/blake2b
|
||||||
|
|
Loading…
Reference in New Issue