diff --git a/src/pkg/net/fd_poll_unix.go b/src/pkg/net/fd_poll_unix.go index e763c7e4d3e..dd1bc104afc 100644 --- a/src/pkg/net/fd_poll_unix.go +++ b/src/pkg/net/fd_poll_unix.go @@ -351,20 +351,29 @@ func (pd *pollDesc) Init(fd *netFD) error { return nil } -// TODO(dfc) these unused error returns could be removed - func (fd *netFD) setDeadline(t time.Time) error { - fd.setReadDeadline(t) - fd.setWriteDeadline(t) - return nil + return setDeadlineImpl(fd, t, true, true) } func (fd *netFD) setReadDeadline(t time.Time) error { - fd.pd.rdeadline.setTime(t) - return nil + return setDeadlineImpl(fd, t, true, false) } func (fd *netFD) setWriteDeadline(t time.Time) error { - fd.pd.wdeadline.setTime(t) + return setDeadlineImpl(fd, t, false, true) +} + +func setDeadlineImpl(fd *netFD, t time.Time, read, write bool) error { + if err := fd.incref(); err != nil { + return err + } + defer fd.decref() + if read { + fd.pd.rdeadline.setTime(t) + } + if write { + fd.pd.wdeadline.setTime(t) + } + fd.pd.Wakeup() return nil } diff --git a/src/pkg/runtime/netpoll.goc b/src/pkg/runtime/netpoll.goc index da6929eed2e..3fb347c74fe 100644 --- a/src/pkg/runtime/netpoll.goc +++ b/src/pkg/runtime/netpoll.goc @@ -134,9 +134,13 @@ func runtime_pollWaitCanceled(pd *PollDesc, mode int) { } func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) { + G *rg, *wg; + runtime·lock(pd); - if(pd->closing) - goto ret; + if(pd->closing) { + runtime·unlock(pd); + return; + } pd->seq++; // invalidate current timers // Reset current timers. if(pd->rt.fv) { @@ -148,9 +152,8 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) { pd->wt.fv = nil; } // Setup new timers. - if(d != 0 && d <= runtime·nanotime()) { + if(d != 0 && d <= runtime·nanotime()) d = -1; - } if(mode == 'r' || mode == 'r'+'w') pd->rd = d; if(mode == 'w' || mode == 'r'+'w') @@ -180,8 +183,18 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) { runtime·addtimer(&pd->wt); } } -ret: + // If we set the new deadline in the past, unblock currently pending IO if any. + rg = nil; + wg = nil; + if(pd->rd < 0) + rg = netpollunblock(pd, 'r', false); + if(pd->wd < 0) + wg = netpollunblock(pd, 'w', false); runtime·unlock(pd); + if(rg) + runtime·ready(rg); + if(wg) + runtime·ready(wg); } func runtime_pollUnblock(pd *PollDesc) {