{"action":"created","issue":{"url":"https://api.github.com/repos/snapframework/snap-server/issues/118","repository_url":"https://api.github.com/repos/snapframework/snap-server","labels_url":"https://api.github.com/repos/snapframework/snap-server/issues/118/labels{/name}","comments_url":"https://api.github.com/repos/snapframework/snap-server/issues/118/comments","events_url":"https://api.github.com/repos/snapframework/snap-server/issues/118/events","html_url":"https://github.com/snapframework/snap-server/issues/118","id":379953694,"node_id":"MDU6SXNzdWUzNzk5NTM2OTQ=","number":118,"title":"Timeout for pure values","user":{"login":"tom-bop","id":26091843,"node_id":"MDQ6VXNlcjI2MDkxODQz","avatar_url":"https://avatars0.githubusercontent.com/u/26091843?v=4","gravatar_id":"","url":"https://api.github.com/users/tom-bop","html_url":"https://github.com/tom-bop","followers_url":"https://api.github.com/users/tom-bop/followers","following_url":"https://api.github.com/users/tom-bop/following{/other_user}","gists_url":"https://api.github.com/users/tom-bop/gists{/gist_id}","starred_url":"https://api.github.com/users/tom-bop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tom-bop/subscriptions","organizations_url":"https://api.github.com/users/tom-bop/orgs","repos_url":"https://api.github.com/users/tom-bop/repos","events_url":"https://api.github.com/users/tom-bop/events{/privacy}","received_events_url":"https://api.github.com/users/tom-bop/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-11-12T21:11:21Z","updated_at":"2018-11-13T19:51:39Z","closed_at":null,"author_association":"NONE","body":"Continuing the conversation from here: https://github.com/snapframework/snap-core/issues/283\r\n\r\n**tl;dr** Handlers seem not to correctly time out if computing a pure value causes them to overrun their time deadline.\r\n\r\nRepro:\r\n```haskell\r\n{-# LANGUAGE OverloadedStrings #-}\r\n\r\nimport Snap.Core\r\nimport Snap.Http.Server\r\n\r\nimport qualified Data.List as L\r\n\r\nmain = quickHttpServe hmm\r\n\r\nhmm :: Snap ()\r\nhmm = do\r\n   setTimeout 5\r\n   writeBS $ if L.find (==1) (repeat 0) == Just 1 then \"A\" else \"B\"\r\n```\r\n\r\nIf 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.\r\n\r\nThe problem, I hypothesize, is that the `hmm` function is immediately returning a thunk, and thus not timing out.\r\n\r\nMy (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.\r\n\r\nFunctions I might try and update are `processRequest` or `runServerHandler` in `Snap.Internal.Http.Server.Session`.\r\n\r\nI can try to hack on this but it'd be good to know if it's the right way forward first."},"comment":{"url":"https://api.github.com/repos/snapframework/snap-server/issues/comments/438412376","html_url":"https://github.com/snapframework/snap-server/issues/118#issuecomment-438412376","issue_url":"https://api.github.com/repos/snapframework/snap-server/issues/118","id":438412376,"node_id":"MDEyOklzc3VlQ29tbWVudDQzODQxMjM3Ng==","user":{"login":"tom-bop","id":26091843,"node_id":"MDQ6VXNlcjI2MDkxODQz","avatar_url":"https://avatars0.githubusercontent.com/u/26091843?v=4","gravatar_id":"","url":"https://api.github.com/users/tom-bop","html_url":"https://github.com/tom-bop","followers_url":"https://api.github.com/users/tom-bop/followers","following_url":"https://api.github.com/users/tom-bop/following{/other_user}","gists_url":"https://api.github.com/users/tom-bop/gists{/gist_id}","starred_url":"https://api.github.com/users/tom-bop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tom-bop/subscriptions","organizations_url":"https://api.github.com/users/tom-bop/orgs","repos_url":"https://api.github.com/users/tom-bop/repos","events_url":"https://api.github.com/users/tom-bop/events{/privacy}","received_events_url":"https://api.github.com/users/tom-bop/received_events","type":"User","site_admin":false},"created_at":"2018-11-13T19:51:39Z","updated_at":"2018-11-13T19:51:39Z","author_association":"NONE","body":"Here's an example that still fails to timeout with `($!)`:\r\n\r\n```haskell\r\n{-# LANGUAGE OverloadedStrings #-}\r\n\r\nimport Snap.Core\r\nimport Snap.Http.Server\r\n\r\nimport qualified Data.ByteString.Lazy as LBS\r\nimport qualified Data.List as L\r\n\r\nmain = quickHttpServe hmm\r\n\r\nhmm :: Snap ()\r\nhmm = do\r\n   setTimeout 5\r\n   let x = if L.find (==1) (repeat 0) == Just 1 then \"A\" else \"B\"\r\n   writeLBS $! 33 `LBS.cons` x\r\n```\r\n\r\n(Again just `curl 'localhost:8000'`)"}}
{"actor":{"display_login":"tom-bop"}}