当主终端关闭时,程序终止

时间:2021-08-12 01:02:47

In my program, When I am trying to close the master file descriptor. Suddenly my program got crashed and I haven't seen any cores. Could someone help me on this. I am providing the code that I have used. This is the code I copied from internet(http://rachid.koucha.free.fr/tech_corner/pty_pdip.html), Only difference is instead of fork I spawn a thread. I know some small info I miss. could someone please shed the light.

在我的程序中,当我试图关闭主文件描述符时。突然,我的程序崩溃了,我没有看到任何核心。有人可以帮我这个吗?我提供的是我用过的代码。这是我从互联网上复制的代码(http://rachid.koucha.free.fr/tech_corner/pty_pdip.html),唯一的区别是代替fork我生成一个线程。我知道一些我想念的小信息。有人可以请光明。

Thanks in advance!!!

提前致谢!!!

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;

}

1 个解决方案

#1


0  

execute_ptcoi_commands_sequence seems to contain steps necessary to daemonize your process:

execute_ptcoi_commands_sequence似乎包含守护进程所需的步骤:

    // 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)
    . . .

Which means the fork and setsid were there to detach from the controlling terminal, so that your process can survive beyond your terminal session.

这意味着fork和setsid可以从控制终端分离,这样您的进程就可以在终端会话之外生存。

After you removed the fork your process remains associated with the controlling terminal and probably terminates when the terminal sends a SIGHUP on close.

删除分支后,您的进程仍然与控制终端关联,并可能在终端发送SIGHUP时终止。

#1


0  

execute_ptcoi_commands_sequence seems to contain steps necessary to daemonize your process:

execute_ptcoi_commands_sequence似乎包含守护进程所需的步骤:

    // 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)
    . . .

Which means the fork and setsid were there to detach from the controlling terminal, so that your process can survive beyond your terminal session.

这意味着fork和setsid可以从控制终端分离,这样您的进程就可以在终端会话之外生存。

After you removed the fork your process remains associated with the controlling terminal and probably terminates when the terminal sends a SIGHUP on close.

删除分支后,您的进程仍然与控制终端关联,并可能在终端发送SIGHUP时终止。