2013-04-18 4 views
1

erlang에서 메시지가 손실되는 문제가 있습니다.erlang에서 메시지가 손실 됨

내가 사용하고있는 코드는 수동으로 사용할 때만 유효합니다. 많은 코드와 병렬로 코드를 테스트하는 '로드 테스트'에서 코드를 사용하는 경우에만 일부 메시지가 수신되지 않습니다. 수신기 부분에서. 모든 단계와 매개 변수 값을 기록 할 때 메시지를 보내는 주소가 정확한지 확인했습니다. 또한 메시지 자체에는 문제가 없습니다.

제 질문은 다음과 같습니다 : erlang에있는 '메시지 분실'에 대한 지식이 있습니까? 아직 erlang에 버그가 있습니까?

필자는 필요한 경우 일부 코드를 게시 할 수 있지만 특히이 질문에 많은 가치를 부여 할 것이라고 생각하지 않습니다.

업데이트 : 내 응용 프로그램의 주요 부분. 이것은 내 문제를 설명하기 위해 꽤 많은 코드이지만 단순화 된 버전에서 문제를 재현 할 수는 없습니다. 응용 프로그램은 할당 시스템입니다. 즉, 병렬로 그리드에 셀 모음을 예약합니다. 중요한 부분은 전체 할당 시스템을 제어하는 ​​액터 인 globalManager입니다. rowManager는 전체 표의 한 행을 관리하며 예약이 이루어지면 해당 행을 잠글니다. 셀 영역을 예약해야하는 경우 request_specific_cells 함수가 호출됩니다. 이 함수는 행을 수정해야하는 모든 rowmanagers에게 예약 요청을 보냅니다. 행 관리자가 행의 영역을 예약하면 globalManager에 확인을 보냅니다. 모든 행 관리 프로그램이 확인을 보내면 요청을 시작한 프로세스로 확인이 전송되고 관리자 중 하나가 실패하면 globalmanager가 실패를 보냅니다.

globalManager(Grid) -> 
    receive 
     {Pid, request_specific_cells, ReservationId, Coordinates, Ctr, XX} -> 
      NewGrid = request_specific_cells(Grid, Pid, ReservationId, Coordinates, Ctr, XX); 

     {Pid, confirm_region, ResId, Rid, Sid, Region, Section, Ctr, XX} -> 
      NewGrid = confirm_region(Grid, Pid, ResId, Rid, Sid, Region, Section, Ctr, XX); 

     {Pid, failed_region, Rid, Region, Ctr, XX} -> 
      NewGrid = failed_region(Grid, Pid, Rid, Region, Ctr, XX); 

     Else -> 
      erlang:display({unexpectedMessage, actor, Else}), 
      NewGrid = Grid 
    end, 
    globalManager(NewGrid). 


request_specific_cells(Grid, Pid, ReservationId, Coordinates, Ctr, XX) -> 
    {{Width, Height}, GridRows, MaxAllocationSize, FreeCells, {UnspecificRequests, NextId}, PendingRequests, BlockedRows} = Grid, 
    {X, Y, W, H} = Coordinates, 
    Rows   = lists:seq(Y,Y+H-1), 
    % Is one of the blocks that have to be reserved currently blocked? 
    BlockedRow = lists:foldl(fun(B, Acc) -> Acc xor search_list(B,BlockedRows) end, false, Rows), 
    Request  = lists:keyfind(ReservationId, 1, UnspecificRequests), 
    {ReservationId, _} = Request, 
    % Now we need the addresses of the sections in which the regions has to be reserved. 
    SubSectionIds = [ SPid || {_,SPid} <- [ lists:keyfind(Row, 1, GridRows) || Row <- Rows]], 
    % Storing request enables us to rollback if one of the registrations fails. 
    NewPendingRequests = PendingRequests ++ [{length(PendingRequests), 0, lists:map(fun(S) -> {S,null} end, SubSectionIds)}], 
    % Send a registration command with the needed section to each corresponding section manager. 
    [SPid ! {self(), request, Pid, ReservationId, length(PendingRequests), Coordinates, Ctr, XX} || SPid<- SubSectionIds], 
    NewBlockedRows = Rows ++ BlockedRows, 
    {{Width, Height}, GridRows, MaxAllocationSize, FreeCells, {UnspecificRequests, NextId}, NewPendingRequests, NewBlockedRows} 
    end. 


confirm_region(Grid, Pid, URid, Rid, Sid, Region, Section, Cttr, XX) -> 
    {Dimensions, GridRows, MaxAllocationSize, FreeCells, {UnspecificRequests, NextId}, PendingRequests, BlockedRows} = Grid, 
    {_,RY,_,_} = Region, 
    if 
     % All blocks have confirmed the reservation so the entire request is successful 
     (Ctr+1) == length(Spids) -> 
       NewUnspecificRequests = lists:keydelete(URid, 1, UnspecificRequests), 
       NewPendingRequests = lists:keydelete(Rid, 1, PendingRequests), 
       NewSpids = lists:keyreplace(Sid, 1, Spids, {Sid, Section}), 
       [Spid ! {self(), confirm_region, Sec} || {Spid, Sec} <- NewSpids], 
       Pid ! {self(), request_specific_cells, Rid, success}; 
     true -> 
       NewUnspecificRequests = UnspecificRequests, 
       % Safe the region that has to be marked/rolled back in the row 
       NewSpids = lists:keyreplace(Sid, 1, Spids, {Sid, Section}), 
       % Increase counter of confirmations 
       NewPendingRequests = lists:keyreplace(Rid, 1, PendingRequests, {Rid, Ctr+1, NewSpids}) 
    end, 
    NewBlockedRows = delete_list(RY, BlockedRows) 
    {Dimensions, GridRows, MaxAllocationSize, FreeCells, {NewUnspecificRequests, NextId}, NewPendingRequests, NewBlockedRows}. 



rowManager(Row) -> 
    receive 
     {Mid, request, Pid, URid, Rid, Region, Ctr, XX} -> 
      NewRow = request_region(Row, Mid, Pid, URid, Rid, Region, Ctr, XX); 
     Else -> 
      erlang:display({unexpectedMessage, rowManager, Else}), 
      NewRow = Row 
    end, 

    rowManager(NewRow). 

request_region(Row, Mid, Pid, URid, Rid, Coordinates, Ctr, XX) -> 
    {RY, Content, Modified} = Row, 
    {X,_,W,_} = Coordinates, 
    if 
     Modified == false -> 
       Free = region_is_empty({X,1,W,1}, Content), 
       if 
        Free -> NewModified = true, 
          NewContent = mark_region({X,1,W,1}, Content, reserved), 
          Mid ! {Pid, confirm_region, URid, Rid, self(), Coordinates, {X,1,W,1}, Ctr, XX}; 
        true -> NewModified = false, 
          NewContent = Content, 
          Mid ! {Pid, failed_region, Rid, Coordinates, Ctr, XX} 
       end; 
     true -> NewModified = false, 
       NewContent = Content, 
       Mid ! {Pid, failed_region, Rid, Coordinates, Ctr, XX} 
    end, 
    {RY, NewContent, NewModified}. 

이 코드는 리저버로 사용됩니다

request_specific_cells(FollowUpPid, ReservationId, {X, Y, Width, Height}, Ctr, XX) -> 
    FollowUpPid ! {self(), request_specific_cells, ReservationId, {X, Y, Width, Height}, Ctr, XX}, 
    receive 
     {FollowUpPid, request_specific_cells, ReservationId, SuccessOrFailure} -> 
     SuccessOrFailure 
end. 

내가 대답을 받기 전에 내가 알고 있기 때문에이 수신기가 사망 있다고 생각 확인/9에서

Pid ! {self(), request_specific_cells, Rid, success} 

그 함수는 항상 올바른 값으로 실행되지만 함수에서 항상 수신되는 것은 아닙니다.

+0

'분실 메시지'에 대해 들어 보지 못했습니다. 그러나 우리는 몇 가지 코드를 사용하여이 문제의 원인을 파악할 수 있습니다. 그러나 메시지가 예상대로 전달되지 않을 수 있습니다. 또한 대부분의 경우 수신자가 사망하면 메시지가 손실됩니다. –

+0

한 노드 내에서 메시지가 손실되지 않습니다! 보낸 메시지가 도착합니다. "틀린"장소에서 이러한 메시지를받을 수있는 일반 수신 패턴이 있습니까? – rvirding

+0

@MuzaayaJoshua 메시지와 주소가 모두 정확하기 때문에 내 문제의 원인은 수신자가 죽는 것입니다. 수신 된 메시지가 있기 전에 수신자가 왜 죽을 수 있습니까? 어떻게 이것을 막을 수 있습니까? 나는 내 문제에 대한 더 많은 정보를 줄 수있는 원래의 코드를 제공하려고 노력할 것이다. – Consec

답변

3

Erlang은 수신자가 살아있을 경우 동일한 노드 내에서 강력한 메시지 전달 보장을 제공합니다.

코드에 경쟁 조건이있는 것으로 보입니다. 같은 문제가있는 작은 응용 프로그램 예제를 작성하여 여기에 게시하십시오.

+0

간단한 버전 (350 줄 대신 120 줄)으로 줄이려고했지만 간단한 버전에서는 다른 작업의 지연을 시뮬레이트하는 시간 제한을 사용하면서 문제를 재현 할 수 없습니다. 어쨌든 도움을 주셔서 감사합니다. – Consec