Skip to content

Commit da4f6de

Browse files
committed
fixes #240 ipc problems with both permissions and path cleanups
This addresses possible problems with the clean up on some systems, as well as permissions. It makes use of the new errors facility in go 1.13, and thus go 1.13 or better is now required.
1 parent 863d237 commit da4f6de

File tree

1 file changed

+50
-57
lines changed

1 file changed

+50
-57
lines changed

transport/ipc/ipc_unix.go

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// +build !windows,!plan9,!js
22

3-
// Copyright 2020 The Mangos Authors
3+
// Copyright 2021 The Mangos Authors
44
//
55
// Licensed under the Apache License, Version 2.0 (the "License");
66
// you may not use file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
package ipc
2020

2121
import (
22+
"errors"
2223
"net"
2324
"os"
2425
"sync"
@@ -30,7 +31,7 @@ import (
3031
)
3132

3233
const (
33-
// Transport is a transport.Transport for IPC.
34+
// Transport implements IPC.
3435
Transport = ipcTran(0)
3536
)
3637

@@ -39,11 +40,11 @@ func init() {
3940
}
4041

4142
type dialer struct {
42-
addr *net.UnixAddr
43-
proto transport.ProtocolInfo
44-
hs transport.Handshaker
45-
maxRecvSize int
46-
lock sync.Mutex
43+
addr *net.UnixAddr
44+
proto transport.ProtocolInfo
45+
hs transport.Handshaker
46+
maxRcvSize int
47+
lock sync.Mutex
4748
}
4849

4950
// Dial implements the Dialer Dial method
@@ -55,7 +56,7 @@ func (d *dialer) Dial() (transport.Pipe, error) {
5556
}
5657
p := transport.NewConnPipeIPC(conn, d.proto)
5758
d.lock.Lock()
58-
p.SetOption(mangos.OptionMaxRecvSize, d.maxRecvSize)
59+
p.SetOption(mangos.OptionMaxRecvSize, d.maxRcvSize)
5960
getPeer(conn, p)
6061
d.lock.Unlock()
6162
d.hs.Start(p)
@@ -70,7 +71,7 @@ func (d *dialer) SetOption(n string, v interface{}) error {
7071
switch n {
7172
case mangos.OptionMaxRecvSize:
7273
if b, ok := v.(int); ok {
73-
d.maxRecvSize = b
74+
d.maxRcvSize = b
7475
return nil
7576
}
7677
return mangos.ErrBadValue
@@ -85,26 +86,26 @@ func (d *dialer) GetOption(n string) (interface{}, error) {
8586

8687
switch n {
8788
case mangos.OptionMaxRecvSize:
88-
return d.maxRecvSize, nil
89+
return d.maxRcvSize, nil
8990
}
9091
return nil, mangos.ErrBadOption
9192
}
9293

9394
type listener struct {
94-
addr *net.UnixAddr
95-
proto transport.ProtocolInfo
96-
listener *net.UnixListener
97-
hs transport.Handshaker
98-
closeq chan struct{}
99-
closed bool
100-
maxRecvSize int
101-
owner int
102-
group int
103-
chown bool
104-
mode uint32
105-
chmod bool
106-
once sync.Once
107-
lock sync.Mutex
95+
addr *net.UnixAddr
96+
proto transport.ProtocolInfo
97+
listener *net.UnixListener
98+
hs transport.Handshaker
99+
closeQ chan struct{}
100+
closed bool
101+
maxRcvSize int
102+
owner int
103+
group int
104+
chown bool
105+
mode uint32
106+
chmod bool
107+
once sync.Once
108+
lock sync.Mutex
108109
}
109110

110111
// Listen implements the PipeListener Listen method.
@@ -113,20 +114,12 @@ func (l *listener) Listen() error {
113114
defer l.lock.Unlock()
114115

115116
select {
116-
case <-l.closeq:
117+
case <-l.closeQ:
117118
return mangos.ErrClosed
118119
default:
119120
}
120121
listener, err := net.ListenUnix("unix", l.addr)
121122

122-
if l.chown {
123-
os.Chown(l.addr.String(), l.owner, l.group)
124-
125-
}
126-
if l.chmod {
127-
os.Chmod(l.addr.String(), os.FileMode(l.mode))
128-
}
129-
130123
if err != nil && (isSyscallError(err, syscall.EADDRINUSE) || isSyscallError(err, syscall.EEXIST)) {
131124
l.removeStaleIPC()
132125
listener, err = net.ListenUnix("unix", l.addr)
@@ -137,21 +130,31 @@ func (l *listener) Listen() error {
137130
if err != nil {
138131
return err
139132
}
133+
134+
// Best effort to update permissions -- note that this can fail for various reasons,
135+
// and it is unadvisable to rely too strongly upon it. (It isn't portable at least.)
136+
if l.chown {
137+
_ = os.Chown(l.addr.String(), l.owner, l.group)
138+
}
139+
if l.chmod {
140+
_ = os.Chmod(l.addr.String(), os.FileMode(l.mode))
141+
}
142+
140143
l.listener = listener
141144
go func() {
142145
for {
143146
conn, err := l.listener.AcceptUnix()
144147
if err != nil {
145148
select {
146-
case <-l.closeq:
149+
case <-l.closeQ:
147150
return
148151
default:
149152
continue
150153
}
151154
}
152155
p := transport.NewConnPipeIPC(conn, l.proto)
153156
l.lock.Lock()
154-
p.SetOption(mangos.OptionMaxRecvSize, l.maxRecvSize)
157+
p.SetOption(mangos.OptionMaxRecvSize, l.maxRcvSize)
155158
getPeer(conn, p)
156159
l.lock.Unlock()
157160
l.hs.Start(p)
@@ -164,7 +167,7 @@ func (l *listener) Address() string {
164167
return "ipc://" + l.addr.String()
165168
}
166169

167-
// Accept implements the the PipeListener Accept method.
170+
// Accept implements the PipeListener Accept method.
168171
func (l *listener) Accept() (transport.Pipe, error) {
169172
l.lock.Lock()
170173
if l.listener == nil {
@@ -181,10 +184,10 @@ func (l *listener) Close() error {
181184
l.lock.Lock()
182185
l.closed = true
183186
if l.listener != nil {
184-
l.listener.Close()
187+
_ = l.listener.Close()
185188
}
186189
l.hs.Close()
187-
close(l.closeq)
190+
close(l.closeQ)
188191
l.lock.Unlock()
189192
})
190193
return nil
@@ -198,7 +201,7 @@ func (l *listener) SetOption(n string, v interface{}) error {
198201
switch n {
199202
case mangos.OptionMaxRecvSize:
200203
if b, ok := v.(int); ok {
201-
l.maxRecvSize = b
204+
l.maxRcvSize = b
202205
return nil
203206
}
204207
return mangos.ErrBadValue
@@ -240,7 +243,7 @@ func (l *listener) GetOption(n string) (interface{}, error) {
240243

241244
switch n {
242245
case mangos.OptionMaxRecvSize:
243-
return l.maxRecvSize, nil
246+
return l.maxRcvSize, nil
244247
}
245248
return nil, mangos.ErrBadOption
246249
}
@@ -253,11 +256,11 @@ func (l *listener) removeStaleIPC() {
253256
}
254257
conn, err := net.DialTimeout("unix", l.addr.String(), 100*time.Millisecond)
255258
if err != nil && isSyscallError(err, syscall.ECONNREFUSED) {
256-
os.Remove(l.addr.String())
259+
_ = os.Remove(l.addr.String())
257260
return
258261
}
259262
if err == nil {
260-
conn.Close()
263+
_ = conn.Close()
261264
}
262265
}
263266

@@ -291,7 +294,7 @@ func (t ipcTran) NewListener(addr string, sock mangos.Socket) (transport.Listene
291294
var err error
292295
l := &listener{
293296
proto: sock.Info(),
294-
closeq: make(chan struct{}),
297+
closeQ: make(chan struct{}),
295298
hs: transport.NewConnHandshaker(),
296299
owner: os.Geteuid(),
297300
group: os.Getegid(),
@@ -307,20 +310,10 @@ func (t ipcTran) NewListener(addr string, sock mangos.Socket) (transport.Listene
307310
}
308311

309312
func isSyscallError(err error, code syscall.Errno) bool {
310-
opErr, ok := err.(*net.OpError)
311-
if !ok {
312-
return false
313-
}
314-
syscallErr, ok := opErr.Err.(*os.SyscallError)
315-
if !ok {
316-
return false
317-
}
318-
errno, ok := syscallErr.Err.(syscall.Errno)
319-
if !ok {
320-
return false
321-
}
322-
if errno == code {
323-
return true
313+
314+
var errno syscall.Errno
315+
if errors.As(err, &errno) {
316+
return errno == code
324317
}
325318
return false
326319
}

0 commit comments

Comments
 (0)