2016-11-03 12 views
0

svc_run()メソッドを使用して、着信RPCをリスンする子プロセスをフォークするクライアントプロセスがあります。私がする必要があるのは、その子プロセスを親プロセスから削除し、子プロセスを再フォークして新しい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

。あなたは答えを正しいものとして受け入れることができます –

関連する問題