Skip to content

Commit a752c89

Browse files
committed
Added hidden console allocation for transport processes on Windows.
This commit updates the process attributes and flags used for transport processes on Windows. Transport processes will now have a hidden console allocated by default. They were previously created without a console and would allocate one when required, creating a large number of pop-ups on Windows when using the Docker transport. This commit also takes the opportunity to reorganize the transport code and attributes. Fixes mutagen-io#233. Signed-off-by: Jacob Howard <[email protected]>
1 parent 3199de5 commit a752c89

24 files changed

+69
-71
lines changed

cmd/mutagen/daemon/start_windows.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ package daemon
33
import (
44
"syscall"
55

6-
"github.com/mutagen-io/mutagen/pkg/process"
6+
"golang.org/x/sys/windows"
77
)
88

99
// daemonProcessAttributes are the process attributes to use for the daemon.
1010
var daemonProcessAttributes = &syscall.SysProcAttr{
11-
CreationFlags: process.DETACHED_PROCESS | syscall.CREATE_NEW_PROCESS_GROUP,
11+
CreationFlags: windows.DETACHED_PROCESS | windows.CREATE_NEW_PROCESS_GROUP,
1212
}

pkg/agent/transport/doc.go

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Package transport provides common functionality for agent transports.
2+
package transport

pkg/agent/transports/docker/transport.go renamed to pkg/agent/transport/docker/transport.go

+17-16
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111
"github.com/pkg/errors"
1212

1313
"github.com/mutagen-io/mutagen/pkg/agent"
14-
"github.com/mutagen-io/mutagen/pkg/agent/transports/ssh"
14+
"github.com/mutagen-io/mutagen/pkg/agent/transport"
15+
"github.com/mutagen-io/mutagen/pkg/agent/transport/ssh"
1516
"github.com/mutagen-io/mutagen/pkg/docker"
1617
"github.com/mutagen-io/mutagen/pkg/process"
1718
"github.com/mutagen-io/mutagen/pkg/prompting"
@@ -26,8 +27,8 @@ Hyper-V doesn't support copying files into running containers.
2627
2728
Would you like to continue? (yes/no)? `
2829

29-
// transport implements the agent.Transport interface using Docker.
30-
type transport struct {
30+
// dockerTransport implements the agent.Transport interface using Docker.
31+
type dockerTransport struct {
3132
// container is the target container name.
3233
container string
3334
// user is the container user under which agents should be invoked.
@@ -73,7 +74,7 @@ func NewTransport(container, user string, environment, parameters map[string]str
7374
}
7475

7576
// Success.
76-
return &transport{
77+
return &dockerTransport{
7778
container: container,
7879
user: user,
7980
environment: environment,
@@ -86,7 +87,7 @@ func NewTransport(container, user string, environment, parameters map[string]str
8687
// specification of the working directory inside the container, as well as an
8788
// override of the executing user. An empty user specification means to use the
8889
// username specified in the remote URL, if any.
89-
func (t *transport) command(command, workingDirectory, user string) (*exec.Cmd, error) {
90+
func (t *dockerTransport) command(command, workingDirectory, user string) (*exec.Cmd, error) {
9091
// Set up top-level command-line flags.
9192
var dockerArguments []string
9293
dockerArguments = append(dockerArguments, t.daemonConnectionFlags...)
@@ -125,8 +126,8 @@ func (t *transport) command(command, workingDirectory, user string) (*exec.Cmd,
125126
return nil, err
126127
}
127128

128-
// Force it to run detached.
129-
dockerCommand.SysProcAttr = process.DetachedProcessAttributes()
129+
// Set the process attributes.
130+
dockerCommand.SysProcAttr = transport.ProcessAttributes()
130131

131132
// Create a copy of the current environment.
132133
environment := os.Environ()
@@ -152,7 +153,7 @@ func (t *transport) command(command, workingDirectory, user string) (*exec.Cmd,
152153
// probeContainer ensures that the containerIsWindows and containerHomeDirectory
153154
// fields are populated. It is idempotent. If probing previously failed, probing
154155
// will simply return an error indicating the previous failure.
155-
func (t *transport) probeContainer() error {
156+
func (t *dockerTransport) probeContainer() error {
156157
// Watch for previous errors.
157158
if t.containerProbeError != nil {
158159
return errors.Wrap(t.containerProbeError, "previous container probing failed")
@@ -286,7 +287,7 @@ func (t *transport) probeContainer() error {
286287

287288
// changeContainerStatus stops or starts the container. It is required for
288289
// copying files on Windows when using Hyper-V.
289-
func (t *transport) changeContainerStatus(stop bool) error {
290+
func (t *dockerTransport) changeContainerStatus(stop bool) error {
290291
// Set up top-level command-line flags.
291292
var dockerArguments []string
292293
dockerArguments = append(dockerArguments, t.daemonConnectionFlags...)
@@ -304,8 +305,8 @@ func (t *transport) changeContainerStatus(stop bool) error {
304305
return errors.Wrap(err, "unable to set up Docker invocation")
305306
}
306307

307-
// Force it to run detached.
308-
dockerCommand.SysProcAttr = process.DetachedProcessAttributes()
308+
// Set the process attributes.
309+
dockerCommand.SysProcAttr = transport.ProcessAttributes()
309310

310311
// Create a copy of the current environment.
311312
environment := os.Environ()
@@ -329,7 +330,7 @@ func (t *transport) changeContainerStatus(stop bool) error {
329330
}
330331

331332
// Copy implements the Copy method of agent.Transport.
332-
func (t *transport) Copy(localPath, remoteName string) error {
333+
func (t *dockerTransport) Copy(localPath, remoteName string) error {
333334
// Ensure that the container has been probed.
334335
if err := t.probeContainer(); err != nil {
335336
return errors.Wrap(err, "unable to probe container")
@@ -390,8 +391,8 @@ func (t *transport) Copy(localPath, remoteName string) error {
390391
return errors.Wrap(err, "unable to set up Docker invocation")
391392
}
392393

393-
// Force it to run detached.
394-
dockerCommand.SysProcAttr = process.DetachedProcessAttributes()
394+
// Set the process attributes.
395+
dockerCommand.SysProcAttr = transport.ProcessAttributes()
395396

396397
// Create a copy of the current environment.
397398
environment := os.Environ()
@@ -464,7 +465,7 @@ func (t *transport) Copy(localPath, remoteName string) error {
464465
}
465466

466467
// Command implements the Command method of agent.Transport.
467-
func (t *transport) Command(command string) (*exec.Cmd, error) {
468+
func (t *dockerTransport) Command(command string) (*exec.Cmd, error) {
468469
// Ensure that the container has been probed.
469470
if err := t.probeContainer(); err != nil {
470471
return nil, errors.Wrap(err, "unable to probe container")
@@ -475,7 +476,7 @@ func (t *transport) Command(command string) (*exec.Cmd, error) {
475476
}
476477

477478
// ClassifyError implements the ClassifyError method of agent.Transport.
478-
func (t *transport) ClassifyError(processState *os.ProcessState, errorOutput string) (bool, bool, error) {
479+
func (t *dockerTransport) ClassifyError(processState *os.ProcessState, errorOutput string) (bool, bool, error) {
479480
// Ensure that the container has been probed.
480481
if err := t.probeContainer(); err != nil {
481482
return false, false, errors.Wrap(err, "unable to probe container")

pkg/process/attributes_posix.go renamed to pkg/agent/transport/process_posix.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
// TODO: Figure out what to do for Plan 9. It doesn't support Setsid.
44

5-
package process
5+
package transport
66

77
import (
88
"syscall"
99
)
1010

11-
// DetachedProcessAttributes returns the process attributes to use for starting
12-
// detached processes.
13-
func DetachedProcessAttributes() *syscall.SysProcAttr {
11+
// ProcessAttributes returns the process attributes to use for starting
12+
// transport processes from the daemon.
13+
func ProcessAttributes() *syscall.SysProcAttr {
1414
return &syscall.SysProcAttr{
1515
// There's also a Noctty field, but it only detaches standard input from
1616
// the controlling terminal (not standard output or error), and if

pkg/agent/transport/process_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package transport
2+
3+
import (
4+
"testing"
5+
)
6+
7+
// TestProcessAttributes tests ProcessAttributes.
8+
func TestProcessAttributes(t *testing.T) {
9+
if ProcessAttributes() == nil {
10+
t.Error("nil transport process attributes returned")
11+
}
12+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package transport
2+
3+
import (
4+
"syscall"
5+
6+
"golang.org/x/sys/windows"
7+
)
8+
9+
// ProcessAttributes returns the process attributes to use for starting
10+
// transport processes from the daemon.
11+
func ProcessAttributes() *syscall.SysProcAttr {
12+
return &syscall.SysProcAttr{
13+
HideWindow: true,
14+
CreationFlags: windows.CREATE_NEW_CONSOLE,
15+
}
16+
}
File renamed without changes.

pkg/agent/transports/ssh/transport.go renamed to pkg/agent/transport/ssh/transport.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/pkg/errors"
1111

1212
"github.com/mutagen-io/mutagen/pkg/agent"
13+
"github.com/mutagen-io/mutagen/pkg/agent/transport"
1314
"github.com/mutagen-io/mutagen/pkg/process"
1415
"github.com/mutagen-io/mutagen/pkg/ssh"
1516
)
@@ -27,8 +28,8 @@ const (
2728
serverAliveCountMax = 1
2829
)
2930

30-
// transport implements the agent.Transport interface using SSH.
31-
type transport struct {
31+
// sshTransport implements the agent.Transport interface using SSH.
32+
type sshTransport struct {
3233
// user is the SSH user under which agents should be invoked.
3334
user string
3435
// host is the target host.
@@ -41,7 +42,7 @@ type transport struct {
4142

4243
// NewTransport creates a new SSH transport using the specified parameters.
4344
func NewTransport(user, host string, port uint16, prompter string) (agent.Transport, error) {
44-
return &transport{
45+
return &sshTransport{
4546
user: user,
4647
host: host,
4748
port: port,
@@ -50,7 +51,7 @@ func NewTransport(user, host string, port uint16, prompter string) (agent.Transp
5051
}
5152

5253
// Copy implements the Copy method of agent.Transport.
53-
func (t *transport) Copy(localPath, remoteName string) error {
54+
func (t *sshTransport) Copy(localPath, remoteName string) error {
5455
// HACK: On Windows, we attempt to use SCP executables that might not
5556
// understand Windows paths because they're designed to run inside a POSIX-
5657
// style environment (e.g. MSYS or Cygwin). To work around this, we run them
@@ -100,8 +101,8 @@ func (t *transport) Copy(localPath, remoteName string) error {
100101
// Set the working directory.
101102
scpCommand.Dir = workingDirectory
102103

103-
// Force it to run detached.
104-
scpCommand.SysProcAttr = process.DetachedProcessAttributes()
104+
// Set the process attributes.
105+
scpCommand.SysProcAttr = transport.ProcessAttributes()
105106

106107
// Create a copy of the current environment.
107108
environment := os.Environ()
@@ -128,7 +129,7 @@ func (t *transport) Copy(localPath, remoteName string) error {
128129
}
129130

130131
// Command implements the Command method of agent.Transport.
131-
func (t *transport) Command(command string) (*exec.Cmd, error) {
132+
func (t *sshTransport) Command(command string) (*exec.Cmd, error) {
132133
// Compute the target.
133134
target := t.host
134135
if t.user != "" {
@@ -154,7 +155,7 @@ func (t *transport) Command(command string) (*exec.Cmd, error) {
154155
}
155156

156157
// Force it to run detached.
157-
sshCommand.SysProcAttr = process.DetachedProcessAttributes()
158+
sshCommand.SysProcAttr = transport.ProcessAttributes()
158159

159160
// Create a copy of the current environment.
160161
environment := os.Environ()
@@ -176,7 +177,7 @@ func (t *transport) Command(command string) (*exec.Cmd, error) {
176177
}
177178

178179
// ClassifyError implements the ClassifyError method of agent.Transport.
179-
func (t *transport) ClassifyError(processState *os.ProcessState, errorOutput string) (bool, bool, error) {
180+
func (t *sshTransport) ClassifyError(processState *os.ProcessState, errorOutput string) (bool, bool, error) {
180181
// SSH faithfully returns exit codes and error output, so we can use direct
181182
// methods for testing and classification. Note that we may get POSIX-like
182183
// error codes back even from Windows remotes, but that indicates a POSIX

pkg/agent/transports/ssh/transport_test.go renamed to pkg/agent/transport/ssh/transport_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestCopy(t *testing.T) {
3636
}
3737

3838
// Create a transport.
39-
transport := &transport{
39+
transport := &sshTransport{
4040
user: user.Username,
4141
host: "localhost",
4242
port: 22,
@@ -86,7 +86,7 @@ func TestCommandOutput(t *testing.T) {
8686
}
8787

8888
// Create a transport.
89-
transport := &transport{
89+
transport := &sshTransport{
9090
user: user.Username,
9191
host: "localhost",
9292
port: 22,

pkg/agent/transports/doc.go

-2
This file was deleted.

pkg/forwarding/protocols/docker/protocol.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net"
88

99
"github.com/mutagen-io/mutagen/pkg/agent"
10-
"github.com/mutagen-io/mutagen/pkg/agent/transports/docker"
10+
"github.com/mutagen-io/mutagen/pkg/agent/transport/docker"
1111
"github.com/mutagen-io/mutagen/pkg/forwarding"
1212
"github.com/mutagen-io/mutagen/pkg/forwarding/endpoint/remote"
1313
"github.com/mutagen-io/mutagen/pkg/logging"

pkg/forwarding/protocols/ssh/protocol.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net"
88

99
"github.com/mutagen-io/mutagen/pkg/agent"
10-
"github.com/mutagen-io/mutagen/pkg/agent/transports/ssh"
10+
"github.com/mutagen-io/mutagen/pkg/agent/transport/ssh"
1111
"github.com/mutagen-io/mutagen/pkg/forwarding"
1212
"github.com/mutagen-io/mutagen/pkg/forwarding/endpoint/remote"
1313
"github.com/mutagen-io/mutagen/pkg/logging"

pkg/process/attributes_test.go

-11
This file was deleted.

pkg/process/attributes_windows.go

-21
This file was deleted.

pkg/synchronization/protocols/docker/protocol.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net"
88

99
"github.com/mutagen-io/mutagen/pkg/agent"
10-
"github.com/mutagen-io/mutagen/pkg/agent/transports/docker"
10+
"github.com/mutagen-io/mutagen/pkg/agent/transport/docker"
1111
"github.com/mutagen-io/mutagen/pkg/logging"
1212
"github.com/mutagen-io/mutagen/pkg/synchronization"
1313
"github.com/mutagen-io/mutagen/pkg/synchronization/endpoint/remote"

pkg/synchronization/protocols/ssh/protocol.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net"
88

99
"github.com/mutagen-io/mutagen/pkg/agent"
10-
"github.com/mutagen-io/mutagen/pkg/agent/transports/ssh"
10+
"github.com/mutagen-io/mutagen/pkg/agent/transport/ssh"
1111
"github.com/mutagen-io/mutagen/pkg/logging"
1212
"github.com/mutagen-io/mutagen/pkg/synchronization"
1313
"github.com/mutagen-io/mutagen/pkg/synchronization/endpoint/remote"

0 commit comments

Comments
 (0)