2016-11-03 6 views
0

У меня есть клиентский процесс, который заставляет дочерний процесс прослушивать входящие RPC с помощью метода svc_run(). То, что мне нужно сделать, это убить этот дочерний процесс от родителя, а затем повторно развернуть дочерний процесс, предоставив ему новый КЛИЕНТ * на новый сервер 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

Итак, я думаю, что мой главный исполняемый только один раз и является первым, что нужно выполнить. После основной вилки мой дочерний процесс запускает «svc_run()» до тех пор, пока дочерний процесс не будет завершен. Родитель продолжается до eventLoop и работает там неограниченное время, за исключением сигнала, который запускает «usr2Signal». Нигде в основном я вижу использование «connectionToServer» в основном? – MrJman006

+0

Кроме того, не «clnt_destroy» в моем «usr2Signal» очищает выделенную память? – 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

Хорошо. Вы можете принять свой ответ как правильно, тогда –