Support android compilation of ioselectors.
This commit is contained in:
parent
d6ab21eed5
commit
ac4ccc695f
2 changed files with 186 additions and 136 deletions
|
|
@ -31,7 +31,7 @@ const hasThreadSupport = compileOption("threads") and defined(threadsafe)
|
||||||
|
|
||||||
const supportedPlatform = defined(macosx) or defined(freebsd) or
|
const supportedPlatform = defined(macosx) or defined(freebsd) or
|
||||||
defined(netbsd) or defined(openbsd) or
|
defined(netbsd) or defined(openbsd) or
|
||||||
defined(linux)
|
(defined(linux) and not defined(android))
|
||||||
|
|
||||||
const bsdPlatform = defined(macosx) or defined(freebsd) or
|
const bsdPlatform = defined(macosx) or defined(freebsd) or
|
||||||
defined(netbsd) or defined(openbsd)
|
defined(netbsd) or defined(openbsd)
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,29 @@ import posix, times
|
||||||
# Maximum number of events that can be returned
|
# Maximum number of events that can be returned
|
||||||
const MAX_EPOLL_RESULT_EVENTS = 64
|
const MAX_EPOLL_RESULT_EVENTS = 64
|
||||||
|
|
||||||
type
|
when not defined(android):
|
||||||
SignalFdInfo* {.importc: "struct signalfd_siginfo",
|
type
|
||||||
header: "<sys/signalfd.h>", pure, final.} = object
|
SignalFdInfo* {.importc: "struct signalfd_siginfo",
|
||||||
ssi_signo*: uint32
|
header: "<sys/signalfd.h>", pure, final.} = object
|
||||||
ssi_errno*: int32
|
ssi_signo*: uint32
|
||||||
ssi_code*: int32
|
ssi_errno*: int32
|
||||||
ssi_pid*: uint32
|
ssi_code*: int32
|
||||||
ssi_uid*: uint32
|
ssi_pid*: uint32
|
||||||
ssi_fd*: int32
|
ssi_uid*: uint32
|
||||||
ssi_tid*: uint32
|
ssi_fd*: int32
|
||||||
ssi_band*: uint32
|
ssi_tid*: uint32
|
||||||
ssi_overrun*: uint32
|
ssi_band*: uint32
|
||||||
ssi_trapno*: uint32
|
ssi_overrun*: uint32
|
||||||
ssi_status*: int32
|
ssi_trapno*: uint32
|
||||||
ssi_int*: int32
|
ssi_status*: int32
|
||||||
ssi_ptr*: uint64
|
ssi_int*: int32
|
||||||
ssi_utime*: uint64
|
ssi_ptr*: uint64
|
||||||
ssi_stime*: uint64
|
ssi_utime*: uint64
|
||||||
ssi_addr*: uint64
|
ssi_stime*: uint64
|
||||||
pad* {.importc: "__pad".}: array[0..47, uint8]
|
ssi_addr*: uint64
|
||||||
|
pad* {.importc: "__pad".}: array[0..47, uint8]
|
||||||
|
|
||||||
|
type
|
||||||
eventFdData {.importc: "eventfd_t",
|
eventFdData {.importc: "eventfd_t",
|
||||||
header: "<sys/eventfd.h>", pure, final.} = uint64
|
header: "<sys/eventfd.h>", pure, final.} = uint64
|
||||||
epoll_data {.importc: "union epoll_data", header: "<sys/epoll.h>",
|
epoll_data {.importc: "union epoll_data", header: "<sys/epoll.h>",
|
||||||
|
|
@ -68,12 +70,22 @@ proc timerfd_create(clock_id: ClockId, flags: cint): cint
|
||||||
proc timerfd_settime(ufd: cint, flags: cint,
|
proc timerfd_settime(ufd: cint, flags: cint,
|
||||||
utmr: var Itimerspec, otmr: var Itimerspec): cint
|
utmr: var Itimerspec, otmr: var Itimerspec): cint
|
||||||
{.cdecl, importc: "timerfd_settime", header: "<sys/timerfd.h>".}
|
{.cdecl, importc: "timerfd_settime", header: "<sys/timerfd.h>".}
|
||||||
proc signalfd(fd: cint, mask: var Sigset, flags: cint): cint
|
|
||||||
{.cdecl, importc: "signalfd", header: "<sys/signalfd.h>".}
|
|
||||||
proc eventfd(count: cuint, flags: cint): cint
|
proc eventfd(count: cuint, flags: cint): cint
|
||||||
{.cdecl, importc: "eventfd", header: "<sys/eventfd.h>".}
|
{.cdecl, importc: "eventfd", header: "<sys/eventfd.h>".}
|
||||||
proc ulimit(cmd: cint): clong
|
|
||||||
{.importc: "ulimit", header: "<ulimit.h>", varargs.}
|
when not defined(android):
|
||||||
|
proc signalfd(fd: cint, mask: var Sigset, flags: cint): cint
|
||||||
|
{.cdecl, importc: "signalfd", header: "<sys/signalfd.h>".}
|
||||||
|
|
||||||
|
var RLIMIT_NOFILE {.importc: "RLIMIT_NOFILE",
|
||||||
|
header: "<sys/resource.h>".}: cint
|
||||||
|
type
|
||||||
|
rlimit {.importc: "struct rlimit",
|
||||||
|
header: "<sys/resource.h>", pure, final.} = object
|
||||||
|
rlim_cur: int
|
||||||
|
rlim_max: int
|
||||||
|
proc getrlimit(resource: cint, rlp: var rlimit): cint
|
||||||
|
{.importc: "getrlimit",header: "<sys/resource.h>".}
|
||||||
|
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
type
|
type
|
||||||
|
|
@ -97,7 +109,10 @@ type
|
||||||
SelectEvent* = ptr SelectEventImpl
|
SelectEvent* = ptr SelectEventImpl
|
||||||
|
|
||||||
proc newSelector*[T](): Selector[T] =
|
proc newSelector*[T](): Selector[T] =
|
||||||
var maxFD = int(ulimit(4, 0))
|
var a = rlimit()
|
||||||
|
if getrlimit(RLIMIT_NOFILE, a) != 0:
|
||||||
|
raiseOsError(osLastError())
|
||||||
|
var maxFD = int(a.rlim_max)
|
||||||
doAssert(maxFD > 0)
|
doAssert(maxFD > 0)
|
||||||
|
|
||||||
var epollFD = epoll_create(MAX_EPOLL_RESULT_EVENTS)
|
var epollFD = epoll_create(MAX_EPOLL_RESULT_EVENTS)
|
||||||
|
|
@ -194,39 +209,53 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
|
||||||
doAssert(pkey.ident != 0)
|
doAssert(pkey.ident != 0)
|
||||||
|
|
||||||
if pkey.events != {}:
|
if pkey.events != {}:
|
||||||
if pkey.events * {Event.Read, Event.Write} != {}:
|
when not defined(android):
|
||||||
var epv = epoll_event()
|
if pkey.events * {Event.Read, Event.Write} != {}:
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
var epv = epoll_event()
|
||||||
raiseOSError(osLastError())
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
dec(s.count)
|
raiseOSError(osLastError())
|
||||||
elif Event.Timer in pkey.events:
|
dec(s.count)
|
||||||
var epv = epoll_event()
|
elif Event.Timer in pkey.events:
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
var epv = epoll_event()
|
||||||
raiseOSError(osLastError())
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
discard posix.close(fdi.cint)
|
raiseOSError(osLastError())
|
||||||
dec(s.count)
|
discard posix.close(fdi.cint)
|
||||||
elif Event.Signal in pkey.events:
|
dec(s.count)
|
||||||
var epv = epoll_event()
|
elif Event.Signal in pkey.events:
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
var epv = epoll_event()
|
||||||
raiseOSError(osLastError())
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
var nmask, omask: Sigset
|
raiseOSError(osLastError())
|
||||||
discard sigemptyset(nmask)
|
var nmask, omask: Sigset
|
||||||
discard sigemptyset(omask)
|
discard sigemptyset(nmask)
|
||||||
discard sigaddset(nmask, cint(s.fds[fdi].param))
|
discard sigemptyset(omask)
|
||||||
unblockSignals(nmask, omask)
|
discard sigaddset(nmask, cint(s.fds[fdi].param))
|
||||||
discard posix.close(fdi.cint)
|
unblockSignals(nmask, omask)
|
||||||
dec(s.count)
|
discard posix.close(fdi.cint)
|
||||||
elif Event.Process in pkey.events:
|
dec(s.count)
|
||||||
var epv = epoll_event()
|
elif Event.Process in pkey.events:
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
var epv = epoll_event()
|
||||||
raiseOSError(osLastError())
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
var nmask, omask: Sigset
|
raiseOSError(osLastError())
|
||||||
discard sigemptyset(nmask)
|
var nmask, omask: Sigset
|
||||||
discard sigemptyset(omask)
|
discard sigemptyset(nmask)
|
||||||
discard sigaddset(nmask, SIGCHLD)
|
discard sigemptyset(omask)
|
||||||
unblockSignals(nmask, omask)
|
discard sigaddset(nmask, SIGCHLD)
|
||||||
discard posix.close(fdi.cint)
|
unblockSignals(nmask, omask)
|
||||||
dec(s.count)
|
discard posix.close(fdi.cint)
|
||||||
|
dec(s.count)
|
||||||
|
else:
|
||||||
|
if pkey.events * {Event.Read, Event.Write} != {}:
|
||||||
|
var epv = epoll_event()
|
||||||
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
dec(s.count)
|
||||||
|
elif Event.Timer in pkey.events:
|
||||||
|
var epv = epoll_event()
|
||||||
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
discard posix.close(fdi.cint)
|
||||||
|
dec(s.count)
|
||||||
|
|
||||||
pkey.ident = 0
|
pkey.ident = 0
|
||||||
pkey.events = {}
|
pkey.events = {}
|
||||||
|
|
||||||
|
|
@ -280,60 +309,61 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
|
||||||
inc(s.count)
|
inc(s.count)
|
||||||
result = fdi
|
result = fdi
|
||||||
|
|
||||||
proc registerSignal*[T](s: Selector[T], signal: int,
|
when not defined(android):
|
||||||
data: T): int {.discardable.} =
|
proc registerSignal*[T](s: Selector[T], signal: int,
|
||||||
var
|
data: T): int {.discardable.} =
|
||||||
nmask: Sigset
|
var
|
||||||
omask: Sigset
|
nmask: Sigset
|
||||||
|
omask: Sigset
|
||||||
|
|
||||||
discard sigemptyset(nmask)
|
discard sigemptyset(nmask)
|
||||||
discard sigemptyset(omask)
|
discard sigemptyset(omask)
|
||||||
discard sigaddset(nmask, cint(signal))
|
discard sigaddset(nmask, cint(signal))
|
||||||
blockSignals(nmask, omask)
|
blockSignals(nmask, omask)
|
||||||
|
|
||||||
let fdi = signalfd(-1, nmask, 0).int
|
let fdi = signalfd(-1, nmask, 0).int
|
||||||
if fdi == -1:
|
if fdi == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
setNonBlocking(fdi.cint)
|
setNonBlocking(fdi.cint)
|
||||||
|
|
||||||
s.checkFd(fdi)
|
s.checkFd(fdi)
|
||||||
doAssert(s.fds[fdi].ident == 0)
|
doAssert(s.fds[fdi].ident == 0)
|
||||||
|
|
||||||
var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
|
var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
|
||||||
epv.data.u64 = fdi.uint
|
epv.data.u64 = fdi.uint
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
|
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
s.setKey(fdi, signal, {Event.Signal}, signal, data)
|
s.setKey(fdi, signal, {Event.Signal}, signal, data)
|
||||||
inc(s.count)
|
inc(s.count)
|
||||||
result = fdi
|
result = fdi
|
||||||
|
|
||||||
proc registerProcess*[T](s: Selector, pid: int,
|
proc registerProcess*[T](s: Selector, pid: int,
|
||||||
data: T): int {.discardable.} =
|
data: T): int {.discardable.} =
|
||||||
var
|
var
|
||||||
nmask: Sigset
|
nmask: Sigset
|
||||||
omask: Sigset
|
omask: Sigset
|
||||||
|
|
||||||
discard sigemptyset(nmask)
|
discard sigemptyset(nmask)
|
||||||
discard sigemptyset(omask)
|
discard sigemptyset(omask)
|
||||||
discard sigaddset(nmask, posix.SIGCHLD)
|
discard sigaddset(nmask, posix.SIGCHLD)
|
||||||
blockSignals(nmask, omask)
|
blockSignals(nmask, omask)
|
||||||
|
|
||||||
let fdi = signalfd(-1, nmask, 0).int
|
let fdi = signalfd(-1, nmask, 0).int
|
||||||
if fdi == -1:
|
if fdi == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
setNonBlocking(fdi.cint)
|
setNonBlocking(fdi.cint)
|
||||||
|
|
||||||
s.checkFd(fdi)
|
s.checkFd(fdi)
|
||||||
doAssert(s.fds[fdi].ident == 0)
|
doAssert(s.fds[fdi].ident == 0)
|
||||||
|
|
||||||
var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
|
var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
|
||||||
epv.data.u64 = fdi.uint
|
epv.data.u64 = fdi.uint
|
||||||
epv.events = EPOLLIN or EPOLLRDHUP
|
epv.events = EPOLLIN or EPOLLRDHUP
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
|
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
s.setKey(fdi, pid, {Event.Process, Event.Oneshot}, pid, data)
|
s.setKey(fdi, pid, {Event.Process, Event.Oneshot}, pid, data)
|
||||||
inc(s.count)
|
inc(s.count)
|
||||||
result = fdi
|
result = fdi
|
||||||
|
|
||||||
proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
|
proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
|
||||||
let fdi = int(ev.efd)
|
let fdi = int(ev.efd)
|
||||||
|
|
@ -382,40 +412,60 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
||||||
events.incl(Event.Error)
|
events.incl(Event.Error)
|
||||||
if (pevents and EPOLLOUT) != 0:
|
if (pevents and EPOLLOUT) != 0:
|
||||||
events.incl(Event.Write)
|
events.incl(Event.Write)
|
||||||
if (pevents and EPOLLIN) != 0:
|
when not defined(android):
|
||||||
if Event.Read in skey.events:
|
if (pevents and EPOLLIN) != 0:
|
||||||
events.incl(Event.Read)
|
if Event.Read in skey.events:
|
||||||
elif Event.Timer in skey.events:
|
events.incl(Event.Read)
|
||||||
var data: uint64 = 0
|
elif Event.Timer in skey.events:
|
||||||
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
var data: uint64 = 0
|
||||||
raiseOSError(osLastError())
|
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||||
events = {Event.Timer}
|
raiseOSError(osLastError())
|
||||||
elif Event.Signal in skey.events:
|
events = {Event.Timer}
|
||||||
var data = SignalFdInfo()
|
elif Event.Signal in skey.events:
|
||||||
if posix.read(fdi.cint, addr data,
|
var data = SignalFdInfo()
|
||||||
sizeof(SignalFdInfo)) != sizeof(SignalFdInfo):
|
if posix.read(fdi.cint, addr data,
|
||||||
raiseOsError(osLastError())
|
sizeof(SignalFdInfo)) != sizeof(SignalFdInfo):
|
||||||
events = {Event.Signal}
|
raiseOsError(osLastError())
|
||||||
elif Event.Process in skey.events:
|
events = {Event.Signal}
|
||||||
var data = SignalFdInfo()
|
elif Event.Process in skey.events:
|
||||||
if posix.read(fdi.cint, addr data,
|
var data = SignalFdInfo()
|
||||||
sizeof(SignalFdInfo)) != sizeof(SignalFdInfo):
|
if posix.read(fdi.cint, addr data,
|
||||||
raiseOsError(osLastError())
|
sizeof(SignalFdInfo)) != sizeof(SignalFdInfo):
|
||||||
if cast[int](data.ssi_pid) == skey.param:
|
raiseOsError(osLastError())
|
||||||
events = {Event.Process}
|
if cast[int](data.ssi_pid) == skey.param:
|
||||||
else:
|
events = {Event.Process}
|
||||||
inc(i)
|
else:
|
||||||
continue
|
|
||||||
elif Event.User in skey.events:
|
|
||||||
var data: uint64 = 0
|
|
||||||
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
|
||||||
let err = osLastError()
|
|
||||||
if err == OSErrorCode(EAGAIN):
|
|
||||||
inc(i)
|
inc(i)
|
||||||
continue
|
continue
|
||||||
else:
|
elif Event.User in skey.events:
|
||||||
raiseOSError(err)
|
var data: uint64 = 0
|
||||||
events = {Event.User}
|
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||||
|
let err = osLastError()
|
||||||
|
if err == OSErrorCode(EAGAIN):
|
||||||
|
inc(i)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raiseOSError(err)
|
||||||
|
events = {Event.User}
|
||||||
|
else:
|
||||||
|
if (pevents and EPOLLIN) != 0:
|
||||||
|
if Event.Read in skey.events:
|
||||||
|
events.incl(Event.Read)
|
||||||
|
elif Event.Timer in skey.events:
|
||||||
|
var data: uint64 = 0
|
||||||
|
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
events = {Event.Timer}
|
||||||
|
elif Event.User in skey.events:
|
||||||
|
var data: uint64 = 0
|
||||||
|
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||||
|
let err = osLastError()
|
||||||
|
if err == OSErrorCode(EAGAIN):
|
||||||
|
inc(i)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raiseOSError(err)
|
||||||
|
events = {Event.User}
|
||||||
|
|
||||||
skey.key.events = events
|
skey.key.events = events
|
||||||
results[k] = skey.key
|
results[k] = skey.key
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue