开发者

"filedescriptor out of range in select()" when using python's subprocess with rsync

开发者 https://www.devze.com 2023-04-11 20:05 出处:网络
the code below is used to sync uploaded picture to another place. it works, but after a period of time(about 10 days), the service is unusable , showing error: \'filedescriptor out of range in select(

the code below is used to sync uploaded picture to another place. it works, but after a period of time(about 10 days), the service is unusable , showing error: 'filedescriptor out of range in select()', but restart service solves the problem.

# sync.py

def sync_file(source_pic, hashval, retry_num=3):

    pic_path = os.path.join(gen_dir(hashval), os.path.split(source_pic)[1])
    filename = tempfile.mkstemp()[1]
    with open(filename, 'w') as f:
        f.write(pic_path)

    for sync_path in options.sync_paths:
        try_num = 0
        rsync_cmd = ['rsync','-au', '--files-from='+filename, options.pic_path, sync_path]

        while try_num < retry_num:
            proc = subprocess.Popen(rsync_cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout_value, stderr_value = proc.communicate()

            if len(stderr_value) != 0:
                logger.error('sync failed: %s' % stderr_value)
                try_num = try_num + 1
                #raise UploadException('sync failed')
            else:
                break

    os.remove(filename)

log info:

File "/path/to/sync.py", line 25, in sync_file
    stdout_value, stderr_value = proc.communicate()
File "/usr/lib/python2.6/subprocess.py", line 691, in communicate
    return开发者_StackOverflow self._communicate(input)
File "/usr/lib/python2.6/subprocess.py", line 1211, in _communicate
    rlist, wlist, xlist = select.select(read_set, write_set, [])
    ValueError: filedescriptor out of range in select()

are there unclosed file descriptors that cause the error? it seems subprocess doesn't close file descriptor, so when it runs 1024 times, the file descriptor is out of range. (we are using python 2.6, subprocess is forced to use select.select() which has a limit of 1024 file descriptors even epoll is available)


https://bugzilla.redhat.com/show_bug.cgi?id=609020

Prior to Python 2.7, programs that used ulimit -n to enable communication with large numbers of subprocesses could still monitor only 1024 file descriptors at a time, which caused an exception:

ValueError: filedescriptor out of range in select()

This was due to the subprocess module using the select system call. The module now uses the poll system call, removing this limitation.

possible fix: use python 2.7+, or backport the code using poll.


You can manually close the file descriptors. After calling communicate, call proc.stderr.close() and proc.stdout.close().

0

精彩评论

暂无评论...
验证码 换一张
取 消