본문 바로가기

개발노트/Ruby

Rubymine > Exception in DebugThread loop: Bad file descriptor(Errno::EBADF) 발생 시

현상

Rubymine 에서 개발을 하다가 debug 모드로 실행하고 break point 걸어서 보려고 하면 Exception in DebugThread loop: Bad file descriptor(Errno::EBADF) 이런 오류가 발생하면서 안 되는 경우가 있다.

 

해결

결론적으로는  Rails.env = development 인 상황에서도 Rails + puma 가 multi processes 로 동작하도록 구성돼 있는 것을 single process 로 동작하도록 구성하면 해결이 된다.

 

원인

puma 가 multi processes 모드(a.k.a. cluster mode)로 실행되면

 

[38032] *   Master PID: 38032

[38032] - Worker 2 (PID: 38156) booted in 0.2s, phase: 0
[38032] - Worker 3 (PID: 38157) booted in 0.2s, phase: 0
[38032] - Worker 0 (PID: 38154) booted in 0.21s, phase: 0
[38032] - Worker 1 (PID: 38155) booted in 0.21s, phase: 0

 

이렇게 Master process 와 이로부터 forked 된 child processes 를 확인할 수 있다.

그런데 Rubymine 에서 rails 를 debugger 로 실행시키면 아래와 같이 별도의 port 를 추가로 사용하게 되는데,

그 별도의 port 는 puma master PID 가 점유하고 있는 port 이다.

즉, debugger 는 puma 의 master process 에 붙어있는 것이다.

 

그런데 puma 서버에 http request 를 보내면, master process 가 요청을 처리하지 않고 child processes 중 하나가 처리하게 되는데(위 스샷에서는 PID 38155) 이 process 입장에서는 연결된 debugger 를 찾을 수 없으니(File Descriptor 를 이용해서 찾나 봄) 이런 오류가 발생하게 된 것으로 보인다.

 

이 문제를 해결하기 위해 puma.rb 의 workers 수를 0으로 변경하여 주면, 아래와 같이 single process(single mode) 만 뜨게 되는데, 아까완 달리 main PID 하나가 정확하게 debugger 가 사용하는 port 를 점유한 PID 와 일치하는 것을 볼 수 있다.

이 상태에서 특정 코드를 실행하도록 하는 trigger(e.g. http request)를 실행하면

문제없이 잘 작동함을 볼 수 있다!

반응형