2016-11-03 5 views
0

svc_run() 메서드를 통해 들어오는 RPC를 수신 대기하는 자식 프로세스를 생성하는 클라이언트 프로세스가 있습니다. 내가해야 할 일은 부모로부터 그 자식 프로세스를 죽인 다음 자식 프로세스를 다시 fork하여 새로운 CLIENT *에 새로운 RPC 서버를 제공하는 것입니다.RPC 서비스 다시 시작

여기에 관련된 나의 코드의 비트 : 내 서버 코드에서

// Client Main 
CLIENT* connectionToServer; 
int pipe[2]; 
int childPID; 
int parentPID; 

static void usr2Signal() 
{ 
    ServerData sd; 
    clnt_destroy(connectionToServer); 
    (void) read(pipe[0], &sd, sizeof(sd)); 


    // Kill child process. 
    kill(childPID, SIGTERM); 
    close(pipe[0]); 


    // RPC connection to the new server 
    CLIENT *newServerConn = 
     clnt_create(
      sd.ip, 
      sd.programNum, 
      1, 
      "tcp"); 

    if (!newServerConn) 
    { 
     // Connection error. 
     exit(1); 
    } 

    connectionToServer = newServerConn; 


    // Respawn child process. 
    if (pipe(pipe) == -1) 
    { 
     // Pipe error. 
     exit(2); 
    } 

    childPID = fork(); 
    if (childPID == -1) 
    { 
    // Fork error. 
    exit(3); 
    } 
    if (childPID == 0) 
    { 
    // child closes read pipe and listens for RPCs. 
     close(pipe[0]); 
     parentPID = getppid(); 
     svc_run(); 
    } 
    else 
    { 
    // parent closes write pipe and returns to event loop. 
    close(pipe[1]); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    /* Some initialization code */ 

    transp = svctcp_create(RPC_ANYSOCK, 0, 0); 
    if (transp == NULL) { 
     // TCP connection error. 
     exit(1); 
    } 

    if (!svc_register(transp, /*other RPC program args*/, IPPROTO_TCP)) 
    { 
     // RPC register error 
     exit(1); 
    } 



    connectionToServer = clnt_create(
     192.168.x.xxx, // Server IP. 
     0x20000123,  // Server RPC Program Number 
     1,    // RPC Version 
     "tcp"); 

    if (!connectionToServer) 
    { 
    // Connection error 
    exit(1); 
    } 

    // Spawn child process first time. 
    if (pipe(pipe) == -1) 
    { 
    // Pipe error 
    exit(1); 
    } 

    childPID = fork(); 
    if (childPID == -1) 
    { 
    // Fork error. 
    exit(1); 
    } 

    if (childPID == 0) 
    { 
    // Close child's read pipe. 
    close(pipe[0]); 
    parentPID = getppid(); 

    // Listen for incoming RPCs. 
    svc_run(); 
    exit (1); 
    } 


    /* Signal/Communication Code */ 

    // Close parent write pipe. 
    close(pipe[1]); 

    // Parent runs in event loop infinitely until a signal is sent. 
    eventLoop(); 
    cleanup(); 
} 

나는 새 연결을 시작하는 서비스 호출이있다. 이 호출은 서버의 다른 작업에 의해 호출됩니다.

// Server Services 
void newserverconnection_1_svc(int *unused, struct svc_req *s) 
{ 
    // This service is defined in the server code 

    ServerData sd; 
    /* Fill sd with data: 
     Target IP: 192.168.a.aaa 
     RPC Program Number: 0x20000321 
     ... other data 
    */ 

    connecttonewserver_1(&sd, connectionToServer); // A client service. 
} 

다시 내 클라이언트에서 나는 다음과 같은 서비스를 : 나는 새로운 연결을 시작할 때까지

// Client Service 
void connecttonewserver_1_svc(ServerData *sd, struct svc_req *s) 
{ 
    // Send the new server connection data to the parent client processs 
    // via the pipe and signal the parent. 
    write(pipe[1], sd, sizeof(sd)); 
    kill(parentPID, SIGUSR2); 
} 

내 문제는, 모든 것이 잘 실행됩니다. 내 오류 섹션 중 하나에 들어 가지 않지만 새 연결을 설정 한 후 약 5 초가 지나면 클라이언트가 응답하지 않게됩니다. 그것은 크래시가 발생하지 않고 자식 프로세스가 여전히 살아있는 것처럼 보입니다. 그러나 마우스의 클릭에 의해 부모 이벤트 루프에 정의 된 이벤트가 트리거 될 때 클라이언트는 더 이상 RPC를 수신하지 않거나 인쇄 문을 표시하지 않습니다. 자식 프로세스에 대해이 새로운 RPC 루프를 생성하기 위해 약간 잘못된 것이 있습니다. 그러나 나는 무엇을 볼 수 없습니다. 어떤 아이디어?

+0

'connectionToServer'에 할당되고'usr2Signal()'에서 사용 된 메모리는 해제되지 않습니다. 그런 다음'main()'에서 다시 사용합니다. –

+0

그래서 내 메인이 한 번 실행되고 실행하는 첫 번째 일이라고 생각합니다. main에있는 fork 후에 자식 프로세스는 자식 프로세스가 종료 될 때까지 "svc_run()"을 실행합니다. 부모는 eventLoop을 계속 수행하고 "usr2Signal"을 트리거하는 신호를 제외하고 무기한으로 실행합니다. 메인에서 아무 것도 메인에서 "connectionToServer"의 사용법을보고 있습니까? – MrJman006

+0

또한 "usr2Signal"에서 "clnt_destroy"가 할당 된 메모리를 정리하지 않습니까? – MrJman006

답변

0

그래서이 솔루션은 내가 찾던 결과를 얻었지만 확실히 완벽하지는 않습니다.

static void usr2Signal() 
{ 
    ServerData sd; 
    // clnt_destroy(connectionToServer); // Removed this as it closes the RPC connection. 
    (void) read(pipe[0], &sd, sizeof(sd)); 


    // Removed these. Killing the child process also seems to close the 
    // connection. Just let the child run. 
    // kill(childPID, SIGTERM); 
    // close(pipe[0]); 


    // RPC connection to the new server 
    CLIENT *newServerConn = 
     clnt_create(
      sd.ip, 
      sd.programNum, 
      1, 
      "tcp"); 

    if (!newServerConn) 
    { 
     // Connection error. 
     exit(1); 
    } 

    // This is the only necessary line. Note that the old 
    // connectionToServer pointer was not deregistered/deallocated, 
    // so this causes a memory leak, but is a quick fix to my issue. 
    connectionToServer = newServerConn; 


    // Removed the rest of the code that spawns a new child process 
    // as it is not needed anymore. 

} 
+0

좋아. 당신은 그 답을 정확하게 받아 들일 수 있습니다. –