When wxProcess::Kill() launches wxProcess::OnTerminate() ?

124 views
Skip to first unread message

na...@centrum.cz

unread,
Oct 27, 2021, 5:12:27 AM10/27/21
to wx-u...@googlegroups.com

Hello,
I have ubuntu 20.04 OS with wxWidgets 3.0.5. I have a custom Process class (inherits from wxProcess) with OnTerminate() function overridden. When I kill a process associated with an instant of MyProcess class with MyProcess::Kill(), according to the documentation of the wxProcess::OnTerminate():

https://docs.wxwidgets.org/3.0/classwx_ ... 4cbb72a172

the OnTerminate() function should not be called. But in my case it is. Regradless of the used terminate flag.

I want to know, if this should not happen at all - mistake is in my code, or if this is an expected behavior. If it is, then under which circumstances is the OnTerminate() launched, when the process is "killed" with MyProcess::Kill().

Additinal info:

I launch the command asynchronously with wxExecute("a.out", wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, myProcess);

The program a.out has this implementation

------------------------------------------------------------

#include <iostream>

int main(int argc, char *argv[]){
    int k;
    
    std::cout << "Narg = " << argc - 1 << std::endl;
    for(k = 1; k < argc; ++k){
        std::cout << argv[k] << std::endl;
    }
    
    std::cerr << "Fail";
    
    while(true){

    }
    
    return 127;
}
------------------------------------------------

The flag returned from MyProcess::Kill() function is always wxKILL_OK.

Thanks,

Dalibor


PB

unread,
Oct 27, 2021, 6:55:14 AM10/27/21
to wx-users
Hi,

I do not use Linux but FWIW, I cannot reproduce this on Windows 10 (with the GIT master) using cmd.exe as the child process with this code:
https://gist.github.com/PBfordev/69d0b40e51b20f88e9b71846087cd3dd

Dalibor, I assume if you run the linked code verbatim except replacing "cmd" with "a.out", MyProcess::OnKill() is still called there? Since you posted the code of the child process instead of the one calling it: Does the child process actually matter or does the issue manifest with any process?

Regards,
PB

PB

unread,
Oct 27, 2021, 1:48:32 PM10/27/21
to wx-users
Dalibor somehow replied to my personal e-mail instead to the group (please do not do that), I am pasting that at the end of the email.

Firstly, I used wxLogMessage() because GUI programs on Windows do not show console. "cmd" is a console command processor built into Windows. The assert was probably because I used %d printf formatter for wxProcess::GetPid() but it returns long and not int and unlike on Windows, these two are different in 64-bit on Linux.

Now the important stuff: I have noticed that when calling wxProcess::Kill(m_process.GetPid()), its window disappeared but wxKill() returned wxKILL_ERROR. MyProcess::OnTerminate() was not called. However, when I tried the same with other applications (Explorer, msys64.exe) their window stayed open after attempting to kill them.

Seeing that, I changed the kill call to  wxProcess::Kill(m_process.GetPid(), wxSIGKILL). When killing "cmd", this change resulted in
1. wxKill() still returned the error but now an additional error message was displayed: " Error: Failed to kill process 20412 (error 5: Access is denied.)". I tried running the app as an Administrator with the same result.
2. cmd's window still disappeared.
3.  MyProcess::OnTerminate() was called.

I tried the same with Explorer and msys64 but nothing changed there, i.e., the processes' windows did not disappear and MyProcess::OnTerminate() was not called.

So it seems that this may be tricky and does not depend only on a platform but also on a signal used to kill as well as the child application itself. Nevertheless, it seems that saying that wxProcess::OnTerminate() is not called when the process is killed is probably incorrect.

Sorry, I do not think I can help any more with this, hopefully someone else will.

Regards,
PB
============== reply from Dalibor to my first post in this thread =============
On Wed, Oct 27, 2021 at 6:49 PM Dalibor wrote:

Hi PB,

thank you for your prompt reply a for writing a minimal example. I do not have cmd.exe at hand, nor its code to compile and use it. If you send it to me, I can try it out in my code.

1. I could compile your code with no problems, but when launched I received this error:

An assertion failed: /usr/include/wx-3.0-unofficial/wx/strvararg.h(462): assert "(argtype & (wxFormatStringSpecifier<T>::value)) == argtype" failed in wxArgNormalizer(): format specifier doesn't match argument type

I am familiared with all the commands in the example except Log messages. Therefore, I commented out all code with them a redirected the output to stdout and stderr with std::cout and std::cerr. The code worked then. See the changed code at the end of my message.

--------------------

QUOTATION: " Dalibor, I assume if you run the linked code verbatim except replacing "cmd" with "a.out", MyProcess::OnKill() is still called there? "

-------------------

Yes, wxKill() is still called. See the terminal output below.

------------

QUOTATION: "Since you posted the code of the child process instead of the one calling it: Does the child process actually matter or does the issue manifest with any process?"

------------

I apologize for not sending the code invoking the wxExecute (and my laziness). I will do my best next time. I admire, and thanks again, that you did this instead of me.

I have tried to launch inkscape with the same result: wxExecute("inkscape", wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, &m_process). Here is the terminal output, which is the same for both a.out and inkscape, except pid and inkscape warning:

------------

TERMINAL OUTPUT FOR INKSCAPE:

Process started, pid = 4751
Going to kill the process in 3 seconds.

** (org.inkscape.Inkscape:4751): WARNING **: 18:42:52.002: Fonts dir '/home/dalibor/.config/inkscape/fonts' does not exist and will be ignored.
Attempting to kill the process...
Process killed.
OnTerminate(): pid = 4751, status = -15
inkscape

TERMINAL OUTPUT FOR A.OUT:

Process started, pid = 4838
Going to kill the process in 3 seconds.
Numer = 0
FailAttempting to kill the process...
Process killed.
OnTerminate(): pid = 4838, status = -15
a.out


------------

 

-------------------------------------

CODE:

#include <wx/wx.h>
#include <wx/process.h>

class MyProcess : public wxProcess
{
public:
    wxString cmd;
    void OnTerminate(int pid, int status) override
    {
        //wxLogMessage("OnTerminate(): pid = %d, status = %d", pid, status);
        std::cout << "OnTerminate(): pid = "<< pid << ", status = " << status << std::endl;
        std::cout << cmd <<std::endl;
    }
};

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, "Test")
    { 
        /*wxLog::SetActiveTarget(new wxLogTextCtrl(new wxTextCtrl(this, wxID_ANY, wxEmptyString,
            wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2)));*/                                        
        m_process.cmd = wxString::FromUTF8("a.out");
        if ( wxExecute(m_process.cmd, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, &m_process) )
        {
            //wxLogMessage("Process started, pid = %d.", m_process.GetPid());
            std::cout << "Process started, pid = " << m_process.GetPid() << std::endl;
            m_timer.SetOwner(this);
            m_timer.StartOnce(3000);
            //wxLogMessage("Going to kill the process in 3 seconds.");
            std::cout << "Going to kill the process in 3 seconds." << std::endl;
        }

        Bind(wxEVT_TIMER, [this](wxTimerEvent&)
            {
              //wxLogMessage("Attempting to kill the process...");
              std::cout << "Attempting to kill the process..." << std::endl;
                if ( wxProcess::Kill(m_process.GetPid()) == wxKILL_OK )
                  //wxLogMessage("Process killed.");
                std::cout << "Process killed." << std::endl;
              else
                  //wxLogError("Could not kill the process.");
                  std::cerr << "Could not kill the process." << std::endl;
            } );
    }  
private:
    MyProcess m_process;
    wxTimer   m_timer;
};

class MyApp : public wxApp
{
    bool OnInit() override
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);

--------------------------------------------------------------


Thanks,

Dalibor

na...@centrum.cz

unread,
Oct 27, 2021, 2:11:41 PM10/27/21
to wx-u...@googlegroups.com

Hi PB,

I appologize for the private reply.


Thanks for your effort. You approved my doublts about the wxProcess::Kill() function. I will wait if anyone else contrubutes to elucidation of the problem.


Thanks,

Dalibor

--
Please read https://www.wxwidgets.org/support/mlhowto.htm before posting.
---
You received this message because you are subscribed to the Google Groups "wx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wx-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wx-users/f358b0d4-72f1-4d16-b9e6-7f832a08a5f5n%40googlegroups.com.

Carsten Arnholm

unread,
Oct 27, 2021, 2:28:15 PM10/27/21
to wx-u...@googlegroups.com
On 27.10.2021 20:11, na...@centrum.cz wrote:
> Thanks for your effort. You approved my doublts about the
> wxProcess::Kill() function. I will wait if anyone else contrubutes to
> elucidation of the problem.

Have you tried

wxProcess::Kill(m_process.GetPid(), SIGNAL_TERMINATE).

I have some working code that does that,but I can't remember why
SIGNAL_TERMINATE is used.

Carsten Arnholm

jon bird

unread,
Oct 27, 2021, 2:49:15 PM10/27/21
to wx-u...@googlegroups.com
There is definitely some odd behaviour around wxProcess, at least on
Windows anyway. I ended up stepping through the code for Kill and a key
thing to note is that the the default behaviour (ie. without specifying
the signal) differs between GUI applications and console apps. In the
former, it attempts to close the app by sending a (I think) WM_QUIT
message, in the latter it does nothing. You have to pass in wxSIGKILL
in order to terminate a console process, which ultimately results in a
call to TerminateProcess (and in my case, a subsequent call to
OnTerminate). That sort of makes sense because in my experience, there
is no other way to kill a console process.

I would hope you'd get the same thing with a GUI app but maybe if it
thinks the WM_QUIT succeeded, it assumes the window has closed. Given
Explorer (not sure what msys64 is but sounds "system" related) is going
to be a fairly unique case, it may be worth checking the behaviour with
a more normal app - Notepad for example.

Other point I observed - which I included as a big comment in my code...

void OnTerminate(int pid, int status) override
{
ProcessActive = false;

/* This statement in the wiki:

If the wxEVT_END_PROCESS event sent after termination is processed
by the parent, then it is responsible for deleting the wxProcess
object which sent it. However, if it is not processed, the object
will delete itself and so the library users should only delete
those objects whose notifications have been processed (and call
wxProcess::Detach for others). This also means that unless you're
going to process the wxEVT_END_PROCESS event, you must allocate the
wxProcess class on the heap.

We aren't attaching an event handler here so the implication here
is that we need to create this class on the heap. Indeed, when it
was on the stack, the process crashes shortly after the dialog gets
closed. However what *doesn't* appear to happen is the object
deleting itself automatically ie. our destructor never gets called
UNLESS we call the OnTerminate method in the base class - below. */

wxProcess::OnTerminate(pid, status);
}

Hope this helps.

Rgs,


Jon.


On Wed, 27 Oct 2021 20:11:36 +0200
"na...@centrum.cz" <na...@centrum.cz> wrote:

> Hi PB,
>
> I appologize for the private reply.
>
>
> Thanks for your effort. You approved my doublts about the
> wxProcess::Kill() function. I will wait if anyone else contrubutes to
> elucidation of the problem.
>
>
> Thanks,
>
> Dalibor
>
>
> On 27. 10. 21 19:48, PB wrote:
> > Dalibor somehow replied to my personal e-mail instead to the group
> > (please do not do that), I am pasting that at the end of the email.
> >
> > Firstly, I used wxLogMessage() because GUI programs on Windows do
> > not show console. "cmd" is a console command processor built into
> > Windows. The assert was probably because I used %d printf formatter
> > for wxProcess::GetPid() but it returns long and not int and unlike
> > on Windows, these two are different in 64-bit on Linux.
> >
> > Now the important stuff: I have noticed that when calling
> > wxProcess::Kill(m_process.GetPid()), its window disappeared but
> > wxKill() returnedwxKILL_ERROR. MyProcess::OnTerminate() was not
> > <mailto:wx-users+u...@googlegroups.com>.
> > <https://groups.google.com/d/msgid/wx-users/f358b0d4-72f1-4d16-b9e6-7f832a08a5f5n%40googlegroups.com?utm_medium=email&utm_source=footer>.
>



--
--
== jon bird - software engineer
== <reply to address _may_ be invalid, real mail below>
== <reduce rsi, stop using the shift key>
== posted as: news 'at' onasticksoftware 'dot' co 'dot' uk

Gunter Königsmann

unread,
Oct 27, 2021, 3:42:31 PM10/27/21
to wx-u...@googlegroups.com, jon bird
If I remember things right on windows the behavior depends on the questions if both processes share a console or something like that. Perhaps that is a security feature: you cannot wildly send signals to processes you have no relation to.

PB

unread,
Oct 27, 2021, 4:15:29 PM10/27/21
to wx-users
Hi again,

FWIW, after reading Jon's information (and yes, explorer was poorly chosen as a test app), I have done some more testing on Windows 10 with wxWidgets GIT master, using this test application and two child processes: cmd as a console application and notepad as a GUI application. Here are the results
Process 'cmd' with pid = 9804 will be killed in 3 sec.
Attempting to kill 'cmd' with wxSIGTERM.
Error: Could not kill the process, wxKill() returned wxKILL_ERROR.

Process 'cmd' with pid = 15448 will be killed in 3 sec.
Attempting to kill 'cmd' with wxSIGKILL.
Process killed successfully.
MyProcess::OnTerminate(): pid = 15448, status = -1

Process 'notepad' with pid = 2984 will be killed in 3 sec.
Attempting to kill 'notepad' with wxSIGTERM.
Process killed successfully.
MyProcess::OnTerminate(): pid = 2984, status = 0

Process 'notepad' with pid = 9200 will be killed in 3 sec.
Attempting to kill 'notepad' with wxSIGKILL.
Process killed successfully.
MyProcess::OnTerminate(): pid = 9200, status = -1

In conclusion, when the process is wxKill()ed successfully, its wxProcess::OnTerminate() appears to be called, for the GUI application with different statuses based on the kill signal used.

Regards,
PB

na...@centrum.cz

unread,
Oct 28, 2021, 5:10:38 AM10/28/21
to wx-u...@googlegroups.com

Hello PB,

Thank you for testing this out. I agree with the conclusion: When the process is killed successfully (return value of wxProcess::Kill() is wxKILL_OK), the OnTerminate() function is launched. Due to my experience, the conclusion can be generalized to include cmd apps as well. At least on Ubuntu.



Regards,
PB
--
Please read https://www.wxwidgets.org/support/mlhowto.htm before posting.

---
You received this message because you are subscribed to the Google Groups "wx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wx-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wx-users/2ff76545-71fd-40b0-bdf2-0b8be772d8c4n%40googlegroups.com.


Thanks,

Dalibor

PB

unread,
Oct 29, 2021, 4:28:22 AM10/29/21
to wx-users
Hi,

I have just created a ticket for this, let's see what the devs are going to say: https://trac.wxwidgets.org/ticket/19309

Regards,
PB

Vadim Zeitlin

unread,
Oct 29, 2021, 10:50:33 AM10/29/21
to wx-u...@googlegroups.com
On Fri, 29 Oct 2021 01:28:21 -0700 (PDT) PB wrote:

P> I have just created a ticket for this, let's see what the devs are going to
P> say: https://trac.wxwidgets.org/ticket/19309

Thanks, I didn't have time to read through the entire thread here,
unfortunately, but I'll try to at least look a this ticket, although even
this might not happen immediately -- but I'll get to it, sooner or later.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Reply all
Reply to author
Forward
0 new messages