LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-06-2021, 07:16 AM   #1
somanyquestions
Member
 
Registered: Jan 2019
Distribution: Ubuntu, Debian, Buildroot
Posts: 34

Rep: Reputation: Disabled
How kill child process without read() hanging in the parent process?


There is an external program I'm calling from within my C/C++ program, by using fork() and execl(), and also redirecting stdio with dup2() to be able to read the output from the external program. It's based on this code: A simple popen2 implementation

In another thread just started, the timeout handling is done.
Then I make calls to read() on the out file handle, in a loop, writing what's read to a stream.
Now that external program waits for something on the system to happen - which might not happen, so after a while, I'd like to call it a timeout and end the child process (from the extra thread).
Whether sending SIGTERM or SIGKILL, changing the order of closing file handles w.r.t. to that, the result is always that the last call to read() hangs forever.

Added: Seems even if the process exits in time, the read() hangs. That did not happen when I used the regular popen() to start the process instead of popen2(), but since I need the PID to terminate the process, I'm using the latter.

I have found discussions about a problem with read() in a somewhat similar situation, and it was suggested that the SIGCHLD must be ignored in the parent process. That doesn't help, though.

Is there something wrong per se in doing things this way, that cause this read() to hang?

Code:
int exec_proc2(std::string cmd, std::ostream & outputStream, unsigned timeoutMilsecs)
{
    constexpr int bufsize = 128;
    std::array<char, bufsize> buffer;
    
    int inf, outf;
    auto pid = popen2( cmd.c_str(), &inf, &outf );
    close( inf ); // writing to process not used, we're only reading
    if (pid < 0)
    {   close( outf );
        return -1;
    }
    
    std::atomic<bool> notDone = true;
    std::atomic<bool> timedOut = false;
    thread timeoutTask( [&]
        {   TimeoutWatch tw(timeoutMilsecs, true);
            while (notDone && !tw.TimedOut())
            {   sleep(0.1);
            }
            if (tw.TimedOut())
            {   close( outf );
                int ret = kill( pid, SIGKILL );
                if (ret != 0)
                {   // this never failed so far
                }
                notDone = false;
                cout << "DBG: TIMEOUT@exec_proc2" << endl; // this is always printed after the timeout time
                timedOut = true;
            }
        } );
    
    size_t count;
    do
    {   if ((count = read( outf, buffer.data(), bufsize )) > 0)
  	    {   outputStream.write( buffer.data(), count );
  	    }
    } while(count > 0 && !timedOut);
    cout << "DBG: joining...@exec_proc2" << endl; // this line is never printed, so it hangs above already
    notDone = false; // for the case that the read() loop exits earlier than the timeout thread: tell the thread it's over
    timeoutTask.join();
    
    close( outf );
    return timedOut ? -2 : 0;
}
 
Old 10-06-2021, 07:53 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
This popen2 might be incomplete.
After fork, when pid!=0:
Code:
    close (p_stdin[READ]);
    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    close (p_stdout[WRITE]);
    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

Last edited by NevemTeve; 10-06-2021 at 10:29 AM.
 
2 members found this post helpful.
Old 10-06-2021, 11:22 AM   #3
somanyquestions
Member
 
Registered: Jan 2019
Distribution: Ubuntu, Debian, Buildroot
Posts: 34

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
This popen2 might be incomplete.
After fork, when pid!=0:
Code:
    close (p_stdin[READ]);
    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    close (p_stdout[WRITE]);
    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];
Thanks! Yes you're right. I meanwhile found this here, and the accepted answer mentions the same:
example at SO
 
  


Reply

Tags
exec, fork, kill, linux, process



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
killng parent process without killing child process (Linux C programming) lettuce84@naver.com Linux - Newbie 3 07-24-2015 08:37 AM
Does child process get killed ,when we kill parent process.? gaurav_s Linux - Newbie 1 08-01-2014 12:50 AM
Kill a zombie process - which process is the parent that I should kill? Mountain Linux - General 3 12-31-2011 02:44 PM
Can a child process kill the parent process ? sree_ec Programming 8 11-20-2010 05:37 AM
When I kill parent process, child isn't killed BengeBoy Linux - Software 0 08-19-2004 04:38 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:00 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration