@@ -13,6 +13,7 @@ import (
13
13
"io/ioutil"
14
14
"os"
15
15
"os/exec"
16
+ "os/signal"
16
17
"path/filepath"
17
18
"regexp"
18
19
"strings"
@@ -158,6 +159,10 @@ func (ms *mutationStats) Total() int {
158
159
return ms .passed + ms .failed + ms .skipped
159
160
}
160
161
162
+ // Used by OS signal handler.
163
+ var tmpFiles = make (map [string ]struct {})
164
+ var tmpDir string
165
+
161
166
func mainCmd (args []string ) int {
162
167
var opts = & options {}
163
168
var mutationBlackList = map [string ]struct {}{}
@@ -166,6 +171,28 @@ func mainCmd(args []string) int {
166
171
return exitCode
167
172
}
168
173
174
+ sigCh := make (chan os.Signal , 1 )
175
+ signal .Notify (sigCh , os .Interrupt , syscall .SIGINT , syscall .SIGTERM , syscall .SIGHUP , syscall .SIGQUIT )
176
+ go func () {
177
+ for {
178
+ sig := <- sigCh
179
+ verbose (opts , "Signal (%s) received, exiting..." , sig )
180
+
181
+ for file := range tmpFiles {
182
+ // "smth.tmp" -> "smth"
183
+ if err := os .Rename (file , file [:len (file )- 4 ]); err != nil {
184
+ fmt .Printf ("Failed to restore original version of file %s, it is stored in %s.\n " , file [:len (file )- 4 ], file )
185
+ fmt .Println (err )
186
+ }
187
+ }
188
+ if err := os .RemoveAll (tmpDir ); err != nil {
189
+ fmt .Printf ("Failed to remove temporary directory (%s): %v.\n " , tmpDir , err )
190
+ }
191
+
192
+ os .Exit (1 )
193
+ }
194
+ }()
195
+
169
196
files := importing .FilesOfArgs (opts .Remaining .Targets )
170
197
if len (files ) == 0 {
171
198
return exitError ("Could not find any suitable Go source files" )
@@ -238,7 +265,8 @@ MUTATOR:
238
265
})
239
266
}
240
267
241
- tmpDir , err := ioutil .TempDir ("" , "go-mutesting-" )
268
+ var err error
269
+ tmpDir , err = ioutil .TempDir ("" , "go-mutesting-" )
242
270
if err != nil {
243
271
panic (err )
244
272
}
@@ -390,6 +418,9 @@ func mutateExec(opts *options, pkg *types.Package, file string, src ast.Node, mu
390
418
}
391
419
392
420
defer func () {
421
+ // Remove tmp file from clean list for signal handler.
422
+ delete (tmpFiles , file + ".tmp" )
423
+
393
424
_ = os .Rename (file + ".tmp" , file )
394
425
}()
395
426
@@ -402,6 +433,9 @@ func mutateExec(opts *options, pkg *types.Package, file string, src ast.Node, mu
402
433
panic (err )
403
434
}
404
435
436
+ // Add tmp file to clean list for signal handler.
437
+ tmpFiles [file + ".tmp" ] = struct {}{}
438
+
405
439
pkgName := pkg .Path ()
406
440
if opts .Test .Recursive {
407
441
pkgName += "/..."
0 commit comments