github.com/rigado/snapd@v2.42.5-go-mod+incompatible/cmd/snap-update-ns/freezer.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package main 21 22 import ( 23 "bytes" 24 "fmt" 25 "io/ioutil" 26 "os" 27 "path/filepath" 28 "time" 29 ) 30 31 var freezerCgroupDir = "/sys/fs/cgroup/freezer" 32 33 var ( 34 freezeSnapProcesses = freezeSnapProcessesImpl 35 thawSnapProcesses = thawSnapProcessesImpl 36 ) 37 38 // freezeSnapProcessesImpl freezes all the processes originating from the given snap. 39 // Processes are frozen regardless of which particular snap application they 40 // originate from. 41 func freezeSnapProcessesImpl(snapName string) error { 42 fname := filepath.Join(freezerCgroupDir, fmt.Sprintf("snap.%s", snapName), "freezer.state") 43 if err := ioutil.WriteFile(fname, []byte("FROZEN"), 0644); err != nil && os.IsNotExist(err) { 44 // When there's no freezer cgroup we don't have to freeze anything. 45 // This can happen when no process belonging to a given snap has been 46 // started yet. 47 return nil 48 } else if err != nil { 49 return fmt.Errorf("cannot freeze processes of snap %q, %v", snapName, err) 50 } 51 for i := 0; i < 30; i++ { 52 data, err := ioutil.ReadFile(fname) 53 if err != nil { 54 return fmt.Errorf("cannot determine the freeze state of processes of snap %q, %v", snapName, err) 55 } 56 // If the cgroup is still freezing then wait a moment and try again. 57 if bytes.Equal(data, []byte("FREEZING")) { 58 time.Sleep(100 * time.Millisecond) 59 continue 60 } 61 return nil 62 } 63 // If we got here then we timed out after seeing FREEZING for too long. 64 thawSnapProcesses(snapName) // ignore the error, this is best-effort. 65 return fmt.Errorf("cannot finish freezing processes of snap %q", snapName) 66 } 67 68 func thawSnapProcessesImpl(snapName string) error { 69 fname := filepath.Join(freezerCgroupDir, fmt.Sprintf("snap.%s", snapName), "freezer.state") 70 if err := ioutil.WriteFile(fname, []byte("THAWED"), 0644); err != nil && os.IsNotExist(err) { 71 // When there's no freezer cgroup we don't have to thaw anything. 72 // This can happen when no process belonging to a given snap has been 73 // started yet. 74 return nil 75 } else if err != nil { 76 return fmt.Errorf("cannot thaw processes of snap %q", snapName) 77 } 78 return nil 79 }