MCPcopy Create free account
hub / github.com/PostHog/duckgres / spawnChildForTLS

Method spawnChildForTLS

server/parent.go:132–232  ·  view source on GitHub ↗

spawnChildForTLS spawns a child worker process to handle TLS handshake and the rest of the connection. This is called after the parent has received an SSL request and sent 'S'. The TCP connection file descriptor is passed to the child via ExtraFiles. Returns the spawned child process or an error.

(conn net.Conn)

Source from the content-addressed store, hash-verified

130// The TCP connection file descriptor is passed to the child via ExtraFiles.
131// Returns the spawned child process or an error.
132func (s *Server) spawnChildForTLS(conn net.Conn) (*ChildProcess, error) {
133 tcpConn, ok := conn.(*net.TCPConn)
134 if !ok {
135 return nil, fmt.Errorf("connection is not TCP")
136 }
137
138 // Get a file descriptor for the TCP connection
139 file, err := tcpConn.File()
140 if err != nil {
141 return nil, fmt.Errorf("failed to get file descriptor: %w", err)
142 }
143 // Note: tcpConn.File() duplicates the FD, so we need to close the original
144 // after starting the child. The file will be passed to the child.
145
146 remoteAddr := conn.RemoteAddr().String()
147
148 // Generate backend key for this connection (used for cancel requests)
149 backendSecretKey := generateSecretKey()
150
151 // Prepare child configuration
152 // Note: Username is not known yet - child will read it from the startup message after TLS
153 childCfg := ChildConfig{
154 RemoteAddr: remoteAddr,
155 DataDir: s.cfg.DataDir,
156 Extensions: s.cfg.Extensions,
157 IdleTimeout: int64(s.cfg.IdleTimeout),
158 ClientIdleTimeoutMax: int64(s.cfg.ClientIdleTimeoutMax),
159 TLSCertFile: s.cfg.TLSCertFile,
160 TLSKeyFile: s.cfg.TLSKeyFile,
161 DuckLake: s.cfg.DuckLake,
162 Users: s.cfg.Users, // Pass all users - child will look up after getting username
163 BackendSecretKey: backendSecretKey,
164 ServerStartTime: processStartTime.UnixNano(),
165 ServerVersion: processVersion,
166 }
167
168 configJSON, err := json.Marshal(childCfg)
169 if err != nil {
170 _ = file.Close()
171 return nil, fmt.Errorf("failed to marshal child config: %w", err)
172 }
173
174 // Spawn child process
175 cmd := exec.Command(os.Args[0])
176 cmd.Env = append(os.Environ(), "DUCKGRES_CHILD_MODE=1")
177 cmd.ExtraFiles = []*os.File{file} // Will be FD 3 in child
178
179 // Pass config via stdin (more secure than env var for passwords)
180 // Create a pipe for stdin
181 stdinPipe, err := cmd.StdinPipe()
182 if err != nil {
183 _ = file.Close()
184 return nil, fmt.Errorf("failed to create stdin pipe: %w", err)
185 }
186
187 // Inherit stdout/stderr for logging
188 cmd.Stdout = os.Stdout
189 cmd.Stderr = os.Stderr

Callers 1

Calls 6

NowMethod · 0.80
CloseMethod · 0.65
StringMethod · 0.45
RemoteAddrMethod · 0.45
StartMethod · 0.45
WriteMethod · 0.45

Tested by

no test coverage detected