{"action":"created","issue":{"url":"https://api.github.com/repos/ddollar/foreman/issues/536","labels_url":"https://api.github.com/repos/ddollar/foreman/issues/536/labels{/name}","comments_url":"https://api.github.com/repos/ddollar/foreman/issues/536/comments","events_url":"https://api.github.com/repos/ddollar/foreman/issues/536/events","html_url":"https://github.com/ddollar/foreman/pull/536","id":59667898,"number":536,"title":"engine: make output Readline-friendly","user":{"login":"kyrylo","id":1079123,"avatar_url":"https://avatars.githubusercontent.com/u/1079123?v=3","gravatar_id":"","url":"https://api.github.com/users/kyrylo","html_url":"https://github.com/kyrylo","followers_url":"https://api.github.com/users/kyrylo/followers","following_url":"https://api.github.com/users/kyrylo/following{/other_user}","gists_url":"https://api.github.com/users/kyrylo/gists{/gist_id}","starred_url":"https://api.github.com/users/kyrylo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kyrylo/subscriptions","organizations_url":"https://api.github.com/users/kyrylo/orgs","repos_url":"https://api.github.com/users/kyrylo/repos","events_url":"https://api.github.com/users/kyrylo/events{/privacy}","received_events_url":"https://api.github.com/users/kyrylo/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":10,"created_at":"2015-03-03T16:36:05Z","updated_at":"2015-06-01T22:18:08Z","closed_at":"2015-03-17T17:51:12Z","pull_request":{"url":"https://api.github.com/repos/ddollar/foreman/pulls/536","html_url":"https://github.com/ddollar/foreman/pull/536","diff_url":"https://github.com/ddollar/foreman/pull/536.diff","patch_url":"https://github.com/ddollar/foreman/pull/536.patch"},"body":"The motivation behind this commit is to make Foreman respect\r\nGNU Readline [1].\r\n\r\nAs Foreman is often used with Pry (or at least many people want to), and\r\nPry is dependent on Readline, using these tools together is very\r\nproblematic [2],[3].\r\n\r\nThe problem is that when you start Pry by means of Foreman, Foreman\r\nsupresses output from Pry, so you don't see what you type. The output\r\ncan only be seen after pressing carriage return. Demonstration (a bit\r\nhard to follow, but you may want to try it yourself; clone the Pry repo\r\nand execute the same command):\r\n\r\n  http://showterm.io/3eb716461d6602ac90b09\r\n\r\nAlthough this problem was reported by Pry users, any Readline\r\napplication is affected. This commit uses IRB for tests, because it also\r\ndepends on Readline, hence it suits for testing perfectly. Other\r\nReadline dependent applications that I tested were GHCi, the Lua REPL,\r\nEshell (erlang shell).\r\n\r\nPreviously, Pry was using a trick, which allowed us to bypass this\r\nproblem [4]. The fix was featured in Pry v0.9.12.6, but then it was\r\nremoved by accident. It's been readded on HEAD recently (not released\r\nyet). However, the fix we currently have is still not perfect. Although\r\nyou can see your input immediately, you can't see your output now :D\r\nDemo:\r\n\r\n  http://showterm.io/f648de27568d96a02f1b3\r\n\r\nThe fix breaks correct piping. Now, when you pipe Pry's output, it\r\ndoesn't output Readline's prompt and user's input. What's being piped is\r\nonly return values of executed expressions.\r\nDemo:\r\n\r\n  http://showterm.io/3651389faf1fdc0d18211\r\n\r\nTo fix the missing output and pipe everything, including the user's\r\ninput, we need to set `Readline.output` correctly. However, if we do\r\nthat, we break minimal support for Foreman. So when I fixed Pry [5], I\r\nfigured it would be interesting to try to fix Foreman.\r\n\r\nNow, it's time to talk about the changes here. I'm not very familiar\r\nwith Foreman, so take the code with a grain of salt. Basically, the\r\nwhole point of the fix is to read one character at a time and print it\r\nimmediately, instead of waiting for a newline character. This technique\r\nallows us to prepend so-called markers (timestamps, if you wish) to a\r\nReadline prompt and display the user's input. It works for all the\r\nReadline apps that I mentioned above and doesn't break piping (that is,\r\ntee).\r\n\r\nNote. I had to remove `$stdout.flush` from the output method, because it\r\nwas causing thread deadlocks with the flush in `#handle_io`. The\r\ndeadlock appears when you use Foreman with Pry, pipe the output and\r\ntrigger SIGINT (control-c press). Example:\r\n\r\n  % foreman start -f Procfile | tee log\r\n  15:50:05 pryhere.1 | started with pid 26881\r\n  15:50:28 pryhere.1 | [1] pry(main)> <CTRL+C><CTRL+D>\r\n  15:50:49 pryhere.1 | [2] pry(main)> foreman/engine.rb:323:in\r\n    `synchronize': deadlock; recursive locking (ThreadError)\r\n\r\nThis is probably because of the race condition, when on SIGINT Foreman\r\nprints stuff here [6], which flushes $stdout.\r\n\r\n[1]: http://ruby-doc.org/stdlib-2.2.0/libdoc/readline/rdoc/Readline.html\r\n[2]: https://github.com/pry/pry/issues/1290\r\n[3]: https://github.com/pry/pry/issues/1275#issuecomment-54416703\r\n[4]: https://github.com/pry/pry/blob/f0cbec507111743fdbc273735ea4f0f6164a5b21/lib/pry/repl.rb#L184\r\n[5]: https://github.com/pry/pry/pull/1372\r\n[6]: https://github.com/ddollar/foreman/blob/339ff1df2347328134e471e413ad70766058faa3/lib/foreman/engine.rb#L413"},"comment":{"url":"https://api.github.com/repos/ddollar/foreman/issues/comments/107734003","html_url":"https://github.com/ddollar/foreman/pull/536#issuecomment-107734003","issue_url":"https://api.github.com/repos/ddollar/foreman/issues/536","id":107734003,"user":{"login":"gtd","id":5603,"avatar_url":"https://avatars.githubusercontent.com/u/5603?v=3","gravatar_id":"","url":"https://api.github.com/users/gtd","html_url":"https://github.com/gtd","followers_url":"https://api.github.com/users/gtd/followers","following_url":"https://api.github.com/users/gtd/following{/other_user}","gists_url":"https://api.github.com/users/gtd/gists{/gist_id}","starred_url":"https://api.github.com/users/gtd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gtd/subscriptions","organizations_url":"https://api.github.com/users/gtd/orgs","repos_url":"https://api.github.com/users/gtd/repos","events_url":"https://api.github.com/users/gtd/events{/privacy}","received_events_url":"https://api.github.com/users/gtd/received_events","type":"User","site_admin":false},"created_at":"2015-06-01T22:18:08Z","updated_at":"2015-06-01T22:18:08Z","body":":+1: \r\n\r\n@ddollar, any chance of reconsidering based on @deivid-rodriguez's message?  This is indeed an extremely common use case for pry and it's a shame to have to keep the main server process out of foreman in order to attach a debugger."}}