Linux child process exit

How do you close a Qt child process and get the child process to execute cleanup code?

I am starting a process in Linux/Qt and then starting some child processes using QProcess. Then eventually I want to close the child processes gracefully (aka execute some clean up code). The child processes are using QSharedMemory and right now when I call QProcess::close() the child processes are closing without calling QSharedMemory::detach() and the result is that all the processes are closed. but there is left over shared memory that is not cleaned up. I have the code for the child process and in the code there is the function cleanup() . How does the parent process close the QProcess in such a manner so that the child process will execute cleanup() ?

There are many many different ways to do this. The goal here is that: I wanted to see what is the «common» or «best practices» approach that is used in the Qt framework.

I am not a Qt master. So I will leave this open until I get a response from someone with lots of Qt experience.

3 Answers 3

I got the child to execute Qt cleanup code using unix signal handlers.

Here’s a high level explanation:

  • the parent opens the child process using QProcess
  • processing occurs
  • the parent closes the child process using QProcess::terminate() which raises the SIGTERM signal on the child
    • (don’t use QProcess::close() because it doesn’t raise the SIGTERM signal)

    Child process code to handle unix SIGTERM signal:

    static void unixSignalHandler(int signum) < qDebug("DBG: main.cpp::unixSignalHandler(). signal = %s\n", strsignal(signum)); /* * Make sure your Qt application gracefully quits. * NOTE - purpose for calling qApp->exit(0): * 1. Forces the Qt framework's "main event loop `qApp->exec()`" to quit looping. * 2. Also emits the QCoreApplication::aboutToQuit() signal. This signal is used for cleanup code. */ qApp->exit(0); > int main(int argc, char *argv[]) < QCoreApplication a(argc, argv); MAINOBJECT mainobject; /* * Setup UNIX signal handlers for some of the common signals. * NOTE common signals: * SIGINT: The user started the process on the command line and user ctrl-C. * SIGTERM: The user kills the process using the `kill` command. * OR * The process is started using QProcess and SIGTERM is * issued when QProcess::close() is used to close the process. */ if (signal(SIGINT, unixSignalHandler) == SIG_ERR) < qFatal("ERR - %s(%d): An error occurred while setting a signal handler.\n", __FILE__,__LINE__); >if (signal(SIGTERM, unixSignalHandler) == SIG_ERR) < qFatal("ERR - %s(%d): An error occurred while setting a signal handler.\n", __FILE__,__LINE__); >// executes mainbobject.cleanupSlot() when the Qt framework emits aboutToQuit() signal. QObject::connect(qApp, SIGNAL(aboutToQuit()), &mainobject, SLOT(cleanupSlot())); return a.exec(); > 

    Conclusion:

    I think this is a good solution because:

    • let’s the parent close the child process in such a way that the child process executes cleanup
    • if the parent closes mistakenly and leaves the child process running, the user/sysadmin can kill the leftover child process using kill command and the child process will still cleanup after itself before closing

    p.s. «why not just do the cleanup code directly in the signal handler entry point?»

    The short answer is because you can’t. Here’s an explanation as to why you can’t execute your Qt cleanup code in the unix signal handler function. From Qt documentation «Calling Qt Functions From Unix Signal Handlers»:

    You can’t call Qt functions from Unix signal handlers. The standard POSIX rule applies: You can only call async-signal-safe functions from signal handlers. See Signal Actions for the complete list of functions you can call from Unix signal handlers.

    Источник

    exit child process, safely

    Here one of the processes exited and also its parent while I comment this line exit if ( $t == 2 ); and run ps -fu $LOGNAME | grep [f]ork again, I found:

     i59tib 624 623 1 16:29:11 pts/34 0:04 /usr/bin/perl ./fork.pl i59tib 629 623 1 16:29:11 pts/34 0:04 /usr/bin/perl ./fork.pl i59tib 628 623 1 16:29:11 pts/34 0:04 /usr/bin/perl ./fork.pl i59tib 625 623 1 16:29:11 pts/34 0:04 /usr/bin/perl ./fork.pl i59tib 627 623 1 16:29:11 pts/34 0:04 /usr/bin/perl ./fork.pl i59tib 626 623 1 16:29:11 pts/34 0:04 /usr/bin/perl ./fork.pl i59tib 623 4766 0 16:29:11 pts/34 0:00 /usr/bin/perl ./fork.pl 

    2 Answers 2

    How can I exit the child process without exiting the parent?

    The parent exited because the parent reached the end of the program, so tell the parent to do something, anything! For example,

    No, parent waits for all process because of waitpid(-1, 0); and I know this because I tested it. If you made the exit commented the parent will not exit till the children finish.

    If you don’t believe me, the test you posted that proves the opposite and the documentation, then why did you bother asking?

    The parent will behave exactly the same no matter how the child exits. It doesn’t matter if the exit system call is called as a result of Perl exiting main or if your child called Perl’s exit or POSIX::_exit , or if the child died from a signal.

    How can I exit the child process without exiting the parent?

    try below program here Child dies before parent.

    #!/usr/bin/perl print "i am about to fork\n"; my $pid = fork(); if($pid > 0) < my $i = 0; while($i<5) < print "PARENT--I will be keep on running\n"; sleep(5); $i++; >print "PARENT-- I m about to dead\n"; > else < $i = 0; while($i <3) < print "CHILD-- I will be dead before than parent\n"; #exit(0); you can put exit like this also. sleep(2); $i++; >print "CHILD-- I m about to dead\n"; > 

    Below is the sample output.

    i am about to fork PARENT--I will be keep on running CHILD-- I will be dead before than parent CHILD-- I will be dead before than parent CHILD-- I will be dead before than parent PARENT--I will be keep on running CHILD-- I m about to dead PARENT--I will be keep on running PARENT--I will be keep on running PARENT--I will be keep on running PARENT-- I m about to dead 

    You can exist with any supported signal also.You can get different signal list here. You can use the same sample code at loop too but make sure here that there will be one super parent and other will be their child.

    please run this program to understand more about this. Always super-parent will get exited at the end no matter you use exit or not.

    #!/usr/bin/perl print "i $$ am about to fork\n"; my @children_pids; my $n = 3; for my $i ( 0..($n-1) ) < my $pid = fork(); if($pid >0) < print "i m $$ child of".getppid()."\n"; push @children_pids, $pid; >else < print "I $$ is about to dead. I am child of".getppid()."\n"; exit(); >> waitpid $_, 0 for @children_pids; print "$$ is finished\n"; 

    typical output at my system of above program is as below.

    i 3919 am about to fork i m 3919 child of3092 I 3920 is about to dead. I am child of3919 i m 3919 child of3092 i m 3919 child of3092 I 3921 is about to dead. I am child of3919 I 3922 is about to dead. I am child of3919 3919 is finished 

    Parent will wait all its child to get exit;then only it will exit.

    Источник

    What is the difference between using _exit() & exit() in a conventional Linux fork-exec?

    I’ve been trying to figure out how the fork-exec mechanism is used inside Linux. Everything was going on according to the plan until some web pages started to confuse me. It is said that a child process should strictly use _exit() instead of a simple exit() or a normal return from main() . As I know, Linux shell fork-execs every one of the external commands; assuming what I said above is true, the conclusion is that none of these external commands nor any other execution happening inside the Linux shell can do normal return! Wikipedia & some other webpages claim we’ve got to use _exit() just to prevent a child process causing deletion of parent’s temporary files while a probable double flushing of stdio buffers may happen. though I understand the former, I have no clues how a double flushing of buffers could be harmful to a Linux system. I’ve spent my whole day on this. Thanks for any clarification.

    4 Answers 4

    You should use _exit (or its synonym _Exit ) to abort the child program when the exec fails, because in this situation, the child process may interfere with the parent process’ external data (files) by calling its atexit handlers, calling its signal handlers, and/or flushing buffers.

    For the same reason, you should also use _exit in any child process that does not do an exec , but those are rare.

    In all other cases, just use exit . As you partially noted yourself, every process in Unix/Linux (except one, init ) is the child of another process, so using _exit in every child process would mean that exit is useless outside of init .

    Источник

    Читайте также:  Запуск графического интерфейса линукс
Оцените статью
Adblock
detector