mirror of
https://github.com/restic/restic.git
synced 2025-01-03 13:45:20 +00:00
Merge pull request #2689 from MichaelEischer/fix-background-hang
Fix shutdown hang when restic is started as background job
This commit is contained in:
commit
3ee6b8ec63
2 changed files with 25 additions and 2 deletions
8
changelog/unreleased/issue-2298
Normal file
8
changelog/unreleased/issue-2298
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Bugfix: Do not hang when run as a background job
|
||||||
|
|
||||||
|
Restic did hang on exit while restoring the terminal configuration when it was
|
||||||
|
started as a background job, for example using `restic ... &`. This has been
|
||||||
|
fixed by only restoring the terminal configuration when restic is interrupted
|
||||||
|
while reading a password from the terminal.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/2298
|
|
@ -85,6 +85,8 @@ var globalOptions = GlobalOptions{
|
||||||
stderr: os.Stderr,
|
stderr: os.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isReadingPassword bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
globalOptions.ctx, cancel = context.WithCancel(context.Background())
|
globalOptions.ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
@ -146,7 +148,10 @@ func stdoutTerminalWidth() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// restoreTerminal installs a cleanup handler that restores the previous
|
// restoreTerminal installs a cleanup handler that restores the previous
|
||||||
// terminal state on exit.
|
// terminal state on exit. This handler is only intended to restore the
|
||||||
|
// terminal configuration if restic exits after receiving a signal. A regular
|
||||||
|
// program execution must revert changes to the terminal configuration itself.
|
||||||
|
// The terminal configuration is only restored while reading a password.
|
||||||
func restoreTerminal() {
|
func restoreTerminal() {
|
||||||
if !stdoutIsTerminal() {
|
if !stdoutIsTerminal() {
|
||||||
return
|
return
|
||||||
|
@ -160,9 +165,17 @@ func restoreTerminal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
AddCleanupHandler(func() error {
|
AddCleanupHandler(func() error {
|
||||||
|
// Restoring the terminal configuration while restic runs in the
|
||||||
|
// background, causes restic to get stopped on unix systems with
|
||||||
|
// a SIGTTOU signal. Thus only restore the terminal settings if
|
||||||
|
// they might have been modified, which is the case while reading
|
||||||
|
// a password.
|
||||||
|
if !isReadingPassword {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
err := checkErrno(terminal.Restore(fd, state))
|
err := checkErrno(terminal.Restore(fd, state))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "unable to get restore terminal state: %#+v\n", err)
|
fmt.Fprintf(os.Stderr, "unable to restore terminal state: %v\n", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -302,7 +315,9 @@ func readPassword(in io.Reader) (password string, err error) {
|
||||||
// password.
|
// password.
|
||||||
func readPasswordTerminal(in *os.File, out io.Writer, prompt string) (password string, err error) {
|
func readPasswordTerminal(in *os.File, out io.Writer, prompt string) (password string, err error) {
|
||||||
fmt.Fprint(out, prompt)
|
fmt.Fprint(out, prompt)
|
||||||
|
isReadingPassword = true
|
||||||
buf, err := terminal.ReadPassword(int(in.Fd()))
|
buf, err := terminal.ReadPassword(int(in.Fd()))
|
||||||
|
isReadingPassword = false
|
||||||
fmt.Fprintln(out)
|
fmt.Fprintln(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "ReadPassword")
|
return "", errors.Wrap(err, "ReadPassword")
|
||||||
|
|
Loading…
Reference in a new issue