Filedescriptor out of range in select
stpclient
의 버그를 보고했는데 다음과 같다.File "/data/apps/column-web/eggs/snow-3.2.1-py2.7.egg/snow/client.py", line 146, in service
stp_response = self._client.call(stp_request.argv)
File "/data/apps/column-web/eggs/snow-3.2.1-py2.7.egg/snow/client.py", line 51, in call
self.send_request(request)
File "/data/apps/column-web/eggs/stpclient2-0.0.15-py2.7.egg/stpclient2/client.py", line 221, in send_request
self._timeout)
ValueError: filedescriptor out of range in select()
이 이상은 이미 여러 차례 발생했기 때문에 나는 원인을 분명히 하기로 결정했다.
원인을 찾다
우선, 항간에 떠도는 버전은
select
에서 감청한 fd
의 개수가 1024를 초과할 때 이 이상이 발생한다. 내가 분석한 결과 이 이상은 stp의 클라이언트가 던진 것이다. 이 버전의 클라이언트는 내가 쓴 것이기 때문에 1024개의 fd를 초과할 수 없다는 것을 나는 똑똑히 알고 있다. 동시에 select
당할 수 없다. 그러면 문제가 생겼다. 도대체 무엇 때문일까?이때 생각나는 문제는 바로 동네 버전에 문제가 있다는 것이다. 그래서 먼저 내가 봤는데 select 시스템 호출 중의 설명은 다음과 같다.
An fd_set is a fixed size buffer. Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to or larger than FD_SETSIZE will result in undefined behavior. Moreover, POSIX requires fd to be a valid file descriptor.
select의 notes에 다음과 같이 쓰여 있습니다.
fd_set은 fd가 음수이거나 FD를 초과하는 고정 크기 버퍼입니다.SETSIZE 시 undefined behavior 가 생성됩니다.POSIX 요구 fd 는 합법적 인 fd 입니다
이런 면에서 보면 동네 소문과는 차이가 있다. 동시에 감청하는 fd가 FD를 초과하는 것은 아니다SETSIZE에 문제가 있을 수 있습니다. fd 크기가 FD를 초과합니다.SETSIZE에 문제가 생길 수 있습니다, FDSETSIZE는 select에 정의되어 있습니다.h의 크기는 1024(문제가 생긴 기계에서)이기 때문에 fd 크기가 1024를 초과하면 문제가 있을 수 있습니다.
/usr/include/linux/posix_types.h #undef __FD_SETSIZE #define __FD_SETSIZE 1024
그러나 여기까지는 우리가 본 그 이상이 어떻게 던져졌는지 알 수 없었다
ValueError: filedescriptor out of range in select()
분명히python에서 던진 이상입니다. 시스템 호출은 undefined behavior가 발생한다고 말할 뿐입니다.
이때python의
socket
모듈을 따라select
모듈의python 소스 코드를 찾았습니다. 우리는 다음과 같은 몇 줄을 발견했습니다.Modules/selectmodule.c#if defined(_MSC_VER) max = 0;/* not used for Win32/#else/!_MSC_VER/if (!_PyIsSelectable_fd(v)) { PyErr_SetString(PyExc_ValueError, "filedescriptor out of range in select()"); goto finally; } if (v >= max) max = v; #endif/_MSC_VER */
그리고 우리는 호출
_PyIsSelectable_fd
을false로 되돌릴 때 우리 위에 있는 이상이 발생하는 것을 발견했다. 다음에 _PyIsSelectable_fd
의 실현을 살펴보자.Include/fileobject.h #ifdef HAVE_SELECT #define _PyIsSelectable_fd(FD) (((FD) >= 0) && ((FD) < FD_SETSIZE)) #else #define _PyIsSelectable_fd(FD) (1) #endif/* HAVE_SELECT */
POSIX에서 select 시스템이 전송된 fd를 호출하는 데 합법적이어야 한다고 규정했기 때문에 호출자가 fd를 검출해야 하기 때문에python에서 fd가 마이너스일 경우 또는 FD 를 초과해야 한다SERSIZE는 비합법적인 것으로 간주되어 던진다
ValueError
그러면 지금 문제가 명확해졌습니다. select 호출을 실행할 때 1024보다 크거나 0보다 작은 fd가 전송되어 위의 이상이 발생했기 때문입니다. 다음 문제는 1024보다 큰 fd가 왜 발생했는지 찾아야 합니다.현상을 해석하다
기초 구조의 학우들을 통해 알 수 있듯이 우리는 프로세스가 가장 많이 열릴 수 있는 프로세스 수를 조정했다. 슈퍼바이저 안의 모든 프로세스가 가장 많이 열릴 수 있는 fd 개수는 655360이기 때문에 fd가 1024를 초과할 가능성이 충분히 있다.이 이상은 웹 기기에 나타난다. 일부zone의 서비스가 짧은 링크를 사용하기 때문에 단일 프로세스가 가지고 있는 fd의 수가 1024를 초과할 수 있다.
이로써 이 문제는 합리적인 해석을 얻은 셈이다. 짧은 링크를 대량으로 사용하기 때문에 단일 프로세스의 fd 개수가 높아지고 1024제한을 초과하여 최초의 이상이 생겼다.
해결 방법
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.