2012-03-10 3 views
1

관찰 가능한 개체 내에서 Process.fork을 사용했지만 관찰자 개체의 파일 출력의 출력을 방해하고있는 것으로 나타났습니다.Process.fork가 Ruby에서 파일 io에 영향을 주어야합니까?

Process 줄을 주석 처리 할 때 출력되는 파일의 번호는 0-15 행의 16 줄입니다. 그러나 주석 처리되지 않은 파일에는 0-15 사이에 136 개의 순서가없는 번호가 들어 있습니다. Process이 주석 처리되었는지 여부에 관계없이 올바른 숫자가 화면에 인쇄됩니다.

부분적으로 예상되는 동작입니까, 아니면 버그입니까? 누구든지이 문제를 해결할 수있는 아이디어가 있습니까?

아래의 코드는 문제를 재현하고 문제를 설명하기에 충분할 때까지 원래 코드를 벗겨서 만들어졌습니다. Process.fork을 사용하는 원래의 이유는 처리 속도를 높이기 위해 몇 가지 프로세스를 만드는 것이 었습니다.

require 'observer' 

class Recorder 
    def initialize(notifier, filename) 
    notifier.add_observer(self) 
    @save_file = File.open(filename, 'w') 
    @i = 0 
    end 

    def update 
    puts @i 
    @save_file.puts @i 
    @i += 1 
    end 


    def stop 
    @save_file.close 
    end 
end 


class Notifier 
    include Observable 

    def run 
    16.times do 
     # When the following two Process lines are uncommented, 
     # the file output from the Recorder above is erratic 
     Process.fork {exit} 
     Process.wait 

     changed 
     notify_observers 
    end 
    end 
end 


notifier = Notifier.new 
recorder = Recorder.new(notifier, 'test.data') 

notifier.run 
recorder.stop 

답변

4

당신이 포크, 자식 프로세스가 데이터 버퍼에 계류되어 무엇 이건 부모의 오픈 파일의 복제를 포함합니다. 자식이 종료되면이 데이터를 플러시하고 열린 파일을 닫습니다. 이것은 부모 나 형제의 열린 파일에는 영향을 미치지 않지만 모두 같은 커널 fd에 매핑되기 때문에 모든 데이터가 동일한 출력 파일로 이동합니다.

fork를 처음 실행할 때 보류중인 출력이 없으므로 자식이 존재할 때 아무 것도 쓰지 않습니다. 두 번째로, "0 \ n"이 보류 중이고, 다음에 종료 할 때 "0 \ n1 \ n"이 버퍼링됩니다. fork 된 프로세스는 생성 된 순서대로 종료되지 않을 수 있습니다 그들은 비동기식입니다.) 따라서 당신의 뒤죽박죽 된 결과.

포크는 열려있는 파일 및 소켓을 보존하므로 조심스럽게 조심해야합니다.

버퍼링 대신 각 쓰기 출력을 플러시하도록 ruby에게 알려줌으로써이 문제를 해결할 수 있습니다.

class Recorder 
    def initialize(notifier, filename) 
    notifier.add_observer(self) 
    @save_file = File.open(filename, 'w') 
    @save_file.sync = true # don't buffer this file 
    @i = 0 
    end 
end 
+0

감사합니다. 동기화 선이 아무런 차이가 없으므로 답변을 편집했지만 원리는 정확하고 대신 플러시를 사용하여 작동합니다. –

+0

IO # sync = 당신을 위해 작동하지 않았다는 것이 궁금합니다. 나는 당신의 코드로 @ save_file.sync = true를 시도했고 루비 1.9.2p180 (2011-02-18 수정 30909) [x86_64-linux]와 루비 1.8.7 (2010-01-10 패치 레벨 249) [x86_64 -linux] – dbenhur

관련 문제