imap: fix panic when sending multiple connect cmds
fixes the panic when the user sends multiple connect commands and is already connected. The panic is caused by closing an already closed channel. This happens when the idle re-init code is not executed, e.g. when there's a return statement in the switch block. A defer func() before the switch block will prevent this. The existing behavior of only creating a new idleStop channel when properly connected is preseverd. Signed-off-by: Koni Marti <koni.marti@gmail.com>
This commit is contained in:
parent
f81d8871c7
commit
022bf1a11f
1 changed files with 26 additions and 15 deletions
|
@ -74,6 +74,14 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
w.worker.PostMessage(&types.Error{Error: err}, nil)
|
w.worker.PostMessage(&types.Error{Error: err}, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if w.client != nil && w.client.State() == imap.SelectedState {
|
||||||
|
w.idleStop = make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
w.idleDone <- w.client.Idle(w.idleStop, &client.IdleOptions{0, 0})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
var reterr error // will be returned at the end, needed to support idle
|
var reterr error // will be returned at the end, needed to support idle
|
||||||
|
|
||||||
|
@ -83,7 +91,8 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
case *types.Configure:
|
case *types.Configure:
|
||||||
u, err := url.Parse(msg.Config.Source)
|
u, err := url.Parse(msg.Config.Source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
reterr = err
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
w.config.scheme = u.Scheme
|
w.config.scheme = u.Scheme
|
||||||
|
@ -123,44 +132,50 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
case "connection-timeout":
|
case "connection-timeout":
|
||||||
val, err := time.ParseDuration(value)
|
val, err := time.ParseDuration(value)
|
||||||
if err != nil || val < 0 {
|
if err != nil || val < 0 {
|
||||||
return fmt.Errorf(
|
reterr = fmt.Errorf(
|
||||||
"invalid connection-timeout value %v: %v",
|
"invalid connection-timeout value %v: %v",
|
||||||
value, err)
|
value, err)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
w.config.connection_timeout = val
|
w.config.connection_timeout = val
|
||||||
case "keepalive-period":
|
case "keepalive-period":
|
||||||
val, err := time.ParseDuration(value)
|
val, err := time.ParseDuration(value)
|
||||||
if err != nil || val < 0 {
|
if err != nil || val < 0 {
|
||||||
return fmt.Errorf(
|
reterr = fmt.Errorf(
|
||||||
"invalid keepalive-period value %v: %v",
|
"invalid keepalive-period value %v: %v",
|
||||||
value, err)
|
value, err)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
w.config.keepalive_period = val
|
w.config.keepalive_period = val
|
||||||
case "keepalive-probes":
|
case "keepalive-probes":
|
||||||
val, err := strconv.Atoi(value)
|
val, err := strconv.Atoi(value)
|
||||||
if err != nil || val < 0 {
|
if err != nil || val < 0 {
|
||||||
return fmt.Errorf(
|
reterr = fmt.Errorf(
|
||||||
"invalid keepalive-probes value %v: %v",
|
"invalid keepalive-probes value %v: %v",
|
||||||
value, err)
|
value, err)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
w.config.keepalive_probes = val
|
w.config.keepalive_probes = val
|
||||||
case "keepalive-interval":
|
case "keepalive-interval":
|
||||||
val, err := time.ParseDuration(value)
|
val, err := time.ParseDuration(value)
|
||||||
if err != nil || val < 0 {
|
if err != nil || val < 0 {
|
||||||
return fmt.Errorf(
|
reterr = fmt.Errorf(
|
||||||
"invalid keepalive-interval value %v: %v",
|
"invalid keepalive-interval value %v: %v",
|
||||||
value, err)
|
value, err)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
w.config.keepalive_interval = int(val.Seconds())
|
w.config.keepalive_interval = int(val.Seconds())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *types.Connect:
|
case *types.Connect:
|
||||||
if w.client != nil && w.client.State() == imap.SelectedState {
|
if w.client != nil && w.client.State() == imap.SelectedState {
|
||||||
return fmt.Errorf("Already connected")
|
reterr = fmt.Errorf("Already connected")
|
||||||
|
break
|
||||||
}
|
}
|
||||||
c, err := w.connect()
|
c, err := w.connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
reterr = err
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Updates = w.updates
|
c.Updates = w.updates
|
||||||
|
@ -168,10 +183,12 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
||||||
case *types.Disconnect:
|
case *types.Disconnect:
|
||||||
if w.client == nil || w.client.State() != imap.SelectedState {
|
if w.client == nil || w.client.State() != imap.SelectedState {
|
||||||
return fmt.Errorf("Not connected")
|
reterr = fmt.Errorf("Not connected")
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if err := w.client.Logout(); err != nil {
|
if err := w.client.Logout(); err != nil {
|
||||||
return err
|
reterr = err
|
||||||
|
break
|
||||||
}
|
}
|
||||||
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
|
||||||
case *types.ListDirectories:
|
case *types.ListDirectories:
|
||||||
|
@ -208,12 +225,6 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
reterr = errUnsupported
|
reterr = errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.client != nil && w.client.State() == imap.SelectedState {
|
|
||||||
w.idleStop = make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
w.idleDone <- w.client.Idle(w.idleStop, &client.IdleOptions{0, 0})
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
return reterr
|
return reterr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue