I have a program that is working on my Mac reliably, but gives erratic
results on other (linux) systems. It maybe something wrong with my code,
but it not obvious to me at all what I might have done wrong.
You can see (but not run in playground) the code here (copy to your
system to try):
https://play.golang.org/p/w_PG50vz_fAll done with go version go1.9
What it does is launch 3 go routines that exec a sleep call with a
context. Then the cancel routines are called, either by a timer or
SIGINT handler.
The timer fires before the sleep call and cancels all the
execs and prints out the context error values ("context canceled").
***This works everywhere I've tested.***
There is also a SIGINT handler that cancels all the execs and prints
out the context error values.
When hitting ^C (after the 'waiting...' output) I get erratic behavior
where the context errs print out as nil most (but not all) of the
time, but sometimes 1 or more print out as "context canceled".
My Mac (OSX 10.12.6 Sierra) seems to work properly all the time.
Systems I have tested where it has had problems:
"real" Ubuntu 14.04
Docker Ubuntu 14.04 and 16.04 on "real" Ubuntu 14.04
VMWare Ubuntu 16.04, 14.04, 12.04
AWS instance Ubuntu 14.04
Output without SIGINT (all tested platforms - expected output):
% /tmp/exectest
waiting...
cancel 0
cancel 1
cancel 2
ctx.err 2 = "context canceled"
ctx.err 0 = "context canceled"
ctx.err 1 = "context canceled"
...done
Output on Mac with SIGINT (always seems to work):
% ./exectest
waiting...
^C! interrupt received !
cancel 0
cancel 1
cancel 2
ctx.err 0 = "context canceled"
ctx.err 1 = "context canceled"
ctx.err 2 = "context canceled"
...done
Example output on other systems with SIGINT (erratic):
% ./exectest
waiting...
^C! interrupt received !
cancel 0
cancel 1
cancel 2
ctx.err 0 = "context canceled"
ctx.err 1 = "context canceled"
ctx.err 2 = "context canceled"
...done
% ./exectest
waiting...
^C! interrupt received !
cancel 0
cancel 1
cancel 2
ctx.err 2 = %!q(<nil>)
ctx.err 0 = %!q(<nil>)
ctx.err 1 = %!q(<nil>)
...done
% ./exectest
waiting...
^Cctx.err 0 = %!q(<nil>)
! interrupt received !
cancel 0
ctx.err 2 = %!q(<nil>)
cancel 1
cancel 2
ctx.err 1 = %!q(<nil>)
...done
% ./exectest
waiting...
^C! interrupt received !
cancel 0
cancel 1
ctx.err 1 = %!q(<nil>)
ctx.err 2 = %!q(<nil>)
cancel 2
ctx.err 0 = "context canceled"
...done