11package main
22
33import (
4- "fmt "
4+ "code.cloudfoundry.org/cfdev/cfdevd/cmd "
55 "log"
66 "net"
77 "os"
88 "os/signal"
9- "path/filepath"
109 "syscall"
1110
12- "io"
13-
1411 "time"
1512
16- "code.cloudfoundry.org/cfdev/cfdevd/cmd"
1713 "code.cloudfoundry.org/cfdev/daemon"
1814
1915 "github.com/spf13/cobra"
2016)
2117
22- const SockName = "ListenSocket"
2318
24- func handleRequest (conn * net.UnixConn ) {
25- if err := doHandshake (conn ); err != nil {
26- fmt .Println ("Handshake Error: " , err )
27- return
28- }
29-
30- defer conn .Close ()
31-
32- command , err := cmd .UnmarshalCommand (conn )
33- if err != nil {
34- fmt .Println ("Command:" , err )
35- return
36- }
37- command .Execute (conn )
38- }
39-
40- func registerSignalHandler () {
41- sigc := make (chan os.Signal , 1 )
42- signal .Notify (sigc , os .Interrupt , syscall .SIGTERM )
43- go func (c chan os.Signal ) {
44- sig := <- c
45- log .Printf ("Caught signal %s: shutting down." , sig )
46- os .Exit (0 )
47- }(sigc )
48- }
19+ var (
20+ timesyncSocket = ""
21+ sockName = "ListenSocket"
22+ doneChan = make (chan bool , 10 )
23+ )
4924
50- func install (programSrc string , args []string ) {
51- lctl := daemon .New ("" )
52- program := "/Library/PrivilegedHelperTools/org.cloudfoundry.cfdevd"
53- programArgs := []string {program }
54- programArgs = append (programArgs , args ... )
55- cfdevdSpec := daemon.DaemonSpec {
56- Label : "org.cloudfoundry.cfdevd" ,
57- Program : program ,
58- ProgramArguments : programArgs ,
59- RunAtLoad : false ,
60- Sockets : map [string ]string {
61- SockName : "/var/tmp/cfdevd.socket" ,
62- },
63- StdoutPath : "/var/tmp/cfdevd.stdout.log" ,
64- StderrPath : "/var/tmp/cfdevd.stderr.log" ,
65- }
66- if err := copyExecutable (programSrc , program ); err != nil {
67- fmt .Println ("Failed to copy cfdevd: " , err )
68- }
69- if err := lctl .AddDaemon (cfdevdSpec ); err != nil {
70- fmt .Println ("Failed to install cfdevd: " , err )
25+ func main () {
26+ if len (os .Args ) > 1 {
27+ switch os .Args [1 ] {
28+ case "install" :
29+ err := install (os .Args [0 ], os .Args [2 :])
30+ if err != nil {
31+ log .Printf ("Error: %s\n " , err )
32+ os .Exit (1 )
33+ }
34+ default :
35+ rootCmd := root ()
36+ rootCmd .SetArgs (os .Args [1 :])
37+ rootCmd .Execute ()
38+ }
7139 }
7240}
7341
74- func copyExecutable (src string , dest string ) error {
75- if err := os .MkdirAll (filepath .Dir (dest ), 0755 ); err != nil {
76- return err
77- }
78-
79- target , err := os .Create (dest )
80- if err != nil {
81- return err
82- }
83-
84- if err = os .Chmod (dest , 0744 ); err != nil {
85- return err
86- }
42+ func root () * cobra.Command {
43+ root := & cobra.Command {Use : "cfdevd" }
44+ root .PersistentFlags ().StringVarP (& timesyncSocket , "timesyncSock" , "t" , "" ,"path to socket where host-timesync-daemon is listening" )
45+ root .Run = func (_ * cobra.Command , _ []string ) {
46+ log .Printf ("Running cfdevd with timesyncSocket=%s\n " , timesyncSocket )
8747
88- binData , err := os . Open ( src )
89- if err != nil {
90- return err
48+ go registerSignalHandler ( )
49+ go syncTime ( timesyncSocket )
50+ listenAndServe ()
9151 }
9252
93- _ , err = io .Copy (target , binData )
94- return err
95- }
96-
97- func timesync (socket string ) {
98- for {
99- fmt .Printf ("dialing socket %s \n " , socket )
100- conn , _ := net .DialUnix ("unix" , nil , & net.UnixAddr {
101- Net : "unix" ,
102- Name : socket ,
103- })
104- if conn != nil {
105- conn .CloseWrite ()
106- }
107- time .Sleep (5 * time .Second )
108- }
53+ return root
10954}
11055
111- func run (timesyncSocket string ) {
112- fmt .Println ("SOCKET: " , timesyncSocket )
113- if timesyncSocket != "" {
114- fmt .Println ("timesync" )
115- go timesync (timesyncSocket )
116- }
117- registerSignalHandler ()
118- listeners , err := daemon .Listeners (SockName )
56+ func listenAndServe () {
57+ listeners , err := daemon .Listeners (sockName )
11958 if err != nil || len (listeners ) != 1 {
120- log .Fatal ("Failed to obtain socket from launchd" )
59+ log .Fatalf ("Failed to obtain socket from launchd: %s \n " , err )
12160 }
61+
12262 listener , ok := listeners [0 ].(* net.UnixListener )
12363 if ! ok {
12464 log .Fatal ("Failed to cast listener to unix listener" )
12565 }
66+
12667 for {
127- conn , err := listener .AcceptUnix ()
128- if err != nil {
129- continue
130- }
131- go handleRequest (conn )
68+ select {
69+ case <- doneChan :
70+ log .Println ("Terminating server listener..." )
71+ return
72+ default :
73+ conn , err := listener .AcceptUnix ()
74+ if err != nil {
75+ continue
76+ }
77+
78+ if err := doHandshake (conn ); err != nil {
79+ log .Printf ("Handshake Error: %s\n " , err )
80+ continue
81+ }
82+
83+ command , err := cmd .UnmarshalCommand (conn )
84+ if err != nil {
85+ log .Printf ("Command Error: %s\n " , err )
86+ continue
87+ }
88+
89+ command .Execute (conn )
90+ conn .Close ()
91+ }
13292 }
93+
13394}
13495
135- func root () * cobra.Command {
136- root := & cobra.Command {Use : "cfdevd" }
137- flags := root .PersistentFlags ()
138- var timesyncSocket string
139- flags .StringVarP (& timesyncSocket , "timesyncSock" , "t" , "" , "path to socket where host-timesync-daemon is listening" )
140- root .Run = func (_ * cobra.Command , _ []string ) {
141- log .Printf ("running cfdevd with timesyncSocket=%s" , timesyncSocket )
142- run (timesyncSocket )
96+ func syncTime (socket string ) {
97+ if socket == "" {
98+ return
14399 }
144- return root
145- }
146100
147- func main () {
148- if len (os .Args ) > 1 {
149- switch os .Args [1 ] {
150- case "install" :
151- install (os .Args [0 ], os .Args [2 :])
152- default :
153- rootCmd := root ()
154- rootCmd .SetArgs (os .Args [1 :])
155- rootCmd .Execute ()
101+ ticker := time .NewTicker (5 * time .Second )
102+
103+ for {
104+ select {
105+ case <- doneChan :
106+ log .Println ("Terminating time sync..." )
107+ return
108+ case <- ticker .C :
109+ // Only try to sync when the socket finally appears
110+ // to avoid the race condition
111+ if _ , err := os .Stat (socket ); os .IsNotExist (err ) {
112+ continue
113+ }
114+
115+ conn , err := net .DialUnix ("unix" , nil , & net.UnixAddr {
116+ Net : "unix" ,
117+ Name : socket ,
118+ })
119+
120+ if err != nil {
121+ log .Printf ("[WHOOPS] we have an error %s\n " , err )
122+ continue
123+ }
124+
125+ // Only close if the error is nil
126+ // and thus 'conn' is not nil or it will panic
127+ conn .Close ()
156128 }
157129 }
158130}
131+
132+ func registerSignalHandler () {
133+ sigc := make (chan os.Signal , 1 )
134+ signal .Notify (sigc , os .Interrupt , syscall .SIGTERM )
135+
136+ <- sigc
137+ log .Println ("Shutting down..." )
138+
139+ // We have at least 2 go functions running so
140+ // we send multiple signals to end them all
141+ doneChan <- true
142+ doneChan <- true
143+ doneChan <- true
144+ }
0 commit comments