{"action":"created","issue":{"url":"https://api.github.com/repos/mstksg/ghcjs-websockets/issues/1","labels_url":"https://api.github.com/repos/mstksg/ghcjs-websockets/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/mstksg/ghcjs-websockets/issues/1/comments","events_url":"https://api.github.com/repos/mstksg/ghcjs-websockets/issues/1/events","html_url":"https://github.com/mstksg/ghcjs-websockets/issues/1","id":73881705,"number":1,"title":"receive functions do not appear to be interruptible","user":{"login":"mgsloan","id":22570,"avatar_url":"https://avatars.githubusercontent.com/u/22570?v=3","gravatar_id":"","url":"https://api.github.com/users/mgsloan","html_url":"https://github.com/mgsloan","followers_url":"https://api.github.com/users/mgsloan/followers","following_url":"https://api.github.com/users/mgsloan/following{/other_user}","gists_url":"https://api.github.com/users/mgsloan/gists{/gist_id}","starred_url":"https://api.github.com/users/mgsloan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgsloan/subscriptions","organizations_url":"https://api.github.com/users/mgsloan/orgs","repos_url":"https://api.github.com/users/mgsloan/repos","events_url":"https://api.github.com/users/mgsloan/events{/privacy}","received_events_url":"https://api.github.com/users/mgsloan/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/mstksg/ghcjs-websockets/labels/bug","name":"bug","color":"fc2929"}],"state":"closed","locked":false,"assignee":{"login":"mstksg","id":187815,"avatar_url":"https://avatars.githubusercontent.com/u/187815?v=3","gravatar_id":"","url":"https://api.github.com/users/mstksg","html_url":"https://github.com/mstksg","followers_url":"https://api.github.com/users/mstksg/followers","following_url":"https://api.github.com/users/mstksg/following{/other_user}","gists_url":"https://api.github.com/users/mstksg/gists{/gist_id}","starred_url":"https://api.github.com/users/mstksg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mstksg/subscriptions","organizations_url":"https://api.github.com/users/mstksg/orgs","repos_url":"https://api.github.com/users/mstksg/repos","events_url":"https://api.github.com/users/mstksg/events{/privacy}","received_events_url":"https://api.github.com/users/mstksg/received_events","type":"User","site_admin":false},"milestone":null,"comments":4,"created_at":"2015-05-07T07:40:44Z","updated_at":"2015-05-12T04:57:48Z","closed_at":"2015-05-09T11:46:44Z","body":"Hi!  Thanks for this library, it's very handy and well documented :)\r\n\r\nAnyway, in practice it seems like async exceptions do not play nicely with the receive functions.  If a receive function is interrupted, then it looks like the next websocket response gets swallowed.  This isn't a bug persay, but was counterintuitive to me.  Ideally this would be documented, and perhaps a layer added to help with this (such as the one below)\r\n\r\nI could probably put together a minimal repro if need be.\r\n\r\nFor now, I am using this to get around this:\r\n\r\n```haskell\r\n-- | Wrapper around JavaScript.WebSockets which has safely interruptible\r\n-- sending and receiving of messages.\r\n--\r\n-- Originally attempted with vanilla Chan, but I ran into what I\r\n-- believe to be an erroneous \"thread blocked indefinitely in an MVar\r\n-- operation\".\r\n--\r\n-- This may be the issue documented here:\r\n-- https://github.com/ghcjs/ghcjs/issues/320\r\n--\r\n-- (I am using a slighty older GHCJS, and don't have time to test HEAD)\r\nmodule Communication where\r\n\r\nimport           Control.Concurrent.Async (race)\r\nimport           Control.Concurrent.STM (atomically)\r\nimport           Control.Concurrent.STM.TChan\r\nimport           Control.Monad (forever)\r\nimport           Data.Text (Text)\r\nimport           Data.Void (absurd)\r\nimport qualified JavaScript.WebSockets as WS\r\n\r\ndata Connection = Connection\r\n  { receiveTChan :: TChan Text\r\n  , sendTChan :: TChan Text\r\n  , connection :: WS.Connection\r\n  }\r\n\r\n-- NOTE: if the websocket disconnects, the inner function is killed.\r\n-- This is due to using the unsafe functions in JavaScript.WebSockets\r\nwithUrl :: Text -> (Connection -> IO a) -> IO a\r\nwithUrl url f = do\r\n    receiveTChan <- newTChanIO\r\n    sendTChan <- newTChanIO\r\n    result <- WS.withUrl url $ \\connection ->\r\n      receiveThread connection receiveTChan `race`\r\n      sendThread connection sendTChan `race`\r\n      f Connection {..}\r\n    case result of\r\n      Left (Left x) -> absurd x\r\n      Left (Right x) -> absurd x\r\n      Right x -> return x\r\n  where\r\n    receiveThread conn chan =\r\n      forever $ WS.receiveText_ conn >>= atomically . writeTChan chan\r\n    sendThread conn chan =\r\n      forever $ atomically (readTChan chan) >>= WS.sendText_ conn\r\n\r\nreceiveText :: Connection -> IO Text\r\nreceiveText = atomically . readTChan . receiveTChan\r\n\r\nsendText :: Connection -> Text -> IO ()\r\nsendText conn = atomically . writeTChan (sendTChan conn)\r\n```"},"comment":{"url":"https://api.github.com/repos/mstksg/ghcjs-websockets/issues/comments/101131372","html_url":"https://github.com/mstksg/ghcjs-websockets/issues/1#issuecomment-101131372","issue_url":"https://api.github.com/repos/mstksg/ghcjs-websockets/issues/1","id":101131372,"user":{"login":"mgsloan","id":22570,"avatar_url":"https://avatars.githubusercontent.com/u/22570?v=3","gravatar_id":"","url":"https://api.github.com/users/mgsloan","html_url":"https://github.com/mgsloan","followers_url":"https://api.github.com/users/mgsloan/followers","following_url":"https://api.github.com/users/mgsloan/following{/other_user}","gists_url":"https://api.github.com/users/mgsloan/gists{/gist_id}","starred_url":"https://api.github.com/users/mgsloan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgsloan/subscriptions","organizations_url":"https://api.github.com/users/mgsloan/orgs","repos_url":"https://api.github.com/users/mgsloan/repos","events_url":"https://api.github.com/users/mgsloan/events{/privacy}","received_events_url":"https://api.github.com/users/mgsloan/received_events","type":"User","site_admin":false},"created_at":"2015-05-12T04:57:48Z","updated_at":"2015-05-12T04:57:48Z","body":"I've confirmed that this fixes the issue.  Thanks for the rapid fix!"}}