snapframework / snap-server Goto Github PK
View Code? Open in Web Editor NEWA fast HTTP server library, which runs Snap web handlers.
Home Page: http://snapframework.com/
License: BSD 3-Clause "New" or "Revised" License
A fast HTTP server library, which runs Snap web handlers.
Home Page: http://snapframework.com/
License: BSD 3-Clause "New" or "Revised" License
The underlying problem is that setenv is not thread safe as simultaneous call to getenv in multithreaded enviroment might lead to segmentation fault by attempting to dereference a null pointer (relevant glibc ticket).
Considering that snap is usually started in a separate thread, this creates a serious issue, because a wide variety of functions call getenv internally (see above ticket for more info).
I personally encountered this problem when using ekg (which uses snap internally).
To be fair, I'm not sure why locale is set there to begin with.
I have been reading through the code and I am pretty sure that I need to override the logA method in order to get custom logging support. I asked a question on SO about it just in case.
But I don't think that I can currently override this logA functionality without changing the code inside of Snap Server. If this is correct then, for this issue, it would be great if I could inject a method into the snap server configuration that would intercept the access log generation and let me write my own access log lines in a custom format.
If I start the server with a config where only the unix path is set, it automatically starts listening on the default TCP port (no port specified, defaulting to port 8000
). This is an issue for me. I start potentially many servers, each listens on a unique unix socket. There is no way to reliably start them all without also allocating an unused TCP port for each one.
Building 1.1.1.0:
[19 of 20] Compiling Snap.Internal.Http.Server.Socket ( src/Snap/Internal/Http/Server/Socket.hs, dist/build/Snap/Internal/Http/Server/Socket.o )
src/Snap/Internal/Http/Server/Socket.hs:176:5: error:
Conflicting definitions for ‘acquire’
Bound at: src/Snap/Internal/Http/Server/Socket.hs:176:5-11
src/Snap/Internal/Http/Server/Socket.hs:182:5-11
|
176 | acquire = openFd fPath ReadOnly Nothing defaultFileFlags
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
After switching to snap-server-1.0.1.1
from snap-server-0.9.5.1
, I see huge and increasing memory usage. It seems to be related to time manager retaining threads forever.
register
adds thread object to a list. It seems that cancel
should be used to remove it from the list, but I didn't find where it is called. So I added it as a cleanup here. Also, cancel
it not exception safe (e.g. T.cancel
may fail, then writeIORef
will not be called), so I guarded writeIORef
with finally
. Now my memory usage issue seems to be solved.
Several frontend servers I know of (haproxy, stud, Amazon ELBs, nginx) speak it.
See http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt.
The current version of network is 2.6.0.2,
my package depends on snap-server + pandoc-1.13.1 which needs network >=2.6
Using System.Console.GetOpt is problematic.
Error reporting from it is real pain.
I think snap should switch to one of the applicative/monadic option parsers instead.
One of the bad things in snap-server config is --proxy options, which uses error
to report errors, and since that value is actually evaluated in other place, server just dies without error message because at that space it eats all exceptions. (Also, eating all exceptions is bad)
Of course it's a breaking change for people who added custom options, but I'm sure everyone will be glad to get rid of GetOpt :)
"An iteratee-based HTTP server library, which runs Snap web handlers"
I don't see no iteratees anywhere ;)
Following the instructions here:
http://snapframework.com/faq#how-do-i-enable-ssl
-Rebuilt snap-server with the -fopenssl flag:
cabal install snap snap-server -fopenssl --reinstall
-Generated a key/certificate:
openssl req -x509 -newkey -keyout key.pem -out cert.pem -days 1000
-Running with that key/certificate: (not root at the moment, so non-standard port)
src/Main --ssl-port=8443 --ssl-cert=cert.pem --ssl-key=key.pem
Snap prints the same information messages to the terminal as normal:
Listening on https://0.0.0.0:8443/
^C
Shutting down...
Site works as normal with SSL off, but with SSL on the connection is reset on requesting a page. Nothing is printed to the terminal, but in /log/error.log I see:
[03/Jul/2014:09:24:40 +0100] Server.httpServe: START, binding to [https://0.0.0.0:8443/]
[03/Jul/2014:09:24:52 +0100] SimpleBackend.acceptThread: user error (RTS doesn't support multiple OS threads (use ghc -threaded when linking))
[03/Jul/2014:09:24:56 +0100] SimpleBackend.acceptThread: user error (RTS doesn't support multiple OS threads (use ghc -threaded when linking))
[03/Jul/2014:09:24:59 +0100] Server.httpServe: SHUTDOWN
[03/Jul/2014:09:24:59 +0100] Server.httpServe: BACKEND STOPPED
Apparrently OpenSSL requires its own OS thread but the runtime isn't configured to allow this. (new to Haskell) Had a look into it, found some people having the same issue (though not with Snap: http://irclog.perlgeek.de/darcs/2013-06-28) but any suggestions for correcting it with command line arguments to cabal just aren't recognized.
I am building the service with -threaded:
ghc src/Main.hs -threaded
Given I'm following the instructions this seems like a bug; don't urgently need SSL and quite enjoying the framework, thank you!
Hi!
I need this small change to the getaddrinfo call in Snap/Internal/Http/Server/Address.hs
, addrSocketType = Stream
}
Now that blaze-builder-0.4.1.0
is out, I get a compile error with snap-server-1.0.3.3
:
src/Snap/Internal/Http/Server/Config.hs:289:10: error:
• No instance for (Semigroup (Config m a))
arising from the superclasses of an instance declaration
• In the instance declaration for ‘Monoid (Config m a)’
|
289 | instance Monoid (Config m a) where
| ^^^^^^^^^^^^^^^^^^^
Maybe consider revising some releases with lower bounds on base or deprecating them.
The testsuite uses has a dependency on random
that needs to be bumped.
So far I haven't been able to build it with the new version yet though, due to
…and more importantly
Context: commercialhaskell/stackage#5474
When using escapeHttp
or terminateConnection
to serve a request, the Snap HTTP server will not make any attempt to log the request, or any exception that the handler may throw.
I would prefer if Snap logs the requested path and any exception that the handler might throw. I found this useful in my Threepenny-GUI project. See also HeinrichApfelmus/threepenny-gui#145 .
Here is a minimal complete test case for the reported behavior:
$ cat SnapTest.hs
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Char8 as BS (hPutStrLn)
import qualified Control.Exception as E
import Snap.Core as Snap
import qualified Snap.Http.Server as Snap
import System.IO (stderr)
config = Snap.setErrorLog (Snap.ConfigIoLog $ BS.hPutStrLn stderr)
$ Snap.setAccessLog (Snap.ConfigIoLog $ BS.hPutStrLn stderr)
$ Snap.defaultConfig
main = Snap.httpServe config $ route
[ ("escape" , Snap.escapeHttp $ \_ _ _ -> E.throw msg)
, ("terminate", Snap.terminateConnection msg)]
msg = E.AssertionFailed "Hello?"
Request issued
$ curl http://0.0.0.0:8000
<!DOCTYPE html>
<html>
<head>
<title>Not found</title>
</head>
<body>
<code>No handler accepted "/"</code>
</body></html>
$ curl http://0.0.0.0:8000/escape
curl: (52) Empty reply from server
$ curl http://0.0.0.0:8000/terminate
curl: (52) Empty reply from server
and the corresponding log
$ runhaskell SnapTest.hs
no port specified, defaulting to port 8000
Listening on http://0.0.0.0:8000
127.0.0.1 - - [07/Dec/2016:23:04:54 +0100] "GET / HTTP/1.1" 404 198 - "curl/7.30.0"
The second and third request have not generated any log entry.
Snap server fails to install with the following error even though network-2.6.0.2 is present.
This is what I get when I try to do 'cabal install snap-server'
Resolving dependencies...
Configuring snap-server-0.9.4.5...
cabal: At least the following dependencies are missing:
network >=2.3 && <2.6 && ==2.6.0.2
cabal: Error: some packages failed to install:
snap-server-0.9.4.5 failed during the configure step. The exception was:
ExitFailure 1
And this is the output I get when I try 'cabal install network'
Resolving dependencies...
All the requested packages are already installed:
network-2.6.0.2
Use --reinstall if you want to reinstall anyway.
Also $HOME/.cabal/bin is present in my path.
Am I missing something?
Thank you.
@zsol reports (L0neGamer/ekg#11) that ekg doesn't respect the hostname given for the server. ekg simply calls setHostname
, followed by httpServe
, so the issue is most likely with snap.
Here's the original bug report:
When I tell it to listen on localhost like here, it still listens on all available interfaces:
tcp 0 0 0.0.0.0:1030 0.0.0.0:* LISTEN 4222/hlogster
(output of netstat -tnpl)
I do realize this is probably a bug in Snap, just thought you should know.
Documentation outlines http://snapframework.com/faq#how-do-i-enable-ssl that to include ssl support I need to recompile it.
I'm working withing stack, so I do
stack build --flag snap-server:openssl
Which seems like downloading openssl-streams and rebuilding server with flag, but running server with command
stack exec -- lumper -p 9000 --ssl-port=443 --ssl-cert=cert.pem --ssl-key=privkey.pem
I would like to know if I'm missing something and how can I enable truly ssl?
Currently, snap-server
is bounded to versions of bytestring
below 0.11.*
. Could this be bumped?
It would be nice to be able to start the server on an existing file descriptor instead of having it opening one based on a port number. This can be usefull e.g. with Circus: Circus will manage the port (and call listen
on it) and fork the server, allowing it to accept
on the FD shared between possibly multiple snap workers.
I'm testing chain-cert functionality. And server is constantly crashing. Usually it shows in stderr only "Shutting down.." message, but sometimes also "server: forkOS_entry: interrupted" and exit code 1.
error.log may contain "got exception in httpAcceptFunc: ProtocolError "error:14076102:SSL routines:SSL23_GET_CLIENT_HELLO:unsupported protocol"
I've used https://www.ssllabs.com/ssltest/ for testing.
Currently text-2.0
is excluded by the constraints on text
.
We need to patch this package in NixOS by runnning
sed -i -e 's|text *>= .*,|text,|' -e 's|HsOpenSSL >= .*|HsOpenSSL|' -e 's|network.*2.6,|network,|' snap-server.cabal
before the build. It would be great if a new version could be released that lifts those restrictions from the Cabal file.
As far as I can tell, snap-server-1.1.2.0
is already buildable with GHC-9.2 when the upper bounds on base
and attoparsec
are relaxed. Could you adjust these bounds?
The latest release requires base < 4.15, so at least that bound needs to be relaxed.
Cancel was added (see #99 (comment)) in this commit: 3d03b32
But here: 3d03b32#diff-6b4d869d46e926e6a8a592022cf1aa89R198 cancel
is returned, not called. As a result, threads are retained forever.
ping @gregorycollins
A few dependency version bounds need to be bumped.
It would be nice to have a variant of httpServe
that choose its port number, possibly starting at some initial value.
This is can be useful for instance when launching multiple "control" command-line commands: each one will return some ID (that make it possible to retrieve the allocate port number), then some querying command-line command will use that ID to communicate with the corresponding control process.
For instance:
> ID=$(control-command run ping www.google.com)
> control-command logs $ID
64 bytes from x.1e100.net (173.194.34.83): icmp_req=3 ttl=56 time=37.2 ms
64 bytes from x.1e100.net (173.194.34.83): icmp_req=4 ttl=56 time=33.9 ms
What does FIXME
mean here? Can we expect ProxyType
to work correctly?
If you make a request to a snap server using an unsupported method, it just hangs up on you. It should return a 501 Not Implemented.
Hi, I'm trying to deliver a large HTTP response using the Haskell Snap framework, but memory usage grows in proportion to the size of the response. Here's a couple of cut down test cases that use a large lazy ByteString:
import Snap.Core (Snap, writeLBS, readRequestBody)
import Snap.Http.Server (quickHttpServe)
import Control.Monad.IO.Class (MonadIO(liftIO))
import qualified Data.ByteString.Lazy.Char8 as LBS (ByteString, length, replicate)
main :: IO ()
main = quickHttpServe $ site test1 where
test1, test2 :: LBS.ByteString -> Snap ()
-- Send ss to client
test1 = writeLBS
-- Print ss to stdout upon receiving request
test2 = liftIO . print
site write = do
body <- readRequestBody 1000
-- Making ss dependant on the request stops GHC from keeping a
-- reference to ss as pointed out by Reid Barton.
let bodyLength = fromIntegral $ LBS.length body
write $ ss bodyLength
ss c = LBS.replicate (1000000000000 * (c + 1)) 'S'
The responses are delivered using chunked encoding (I checked, and it's 1Tb so it would have to be). I thought Snap should also be able to deliver the response in constant memory. Is there any way to achieve this? It's also worth noting that the response starts being delivered immediately.
Memory was measured using "top" on linux and was observed to grow to 15GB resident at which point it was just starting to swap. The memory grew by jumping a factor of 2 each time rather than steadily increasing. The request did complete and deliver ~1Terabyte, so the memory usage is a couple of orders of magnitude less than the size of the ByteString. Once the request had completed, it sat at 15Gb resident (I left it for a few minutes). When I fired another request at it, it still remained steady at 15Gb and completed the request as before. The virtual size stayed within 5% of the resident size.
Firing 2 concurrent requests at it resulted at first in a drop in virtual and resident memory to about 5Gb, followed by an increase to about 17Gb at which point the machine was getting unusable so I killed the process.
GHC version 7.8.3, Snap version 0.14.0.5
Also GHC version 7.10.2, Snap version 0.14.0.6
AFAICT only the bound on base
needs to be bumped.
io-stream-haproxy
needs an update too: snapframework/io-streams-haproxy#19
This is not obvious, and in particular, http://snapframework.com/faq#how-do-i-enable-ssl makes no mention of this. Please consider updating the documentation to mention that -threaded is required for SSL connections to work
Requests made with unsupported HTTP versions (HTTP/2.0) are accepted and processed as if they were HTTP 1.1. They should get 505 HTTP Version Not Supported responses instead. If HTTP 2.0 actually happens some day, there will be an issue with older snap servers claiming to support it, but not actually supporting it.
I was running a websockets-snap server on my laptop,
when my wifi was off, I got
[24/Apr/2014:15:15:54 +0800] ["192.168.1.204"]: an exception escaped to toplevel: recv: resource vanished (Connection reset by peer)
and some clean up cannot executed,
is this a bug of snap-server?
should snap-server catch recv exception?
https://hackage.haskell.org/package/transformers-0.6.0.0/changelog
Could you upload a compatible release or make a Hackage revision?
snap-server configures OpenSSL using contextSetCertificateFile
. It would be great to also support setting a certificate chain via contextSetCertificateChainFile
.
Test suite (and probably live servers also) are failing with this error. In the discussion of #60 @simonmar says:
I think this can happen if something calls forkOS_entry while the program is shutting down. The RTS sets a flag to say things are shutting down, and subsequent calls to forkOS_entry (which is the callback invoked by forkOS) will exit(1) with this interrupted message.
So I think the upshot is try to make sure that everything is finished - kill child threads etc. - before exiting main.
We are sloppy about this right now and will have to work harder to ensure that our child threads die before the main thread dies.
When I start a snap server on a port other than 443 strange things happen. On port 444 or 445 when I make a request it just hangs. On port 888 or 999 I get into an infinite reset loop. Observe:
./nlh -port 8888 --ssl-port=444 --hostname=nadineloveshenry.com
accessLog: Just log to file "./access.log"
errorLog: Just log to file "./error.log"
locale: Just "en_US"
port: Just 8888
bind: Just "0.0.0.0"
sslport: Just 444
sslbind: Just "0.0.0.0"
sslcert: Just "/etc/letsencrypt/live/nadineloveshenry.com/cert.pem"
sslchaincert: Just False
sslkey: Just "/etc/letsencrypt/live/nadineloveshenry.com/privkey.pem"
unixsocket: Nothing
unixaccessmode: Nothing
compression: Just True
verbose: Just True
defaultTimeout: Just 60
proxyType: Nothing
Listening on http://0.0.0.0:8888
Listening on https://0.0.0.0:444
Results in:
wget -S http://nadineloveshenry.com:888/dump
--2020-09-12 14:11:22-- http://nadineloveshenry.com:888/dump
Resolving nadineloveshenry.com (nadineloveshenry.com)... 65.111.168.75
Connecting to nadineloveshenry.com (nadineloveshenry.com)|65.111.168.75|:888... connected.
HTTP request sent, awaiting response... Read error (Connection reset by peer) in headers.
Retrying.
wget -S http://nadineloveshenry.com:444/dump
--2020-09-12 14:14:04-- http://nadineloveshenry.com:444/dump
Resolving nadineloveshenry.com (nadineloveshenry.com)... 65.111.168.75
Connecting to nadineloveshenry.com (nadineloveshenry.com)|65.111.168.75|:444...
and it hangs forever.
No one else is listening to these ports:
netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 14980/nginx: master
tcp 0 0 127.0.0.1:8001 0.0.0.0:* LISTEN 14940/./nlh
tcp 0 0 127.0.0.1:39815 0.0.0.0:* LISTEN 349/containerd
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 269/systemd-resolve
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 14980/nginx: master
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 269/systemd-resolve
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 347/sshd: /usr/bin/
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 532/master
tcp6 0 0 :::5355 :::* LISTEN 269/systemd-resolve
tcp6 0 0 :::80 :::* LISTEN 14980/nginx: master
tcp6 0 0 :::22 :::* LISTEN 347/sshd: /usr/bin/
Is this the expected behaviour? Any insights would be appreciated.
Best wishes,
Henry Laxen
Hey there.
Whenever attempting stack install snap
, I've found that the build process fails due to snap-server.
I get the following error:
Progress: 72/76
-- While building package snap-server-1.0.1.0 using:
/usr/home/ian/.stack/setup-exe-cache/x86_64-freebsd/setup-Simple-Cabal-1.24.0.0-ghc-8.0.1 --builddir=.stack-work/dist/x86_64-freebsd/Cabal-1.24.0.0 build --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
Logs have been written to: /usr/home/ian/Development/waitingfortodo/Backend/.stack-work/logs/snap-server-1.0.1.0.log
Configuring snap-server-1.0.1.0...
Building snap-server-1.0.1.0...
Preprocessing library snap-server-1.0.1.0...
[ 1 of 20] Compiling System.SendFile.FreeBSD ( .stack-work/dist/x86_64-freebsd/Cabal-1.24.0.0/build/System/SendFile/FreeBSD.hs, .stack-work/dist/x86_64-freebsd/Cabal-1.24.0.0/build/System/SendFile/FreeBSD.o )
/tmp/stack24898/snap-server-1.0.1.0/src/System/SendFile/FreeBSD.hsc:33:1: error:
The type signature for ‘sendFile’ lacks an accompanying binding
Whenever I look at the accompanying file (https://github.com/snapframework/snap-server/blob/master/src/System/SendFile/FreeBSD.hsc), I notice it's just a type signature.
I'm mostly wondering if this is due to historical reasons that it's not implemented, or if it's due to BSD reasons--a.k.a, nobody uses it :)
Regardless, I'm willing to contribute, but I didn't want to charge straight into it in the case that there is a historical reason for it not being implemented.
In snap-core 0.9.8.0 a commit was made (10f44610f5e597f665de7c3e8d07a70870c97688) in response to issue #242 which removes Content-Length header for both 204 and 304 responses. This is correct for 204 responses per RFC 7230.
But with snap-server 0.9.5.1 (latest on hackage), sendResponse adds "Transfer-Encoding: chunked" header when Content-Length is missing, response is HTTP/1.1 and not a HEAD method.
The result is that a 204 response has a "Transfer-Encoding: chunked" header which violates section 3.3.1 of RFC 7230 : "A server MUST NOT send a Transfer-Encoding header field in any response with a status code of 1xx (Informational) or 204 (No Content)."
When snap-core 0.9.8.0 with snap-server 0.9.5.1 is behind haproxy 1.5.14, such a response confuses haproxy causing it to hang until timeout. While haproxy may be at fault for not recognizing the terminating chunk and closing the connection with the client, it is probably not expecting chunked encoding at all on 204. It seems snap should adhere to RFC here to ease compatibility.
It looks like HEAD of snap-server may not have this problem as sendResponse there does not add Content-Encoding for 204 or 304 responses. Can that change get back ported to 0.9.x?
I found out that server stops accepting connections because there were too many opened sockets in CLOSE_WAIT state. For my server it happens every one or two days and only for ssl connections.
Problem: The IP address logged into the file given by --access-log=<logfile>
is recording 127.0.0.1
instead of the real visitor IP address. This happens even if I specify --proxy=X_Forwarded_For
.
I have also tried putting my entire Snap app (in Haskell) behind behindProxy X_Forwarded_For $
but that doesn't work either.
This is my nginx setup:
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:4567/;
proxy_redirect off;
}
What am I doing wrong?
Snap projects compiled under Ubuntu against Snap 1.0 ( aa87e46f50a7485ae315ebf303ed949a1447d24d and the git submodules it comes packaged with) fail to serve data.
When run on port 8000, curl localhost:8000
produces: curl: (52) Empty reply from server
When run as su on port 80, curl localhost
gives curl: (56) Recv failure: Connection reset by peer
A minimal example is here: http://github.com/imalsogreg/tests under the 'snap1' branch.
The same behavior occurs on two Ubuntu VM's and and one physical Ubuntu laptop.
The server works as expected under osx Yosemite.
One physical Ubuntu machine produces working servers from the tests/snap1
example. I don't know why that machine produces good executables and the others bad, but it may be related to the fact that cabal update
has not been run on the good machine in the last 139 days.
Executables copied from that 'good' machine to one of the 'bad' ones successfully serve data back to curl, making me suspect some transitive dependencies more than some OS environment issues.
The cabal-freeze output of the good machine is here: https://gist.github.com/imalsogreg/aa5f53a1a24551d4204e
And the cabal-freeze output from one bad machine is here:
https://gist.github.com/imalsogreg/41cb3082f6233f29a9f7
The diff between them (left side good, right side bad): https://www.diffchecker.com/zgjxmat4
Update: Adding the good machine's cabal.config file generated by cabal freeze
to the project directory on the 'bad' machine and rebuilding results in a working server. Now to identify which dependency is causing the trouble...
It might be nice to point out in the documentation for commandLineConfig that it has to be called after setting various parameters of a Config object. Based on the documentation we have now, I tried:
main = do
start <- commandLineConfig emptyConfig
let config = setAccessLog ConfigNoLog start
let config' = setErrorLog ConfigNoLog config
let config'' = setPort 8000 config'
httpServe config'' site
since commandLineConfig says "just pass in emptyConfig to start with". But, if you do that, command line options are ignored. Eeek!
I subsequently discovered you instead have to do:
main = do
let config = setAccessLog ConfigNoLog mempty
let config' = setErrorLog ConfigNoLog config
let config'' = setPort 8000 config'
start <- commandLineConfig config''
httpServe start site
and then command line options are honoured as with quickHttpServe. So, sure, ok, but perhaps something to indicate this is the way it has to be used would be appropriate?
AfC
I tried to use setBind "/path/to/unix.socket"
but the server parses the bytestring as IP address.
Continuing the conversation from here: snapframework/snap-core#283
tl;dr Handlers seem not to correctly time out if computing a pure value causes them to overrun their time deadline.
Repro:
{-# LANGUAGE OverloadedStrings #-}
import Snap.Core
import Snap.Http.Server
import qualified Data.List as L
main = quickHttpServe hmm
hmm :: Snap ()
hmm = do
setTimeout 5
writeBS $ if L.find (==1) (repeat 0) == Just 1 then "A" else "B"
If you curl 'localhost:8000'
, it won't time out in 5 seconds, or seemingly ever. If you change writeBS $
to writeBS $!
, though, forcing the value to WHNF is enough to properly time out.
The problem, I hypothesize, is that the hmm
function is immediately returning a thunk, and thus not timing out.
My (hand-wavy) proposal is to force to WHNF (or normal form) the ByteString response body, in order to correctly time out. This'll prevent malicious input (to vulnerable handlers) from creating "permanent" un-killed response threads.
Functions I might try and update are processRequest
or runServerHandler
in Snap.Internal.Http.Server.Session
.
I can try to hack on this but it'd be good to know if it's the right way forward first.
[26 of 26] Compiling Main ( test/TestSuite.hs, dist/build/testsuite/testsuite-tmp/Main.o )
test/TestSuite.hs:16:1: error:
Failed to load interface for ‘Snap.Internal.Http.Server.Address.Tests’
Perhaps you meant
Snap.Internal.Http.Server.Address
Snap.Internal.Http.Server.Parser
Snap.Internal.Http.Server.Session
Use -v to see a list of the files searched for.
I'm working on the commandline branch. A simple example server such as the one below prints the typical snap startup info to stdout, and then the process immediately ends without writing anything to access.log or error.log:
main = quickServe (writeText "hello")
Steps to reproduce:
Children aren't getting harvested on ctrl-c in GHCi, can see their output continue even though the web server itself successfully shut down.
I think slave-thread needs 1 a ThreadKilled 2 exception to bubble up to the parent thread (the one in main
which invoked httpServe
) in order for it to do its thing.
This looks like a good candidate for starting to narrow things down.
I'll try to put together a minimal repro in a bit.
Some context from IRC:
< mightybyte> One of our apps started exhibiting this behavior a few months back.
< bitemyapp> I think perhaps it is not letting the ThreadKilled bubble up.
< mightybyte> And I think it happened around the time that some code was added that probably forked some threads.
< mightybyte> So that all lines up with what you're saying.
Here is snippet from compilation log:
[ 8 of 17] Compiling Paths_snap_server ( dist/build/autogen/Paths_snap_server.hs, dist/build/Paths_snap_server.o )
dist/build/autogen/Paths_snap_server.hs:21:13:
Not in scope: `catch'
dist/build/autogen/Paths_snap_server.hs:22:13:
Not in scope: `catch'
dist/build/autogen/Paths_snap_server.hs:23:14:
Not in scope: `catch'
dist/build/autogen/Paths_snap_server.hs:24:17:
Not in scope: `catch'
Compiled with ghc-7.6.2 and base-4.6.0.1
I would appreciate some hints how to fix it. This file seems to be autogenerated during compilation, because all what is in this file in sources is just some version information, so it is hard to figure out how to edit it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.