-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HttpBeast random segfault on orc and threads > 1 #21422
Comments
I also just ran into this today. Unfortunately it makes Jester not work on latest devel which is quite bad. |
Also in the process of upgrading my code to 1.6.12 before the 2.0 release, but all code using |
reduced import selectors, net, nativesockets, os, posix
from osproc import countProcessors
type
Data = object
type
Ref = ref object
Settings* = object
port*: Port
bindAddr*: string
domain*: Domain
numThreads*: int
loggers*: seq[Ref]
HttpBeastDefect* = ref object of Defect
proc initSettings*(port: Port = Port(8080),
bindAddr: string = "",
numThreads: int = 0,
domain = Domain.AF_INET,
): Settings =
Settings(
port: port,
bindAddr: bindAddr,
domain: domain,
numThreads: numThreads,
loggers: @[Ref()],
)
proc eventLoop(
params: tuple[settings: Settings, isMainThread: bool]
) =
let (settings, isMainThread) = params
echo settings.domain
let selector = newSelector[Data]()
proc run*(settings: Settings) =
when compileOption("threads"):
let numThreads =
if settings.numThreads == 0: countProcessors()
else: settings.numThreads
else:
let numThreads = 1
echo("Starting ", numThreads, " threads")
if numThreads > 1:
when compileOption("threads"):
var threads = newSeq[Thread[(Settings, bool)]](numThreads - 1)
for t in threads.mitems():
createThread[(Settings, bool)](
t, eventLoop, (settings, false)
)
else:
assert false
echo("Listening on port ", settings.port) # This line is used in the tester to signal readiness.
eventLoop((settings, true))
run(initSettings(numThreads=2)) |
Assuming that's a faithful reproduction this is not a Nim problem. The following program ran with import selectors, net, nativesockets, os, posix
from osproc import countProcessors
type
Data = object
type
Ref = ref object
Settings* = object
val: Ref
proc eventLoop(
settings: Settings
) =
let settings = settings # Copy value so destructor kicks in
echo cast[int](settings.val)
let selector = newSelector[Data]()
proc run*(settings: Settings) =
for x in 0 .. 100:
let numThreads = 2
if paramCount() == 1 and paramStr(1) == "fail":
if numThreads > 1:
var threads = newSeq[Thread[Settings]](numThreads - 1)
for t in threads.mitems():
createThread[Settings](
t, eventLoop, settings
)
echo "main loop start"
eventLoop(settings)
else:
var threads: seq[Thread[Settings]]
if numThreads > 1:
threads = newSeq[Thread[Settings]](numThreads - 1)
for t in threads.mitems():
createThread[Settings](
t, eventLoop, settings
)
echo "main loop start"
eventLoop(settings)
joinThreads(threads)
run(Settings(val: Ref())) |
It seems that my reduce is not good enough. |
I don't think it's right way for httpbeast to work with threads in ORC. It should implement a startup event so that Logger can be initialized each thread without passing refs between threads. It works for my fork => https://github.com/ringabout/httpx/blob/a3a2a9f65ac6fb3a3153e5379d561d99079e0402/src/httpx.nim#L529 # hello.nim
import options, asyncdispatch, logging
import httpx
proc onRequest(req: Request): Future[void] =
logging.debug "fine"
if req.httpMethod == some(HttpGet):
case req.path.get()
of "/":
req.send("Hello World")
else:
req.send(Http404)
proc startup() =
if logging.getHandlers().len == 0:
addHandler(logging.newConsoleLogger())
addHandler(logging.newConsoleLogger())
run(onRequest, initSettings(numThreads=2, startup=startup)) |
I'm still able to produre I have tried to with split screen between httpbeast and httpx and commented out one line at the time but with no helpful outcome :| . I have also tested httpx, but I never got it to fail like httpbeast.. |
All of them? You need to comment addHandler in the eventloop function. |
Yes:
Test
Output
|
Weird, I will try again later. |
I confirmed @beef331 's solution works, and my thought is the issue because httpbeast use eventLoop in main thread keep threads not cancel, when server stoped, the threads suddenly destroyed and related resource not properly free. I push a patch merged seem worked out. |
Description
Original issue was posted here dom96/httpbeast#80.
This bug arises when adding new logging handler in httpbeast application that's using orc and threads more than 1. Below is the minimal code that could reproduce the issue (taken from httpbeast example with only addition being
addHandler
).I've tried replicating this by implementing httpbeast
Settings
object flow, which is being passed between 2 threads that I thought was the root cause, but it didn't give segfault. So far, I'm only able to replicate the bug when adding newConsoleLogger
in httpbeast applications, which also affects jester as well.Nim Version
Latest nightlies for
linux_x64
downloaded here https://github.com/nim-lang/nightlies/releases/tag/latest-version-2-0Also tested on Nim release
1.6.8
Current Output
Expected Output
Possible Solution
I found that I can solve the issue by commenting this block of code. Other workaround that I did was modifying
Settings.loggers
toref seq[Logger]
, which also removes the random segfault.https://github.com/dom96/httpbeast/blob/0f7b07f00e4c90eceef90e27da6e997a111407cc/src/httpbeast.nim#L336-L339
Additional Information
0.4.1
The text was updated successfully, but these errors were encountered: