Created
July 15, 2014 17:28
-
-
Save quiiver/206d9e6127186d5975c2 to your computer and use it in GitHub Desktop.
Hot reloadable tcp client in go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"log" | |
"net" | |
"os" | |
"os/signal" | |
"syscall" | |
"time" | |
) | |
var fds = flag.Int("fds", -1, "Fd you want to take over") | |
func send(conn net.Conn, fd uintptr) { | |
l, err := conn.Write([]byte("============= NEW CONN ===================\n")) | |
log.Printf("Wrote %d bytes to conn %v", l, conn) | |
if err != nil { | |
log.Printf("Could not write conn err: %v", err) | |
panic(err) | |
} | |
for { | |
conn.Write([]byte(fmt.Sprintf("hello from pid: %d, fd: %d\n", syscall.Getpid(), fd))) | |
time.Sleep(time.Second * 1) | |
} | |
} | |
func connect() (fd uintptr) { | |
if *fds == -1 { | |
log.Println("creating a new connection no fd to inherit") | |
conn, err := net.Dial("tcp", "localhost:3333") | |
if err != nil { | |
log.Panic(err) | |
} | |
tcp := conn.(*net.TCPConn) | |
file, err := tcp.File() | |
fd := file.Fd() | |
//fd, err = getFd(conn) | |
if err != nil { | |
log.Panic(fmt.Errorf("Error getting FD: %v", err)) | |
} | |
go send(conn, fd) | |
return fd | |
} | |
fd = uintptr(*fds) | |
file := os.NewFile(fd, "tcp sock") | |
conn, err := net.FileConn(file) | |
if err != nil { | |
log.Panic(err) | |
} | |
log.Printf("inheriting connection. fd: %v, conn: %+v ", fd, conn) | |
go send(conn, fd) | |
return | |
} | |
func dup(oldfd int) (newfd int, err error) { | |
syscall.ForkLock.RLock() | |
defer syscall.ForkLock.RUnlock() | |
newfd, err = syscall.Dup(oldfd) | |
if err != nil { | |
return -1, err | |
} | |
return | |
} | |
func main() { | |
flag.Parse() | |
var fd uintptr | |
log.Println("fd to reconnect", *fds) | |
sigc := make(chan os.Signal, 1) | |
signal.Notify(sigc, syscall.SIGHUP) | |
fd = connect() | |
log.Println("Got fd from connect: ", fd) | |
log.Println("waiting for signal") | |
log.Printf("kill -SIGHUP %d", syscall.Getpid()) | |
sig := <-sigc | |
newFd, err := dup(int(fd)) | |
if err != nil { | |
panic(err) | |
} | |
log.Println("Got signal:", sig) | |
args := append(os.Args, fmt.Sprintf("-fds=%d", newFd)) | |
cmd := os.Args[0] | |
syscall.Exec(cmd, args, os.Environ()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment