2017-07-27 75 views
0

在我的程序中,當我試圖關閉主文件描述符時。突然間,我的程序崩潰了,我還沒有看到任何內核。有人能幫我解決這個問題嗎?我正在提供我用過的代碼。這是我從互聯網上覆制的代碼(http://rachid.koucha.free.fr/tech_corner/pty_pdip.html),唯一的區別就是代替了fork我產生了一個線程。我知道我想念的一些小信息。有人可以擺脫燈光。當主終端關閉時程序終止

在此先感謝!

int ScalingCommandReceiver::execute_ptcoi_commands_sequence(const char * bc_name, std::vector<cmd_output_pair>& cmd_seq, std::string& output_str) 
{ 
    int fdm, fds; 
    int rc; 

    output_str.clear(); 

    fdm = posix_openpt(O_RDWR); 
    if (fdm < 0) 
    { 
     output_str.append("Error on posix_openpt() \n"); 
     return -1; 
    } 

    rc = grantpt(fdm); 
    if (rc != 0) 
    { 
     output_str.append("Error on grantpt() \n"); 
     close(fdm); 
     return -1; 
    } 

    rc = unlockpt(fdm); 
    if (rc != 0) 
    { 
     output_str.append("Error on unlockpt() \n"); 
     close(fdm); 
     return -1; 
    } 

    // Open the slave side ot the PTY 
    fds = open(ptsname(fdm), O_RDWR); 

    if (fds < 0) 
    { 
     output_str.append("Error on posix_openpt() \n"); 
     close(fdm); 
     return -1; 
    } 


    std::string cp_name ("bc3"); 

    pt_session_struct *file_refs = NULL; 
    file_refs = (pt_session_struct*) ::malloc(sizeof(pt_session_struct)); 

    if (file_refs == NULL) { 
     output_str.append("ERROR: Failed to create the struct info for the thread! \n"); 
     close(fdm); 
     close(fds); 
     return -1; 
    } 


    file_refs->fds = fds; 
    file_refs->cp_name = (char*)bc_name; 

    //Spawn a thread 
    if (ACE_Thread::spawn(ptcoi_command_thread, file_refs, THR_DETACHED) < 0) { 
     output_str.append("ERROR: Failed to start ptcoi_command_thread thread! \n"); 
     close(fdm); 
     close(fds); 
     ::free(file_refs); 
     return -1; 
    } 

    int i = 0; 
    while (i <= cmd_seq_dim) 
    { 
     char buffer[4096] = {'\0'}; 
     ssize_t bytes_read = 0; 

     int read_res = 0; 
     do 
     { 

      // get the output in buffer 
      if((read_res = read(fdm, (buffer + bytes_read), sizeof(buffer))) > 0) 
      { 
       // The number of bytes read is returned and the file position is advanced by this number. 
       // Let's advance also buffer position. 
       bytes_read += read_res; 
      } 
     } 
     while((read_res > 0) && !strchr(buffer, cpt_prompt) && (std::string(buffer).find(ptcoi_warning) == std::string::npos)); 

     if (bytes_read > 0) // No error 
     { 

      // Send data on standard output or wherever you want 
      //Do some operations here 

     } 
     else 
     { 
      output_str.append("\nFailed to read from master PTY \n"); 
     } 

     if(i < cmd_seq_dim) 
     { 
      // Send data on the master side of PTY 
      write(fdm, cmd_seq[i].first.c_str(), cmd_seq[i].first.length()); 

     } 
     ++i; 
    } // End while 


    if(/*have some internal condition*/) 
    { 
     close(fdm); //Here I observe the crash :-(
     return 0; // OK 
    } 
    else 
    { 
     output_str.append ("\nCPT printouts not expected.\n"); 
     close(fdm); 
     return -1; // Failure 
    } 

    close(fdm); 
    return 0; // OK 

} 

ACE_THR_FUNC_RETURN ScalingCommandReceiver::ptcoi_command_thread(void* ptrParam) 
{ 
     pt_session_struct* fd_list = (pt_session_struct*) ptrParam; 

     struct termios slave_orig_term_settings; // Saved terminal settings 
     struct termios new_term_settings; // Current terminal settings 


     int fds = fd_list->fds; 

     char* cp_name = fd_list->cp_name; 

     ::free (fd_list); 


     // Save the defaults parameters of the slave side of the PTY 
     tcgetattr(fds, &slave_orig_term_settings); 

     // Set RAW mode on slave side of PTY 
     new_term_settings = slave_orig_term_settings; 
     cfmakeraw (&new_term_settings); 
     tcsetattr (fds, TCSANOW, &new_term_settings); 

     int stdinCopy, stdoutCopy, stdErr; 

     stdinCopy = dup (0); 

     stdoutCopy = dup (1); 

     stdErr = dup (2); 

     // The slave side of the PTY becomes the standard input and outputs of the child process 
     close(0); // Close standard input (current terminal) 
     close(1); // Close standard output (current terminal) 
     close(2); // Close standard error (current terminal) 

     dup(fds); // PTY becomes standard output (0) 
     dup(fds); // PTY becomes standard output (1) 
     dup(fds); // PTY becomes standard error (2) 


     // Now the original file descriptor is useless 
     close(fds); 


     // Make the current process a new session leader 
     //setsid(); 

     // As the child is a session leader, set the controlling terminal to be the slave side of the PTY 
     // (Mandatory for programs like the shell to make them manage correctly their outputs) 
     ioctl(0, TIOCSCTTY, 1); 

     // Execution of the program 
     char PTCOI [64] = {0}; 
     snprintf(PTCOI, sizeof(PTCOI), "/opt/ap/mas/bin/mas_cptaspmml PTCOI -cp %s -echo 7", cp_name); 

     system(PTCOI); //my command 


     close(0); // Close standard input (current terminal) 
     close(1); // Close standard output (current terminal) 
     close(2); // Close standard error (current terminal) 


     dup2 (stdinCopy, 0); 
     dup2 (stdoutCopy, 1); 
     dup2 (stdErr, 2); 


     close (stdinCopy); 
     close (stdoutCopy); 
     close (stdErr); 


     return 0; 

} 
+0

核心轉儲_could_因缺失而丟失。在這種情況下:'ulimit -c unlimited'啓用核心轉儲。更多關於這個我發現:[SO:核心轉儲文件沒有生成](https://stackoverflow.com/q/7732983/7478597)。 – Scheff

+0

是否是一個衍生線程(與分叉線程相比)限制在「spawner」的生命週期中,即終端上下文?這將解釋「與」終端的終止。 – Yunnosch

+0

我想了解爲什麼該程序崩潰。核心缺失不是問題。 – user2413497

回答

0

execute_ptcoi_commands_sequence似乎包含了必要的步驟來daemonize your process

// The slave side of the PTY becomes the standard input and outputs of the child process 
    close(0); // Close standard input (current terminal) 
    close(1); // Close standard output (current terminal) 
    close(2); // Close standard error (current terminal) 
    . . . 

這意味着forksetsid在那裏從控制終端分離,讓你的進程可以超出你的終端會話生存。

刪除fork後,您的進程仍與控制終端相關聯,並可能在終端在關閉時發送SIGHUP時終止。

+0

'fork'不會與控制終端分離(即使關閉所有連接到它的FD後),但是會發出'setsid'。 – pynexj

+0

我想說,爲了從終端上分離,兩者都是需要的。 – rustyx

+0

是的,因爲'setsid'需要*調用進程不是進程組的領導*。 – pynexj