0

In my program, when I was trying to close the master file descriptor, suddenly my program got crashed and I haven't seen any cores. Could someone help me with this? I am providing the code that I have used. This is the code I copied from the internet(http://www.rkoucha.fr/tech_corner/pty_pdip.html), The only difference is that instead of fork I spawn a thread. I know some small info I miss. Could someone please shed the light?

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;

}
Positive Navid
  • 2,481
  • 2
  • 27
  • 41
user2413497
  • 211
  • 2
  • 3
  • 7
  • Core dump _could_ be missing because it's disabled. In this case: `ulimit -c unlimited` enables core dump. More about this I found in: [SO: Core dump file is not generated](https://stackoverflow.com/q/7732983/7478597). – Scheff's Cat Jul 27 '17 at 09:06
  • Is a spawned thread (in contrast to a forked one) restricted to the lifetime of the "spawner", i.e. the terminal context? That would explain termination "with" the terminal. – Yunnosch Jul 27 '17 at 09:09
  • I want to understand why the program is crashed. Core missing is not a problem. – user2413497 Jul 27 '17 at 09:40
  • Hi Yunnosch. I didn't understand your question. I am closing the thread once my operation is completed. – user2413497 Jul 27 '17 at 09:42
  • What is the consequene if I don't close the master – user2413497 Jul 28 '17 at 11:01

1 Answers1

0

execute_ptcoi_commands_sequence seems to contain steps necessary to 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)
    . . .

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

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

rustyx
  • 80,671
  • 25
  • 200
  • 267