deivid-rodriguez/byebug

Puma cluster mode causes terminal corruption

ersinakinci opened this issue · 3 comments

Problem description

When I run Puma with multiple workers in cluster mode, byebug tends to cause strange behavior on the terminal. For example, I'll try to type in quit at a breakpoint, but it will non-deterministically come out as qit, ui, qt, etc.

I'm able to get the correct input by repeatedly pressing certain keys (including backspace) until the desired input is displayed. However, when I press enter, it still complains that qit, ui, etc. doesn't exist even though the correct command is nominally on the screen. Stranger still, if I press enter a second time, it will appear to run the correct command even though there isn't any command waiting in the prompt anymore.

The generally recommended advice is to use Puma in single mode in development, but this isn't possible for my use case. I'm running SSR in a separate Node process that issues a request during SSR back to the Rails server. In single mode, there's only one process, so the SSR request times out because it's waiting on the browser request, but the browser request can't finish until SSR finishes...

Note, I get the same strange behavior when using pry and pry-byebug.

Expected behavior

Byebug should just work when using Puma in cluster mode.

Actual behavior

Byebug corrupts terminal input.

Steps to reproduce the problem

  1. Create a Rails project with byebug and puma installed.
  2. Insert a breakpoint.
  3. Start the Rails server in cluster mode with two workers.
  4. Initiate two simultaneous requests to the Rails server.
  5. 💥

It's almost as if byebug doesn't know which Puma process to latch onto, or somehow it gets confused and non-deterministically splits the terminal input between them.

Here's an example from when I typed continue. Notice that when I typed it, only oiu came out. Then, when I pressed enter a second time, it claimed that I was attempting to execute a command called cntne. In other words, the characters in the word continue got split up between two different streams and somehow got jumbled:

[71, 80] in /Users/ersin/projects/gamacy/app/services/redux_preloaded_state_service.rb
   71:     }
   72:   end
   73: 
   74:   def populate_session_slice
   75:     byebug
=> 76:     result[:session] = { user: user.session_hash } if user.present?
   77:   end
   78: 
   79:   # Makes Flipper features available via Redux
   80:   # e.g., :my_feature --> state.features.myFeature
(byebug) oiu
*** NameError Exception: undefined local variable or method `oiu' for #<ReduxPreloadedStateService:0x00007f94f0813530>

nil
(byebug) *** NameError Exception: undefined local variable or method `cntne' for #<ReduxPreloadedStateService:0x00007f94f011b8e0>

nil

Closing as duplicate of #487.