none
서로다른 프로세스간의 SendMessage 통신 RRS feed

  • 질문

  • 안녕하세요,

    A, B 두 프로세스간 SendMessage를 이용하여 WM_COPYDATA 메시지 통신을 합니다.

    A라는 프로세스에서 "COMMAND_MESSAGE"를 SendMessage로 보냈고,

    B라는 프로세스의 OnCopyData 함수에서 "COMMAND_MESSAGE"를 받아 곧바로 Sleep(90000) 90초 대기 후 A 프로세스에게 "COMMAND_MESSAGE_DONE" 메시지를 SendMessage로 다시 보내도록 샘플 프로그램을 작성하면.. B프로세스에의 OnCopyData 함수에 메시지 수신에 대한 결과를 AfxMessageBox로 표시하도록 하여도, 가끔 "COMMAND_MESSAGE_DONE"메시지를 못 받습니다.

    A 프로세스의 SendMessage 리턴 값을 1이나, B 프로세스에서는 메시지를 놓치는 경우가 있습니다.(Debug 모드가 아닌 Release 모드에서 테스트하셔야 합니다.)

    해당 문제를 피하려면 프로그램 구조를 바꾸면 되는데, 위와 같이 메시지가 사라지는 원인이 궁금하여 문의 드립니다.

    SendMessage로 꼬리 물기를 많이 하면 Stack overflow가 발생하는 것은 알고 있으나, 위와 같은 경우 stack overflow 에러가 없는 상태에서 메시지가 누락되는 것과 같은 현상이 발생합니다.

    감사합니다.

    2012년 3월 19일 월요일 오전 2:53

답변

  • 저희도 비슷한 프로그램을 많이 만들어봤지만, 보낸 메시지를 놓친적은 없습니다. 만약, 그런 경우가 있다면
    WM_COPYDATA 는 사용할수 없는 기술로 분류될것이기 때문에 문제가 있었다고 할지라도 이미 수정되었을것입니다.

      

    오히려, 보냈는데 못받았다기보다는 보내지 못하는 경우가 더 많습니다. 예를들어, WM_COPYDATA 를 사용할때 전송할 데이터의
    구성을 잘못하여 전송을 제대로 못했거나 전송했다고 생각했지만 코드 구성에 오류가 있어서 해당 코드가 제대로 실행되지
    않았을 경우도 고려하셔야 합니다.
     

    또한 메시지 전송 또는 수신시에 멀티 스레드를 사용하면서 Lock 을 제대로 하지 않은 경우에도 비슷한 문제가 발생할수 있습니다.

    P.S  간략하게라도 어떻게 메시지를 구성해서 전송했고 수신을 하는지에 대한 코드가 같이 있어야지
                좀더 정확한 조언을 해드릴수 있을것 같습니다.

    2012년 3월 19일 월요일 오전 4:01
    중재자
  • 편의상 두 프로그램을 A(전송), B(수신후 완료 전송) 라고 가정하겠습니다.

     

    A 프로그램이 전송한 메시지를 B 프로그램이 OnCopyData 함수에서 수신하는데, 이 함수내에서
    SendMessage 를 이용하여 WM_COPYDATA 메시지를 A 프로그램에 전송하고 있다는 뜻입니까?

     

    이런구조라면 A와 B가 주고받을때마다 이전에 보낸 작업이 완료되지 않은 상태로 누적되기 때문에
    문제가 발생할수 밖에 없습니다. 보통 이런 상황에서는 메모리 관련된 오류가 발생하기도 하고
    구조에 따라서는 메시지를 수신하지 못하는 경우도 발생합니다. ( 메시지 큐가 가득차버림 )
    이런 상황이 지속되면 단순히 메시지를 수신못하는 상황이 아니라 어떤한 메시지도 주고 받지 못하는 상황이 발생하기도 합니다.
    즉, 몇번 메시지를 수신못하는 상황이 반복된후에 해당 프로그램이 어떤 메시지도 주고받지 못하는 상황이 될수도 있습니다.
    ( 프로그램을 종료했다가 실행해도 안되어서 컴퓨터를 리부팅해야 하는 경우도 있습니다. )

     

    이문제는 WM_COPYDATA 의 문제가 아니라 구조를 잘못잡으셔서 메시지처리가 완료되지 못한
    상태로 누적되어서 그렇습니다. OnCopyData 쪽에서 PostMessage 함수를 이용하여 OnCopyData
    함수가 완료된 뒤에 응답을 A로 전송할수 있도록 구조를 변경하시면 문제가 없어질것입니다.

    2012년 3월 19일 월요일 오전 8:55
    중재자
  • 제가 몇가지 테스트를 해보았는데, 상황이 지속되면 해당 프로그램이 WM_COPYDATA 뿐만 아니라 자신 스스로에게 전달하는
    메시지도 수신을 못하는 상황이 발생했습니다. 메시지 큐 또는 메시지 처리 시스템에 어떤 문제가 발생했다는 뜻입니다.
    이 문제는 컴퓨터를 리부팅 할때까지도 지속되는것으로 보아 응용프로그램단에 문제는 아닐듯합니다.

    하지만, 이 문제가 메시지큐에 의한것인지 메시지 처리를 관리하는쪽의 문제인지는 확인할 방법이 없었습니다. 
    여러가지 추측은 해볼수 있지만, 그건은 저 개인적인 추측일뿐 객관적인 내용이 아니기 때문에 이야기 드리기는
    어려울듯합니다. 차후에라도 이 문제에 관련되어서 객관적인 자료나 증거를 발견하게되면 이글에 리플로 남겨드리겠습니다.

     

    2012년 3월 21일 수요일 오전 2:46
    중재자

모든 응답

  • 저희도 비슷한 프로그램을 많이 만들어봤지만, 보낸 메시지를 놓친적은 없습니다. 만약, 그런 경우가 있다면
    WM_COPYDATA 는 사용할수 없는 기술로 분류될것이기 때문에 문제가 있었다고 할지라도 이미 수정되었을것입니다.

      

    오히려, 보냈는데 못받았다기보다는 보내지 못하는 경우가 더 많습니다. 예를들어, WM_COPYDATA 를 사용할때 전송할 데이터의
    구성을 잘못하여 전송을 제대로 못했거나 전송했다고 생각했지만 코드 구성에 오류가 있어서 해당 코드가 제대로 실행되지
    않았을 경우도 고려하셔야 합니다.
     

    또한 메시지 전송 또는 수신시에 멀티 스레드를 사용하면서 Lock 을 제대로 하지 않은 경우에도 비슷한 문제가 발생할수 있습니다.

    P.S  간략하게라도 어떻게 메시지를 구성해서 전송했고 수신을 하는지에 대한 코드가 같이 있어야지
                좀더 정확한 조언을 해드릴수 있을것 같습니다.

    2012년 3월 19일 월요일 오전 4:01
    중재자
  • 간단한 샘플 프로그램 작성으로 테스트 가능합니다.

    A, B 프로그램 공히 WM_COPYDATA 메시지를 SendMessage 함수로 전달하는 함수를 만듭니다.

    A, B 프로그램은 모두 Dialog based로 작성하고, 위 함수는 A, B 프로그램의 이름을 FindWindow함수로 찾은 후

    ::SendMessage(Handle, WM_COPYDATA, NULL, COPYDATASTRUCT&) 형식으로 메시지를 보냅니다.

    여기서 전달되는 COPYDATASTRUCT에는 임의로 작성된 Header와 Data로 구성되며, Header는 "MISSING_MESSAGE", "MISSING_MESSAGE_DONE" 값들이 됩니다.

    A 프로그램은

    1. 위 함수로 "MISSING_MESSAGE"를 보내고..

    2. OnCopyData(...) 함수에서 "MISSING_MESSAGE_DONE"을 받으면 AfxMessageBox("MISSING_MESSAGE_DONE"); 을 합니다.

    B 프로그램은

    1. OnCopyData(...)함수에서 "MISSING_MESSAGE"를 받으면 곧바로 Sleep(90초)한 후

         위 함수를 이용해 다시 "MISSING_MESSAGE_DONE"을 보냅니다.

    이를 Release mode로 테스트해 보면 B에서는 Sleep 후 DONE에 대한 Return 값이 항상 1이나,

    A에서는 "MISSING_MESSAGE_DONE" 메시지가 표시될 때도 있고, 안될 때도 있습니다.

    참고로 Lock, Unlock 하는 것 없고, 새로 실행하는 Thread에서 해당 메시지를 처리하지 않습니다.

    Dialog based 로 작성하여 Button에 의한 SendMessage 함수 호출입니다.

    감사합니다.

    2012년 3월 19일 월요일 오전 4:41
  • 편의상 두 프로그램을 A(전송), B(수신후 완료 전송) 라고 가정하겠습니다.

     

    A 프로그램이 전송한 메시지를 B 프로그램이 OnCopyData 함수에서 수신하는데, 이 함수내에서
    SendMessage 를 이용하여 WM_COPYDATA 메시지를 A 프로그램에 전송하고 있다는 뜻입니까?

     

    이런구조라면 A와 B가 주고받을때마다 이전에 보낸 작업이 완료되지 않은 상태로 누적되기 때문에
    문제가 발생할수 밖에 없습니다. 보통 이런 상황에서는 메모리 관련된 오류가 발생하기도 하고
    구조에 따라서는 메시지를 수신하지 못하는 경우도 발생합니다. ( 메시지 큐가 가득차버림 )
    이런 상황이 지속되면 단순히 메시지를 수신못하는 상황이 아니라 어떤한 메시지도 주고 받지 못하는 상황이 발생하기도 합니다.
    즉, 몇번 메시지를 수신못하는 상황이 반복된후에 해당 프로그램이 어떤 메시지도 주고받지 못하는 상황이 될수도 있습니다.
    ( 프로그램을 종료했다가 실행해도 안되어서 컴퓨터를 리부팅해야 하는 경우도 있습니다. )

     

    이문제는 WM_COPYDATA 의 문제가 아니라 구조를 잘못잡으셔서 메시지처리가 완료되지 못한
    상태로 누적되어서 그렇습니다. OnCopyData 쪽에서 PostMessage 함수를 이용하여 OnCopyData
    함수가 완료된 뒤에 응답을 A로 전송할수 있도록 구조를 변경하시면 문제가 없어질것입니다.

    2012년 3월 19일 월요일 오전 8:55
    중재자
  • 네.. 방법은 말씀해주신 대로 OnCopyData 함수에서 PostMessage 함수를 이용하여 필요 처리를 하도록 하거나, ReplyMessage 함수를 사용하면 해결되네요.

    그렇다면 한가지 궁금한 것이 있습니다.

    서로 다른 스레드 간 SendMessage는 아래와 같이 처리된다고 합니다.

    1. SendMessage 호출 시 시스템 큐에 해당 메시지 등록 후 Reply Message Queue에 메시지가 들어오기를 기다림

    2. SendMessage 수신 측에서 시스템 큐의 메시지를 처리 후, 송신 측 Reply Message Queue에 결과를 등록

    3. SendMessage를 보낸 측에서는 Reply Message Queue의 메시지 확인 후 대기(블럭킹) 해제

    여기서 문제가된 MISSING_MESSAGE_DONE 메시지가 사라지는 경우는 어떻게 해석할 수 있을까요?

    1번 SendMessage 호출 시 시스템 큐에 해당 메시지를 등록하게 되어있는데, 해당 메시지가 사라졌다는 것은 시스템 큐가 Full되어서 전송 자체가 안되었다고 보는 것이 맞겠는지요?

    (OS에 시스템 큐가 하나이고, 하나의 메시지가 처리되기 전까지는 이후 메시지가 처리되지 않는다면

    다른 프로세스에서 발생하는 SendMessage도 있을테니 충분히 Qeueu full이 발생할 수 있다고 생각합니다. 다만,)

    해결할 방법은 있는데 명확한 이유를 모르니 목에 가시가 걸린 것 같아 문의드려 봅니다.

    감사합니다.

    2012년 3월 20일 화요일 오전 5:25
  • 제가 몇가지 테스트를 해보았는데, 상황이 지속되면 해당 프로그램이 WM_COPYDATA 뿐만 아니라 자신 스스로에게 전달하는
    메시지도 수신을 못하는 상황이 발생했습니다. 메시지 큐 또는 메시지 처리 시스템에 어떤 문제가 발생했다는 뜻입니다.
    이 문제는 컴퓨터를 리부팅 할때까지도 지속되는것으로 보아 응용프로그램단에 문제는 아닐듯합니다.

    하지만, 이 문제가 메시지큐에 의한것인지 메시지 처리를 관리하는쪽의 문제인지는 확인할 방법이 없었습니다. 
    여러가지 추측은 해볼수 있지만, 그건은 저 개인적인 추측일뿐 객관적인 내용이 아니기 때문에 이야기 드리기는
    어려울듯합니다. 차후에라도 이 문제에 관련되어서 객관적인 자료나 증거를 발견하게되면 이글에 리플로 남겨드리겠습니다.

     

    2012년 3월 21일 수요일 오전 2:46
    중재자