Author Topic: How does Run abort work  (Read 8852 times)

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
How does Run abort work
« on: March 31, 2016, 01:18:17 am »
In the CodeBlocks compiler toolbar is a red button with a white cross. If one starts the current project with the green Run button, is stopped when that red button is pressed.

Does anyone know what actually happens when I press that button?



using CB16.1/Win7
« Last Edit: March 31, 2016, 03:51:45 pm by tigerbeard »

Offline BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 3353
Re: How does Run abort work
« Reply #1 on: April 02, 2016, 03:25:55 pm »
C::b is open source so: look into the code ;)

Code
int CompilerGCC::KillProcess()
{
    ResetBuildState();
    m_RunAfterCompile = false;
    if (!IsProcessRunning())
        return 0;
    if (!m_CommandQueue.LastCommandWasRun())
        LogMessage(_("Aborting build..."), cltInfo, ltMessages);
    wxKillError ret = wxKILL_OK;

    m_CommandQueue.Clear();

    for (size_t i = 0; i < m_CompilerProcessList.size(); ++i)
    {
        if (!m_CompilerProcessList.at(i).pProcess)
            continue;

        #if defined(WIN32) && defined(ENABLE_SIGTERM)
            ::GenerateConsoleCtrlEvent(0, m_CompilerProcessList.at(i).PID);
        #endif

        // Close input pipe
        m_CompilerProcessList.at(i).pProcess->CloseOutput();
        ((PipedProcess*) m_CompilerProcessList.at(i).pProcess)->ForfeitStreams();

        ret = wxProcess::Kill(m_CompilerProcessList.at(i).PID, wxSIGTERM);

        if (!platform::windows)
        {
            if (ret != wxKILL_OK)
            {
                // No need to tell the user about the errors - just keep him waiting.
                Manager::Get()->GetLogManager()->Log(F(_("Aborting process %d ..."), i), m_PageIndex);
            }
            else switch (ret)
            {
                case wxKILL_OK:
                    Manager::Get()->GetLogManager()->Log(_("Process aborted (killed)."), m_PageIndex);
//                case wxKILL_ACCESS_DENIED: cbMessageBox(_("Access denied"));     break;
//                case wxKILL_NO_PROCESS:    cbMessageBox(_("No process"));        break;
//                case wxKILL_BAD_SIGNAL:    cbMessageBox(_("Bad signal"));        break;
//                case wxKILL_ERROR:         cbMessageBox(_("Unspecified error")); break;
                case wxKILL_ACCESS_DENIED: // fall-through
                case wxKILL_NO_PROCESS:    // fall-through
                case wxKILL_BAD_SIGNAL:    // fall-through
                case wxKILL_ERROR:         // fall-through
                default:                   break;
            }
        }
    }

    ProjectManager *projectManager = Manager::Get()->GetProjectManager();
    if (projectManager->GetIsRunning() == this)
        projectManager->SetIsRunning(NULL);
    return ret;
}

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #2 on: April 02, 2016, 05:35:58 pm »
I don't think this is the correct function:)
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 3353
Re: How does Run abort work
« Reply #3 on: April 02, 2016, 05:45:07 pm »
Does anyone know what actually happens when I press that button?

well i didn't read the title...

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #4 on: April 02, 2016, 06:13:07 pm »
Code
ret = wxProcess::Kill(m_CompilerProcessList.at(i).PID, wxSIGTERM);
Wouldn't that be the same than using taskkill PID on the console? This produces a different result that that button, so the button must do sth else.

C::b is open source so: look into the code ;)

Forgot to say that I tried that. Unfortunately CB does not compile so I can't use a breakpoint to find out where I need to look or what I need to search for. Unfortunatley I did not yet understand the structure of the source, though. Maybe a hint about which class handles that button would help.


Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #5 on: April 02, 2016, 07:47:59 pm »
I don't think this is the correct function:)
I was wrong. This is the correct function/method.

@tigerbeard: Usually you don't need a debugger to find what something does.
I've done it like this:
1. started from Build -> Abort.
2. search for Abort in the src folder.
3. you'll find that it is a menu item.
4. then you'll find the menu item's id - idCompilerMenuKillProcess
5. search for idCompilerMenuKillProcess in src
6. you find which function is called when this menu is selected
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #6 on: April 03, 2016, 12:53:51 am »
Very helpful answer, thanks.
After the initial surprise about the huge number of Abort hits I managed to find the location. Great. The killing is just a few lines, just as posted. However its helpful to see the bits around as well.

I am not sure what the purpose of that event is, does that influence the Kill below?
Code
        #if defined(WIN32) && defined(ENABLE_SIGTERM)
            ::GenerateConsoleCtrlEvent(0, m_CompilerProcessList.at(i).PID);
        #endif

Basically that kill command in here
Code
        // Close input pipe
        m_CompilerProcessList.at(i).pProcess->CloseOutput();
        ((PipedProcess*) m_CompilerProcessList.at(i).pProcess)->ForfeitStreams();
        ret = wxProcess::Kill(m_CompilerProcessList.at(i).PID, wxSIGTERM);

should be doing the same as
Code
 taskkill /F /IM MyApp.exe

shouldn't it? But it does not and I can not see why.  The code kill takes the app to hang for 1-2 secs before the Program stopped error is displayed. The console kill closes it instantly.

After the crash I get this output of Dr. MinGw. The only codeline from my app is IMPLEMENT_APP().
Code
Test.exe caused an Access Violation at location 6fe718d0 in module libstdc++-6.dll Reading from location 000000c8.

Registers:
eax=000000c4 ebx=00000000 ecx=000000c4 edx=00000000 esi=00000000 edi=0000003c
eip=6fe718d0 esp=0028fa9c ebp=0028fab8 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206

Call stack:
6FE718D0  libstdc++-6.dll:6FE718D0  _ZNKSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE5emptyEv
61D829F7  wxmsw293ud_gcc_custom.dll:61D829F7  _ZNK16wxAppConsoleBase17GetAppDisplayNameEv
61FD5F27  wxmsw293ud_gcc_custom.dll:61FD5F27  _ZNK8wxLogGui8GetTitleEv
61FD61DB  wxmsw293ud_gcc_custom.dll:61FD61DB  _ZN8wxLogGui5FlushEv
61DD6339  wxmsw293ud_gcc_custom.dll:61DD6339  _ZN5wxLog15SetActiveTargetEPS_
61DCBADD  wxmsw293ud_gcc_custom.dll:61DCBADD  _Z12wxEntryStartRiPPc
61DCBB48  wxmsw293ud_gcc_custom.dll:61DCBB48  _Z14wxEntryCleanupv
61DCBDE0  wxmsw293ud_gcc_custom.dll:61DCBDE0  _Z14wxUninitializev
623B5BE4  wxmsw293ud_gcc_custom.dll:623B5BE4  _ZN13wxInitializerD1Ev
61DCBC0D  wxmsw293ud_gcc_custom.dll:61DCBC0D  _Z11wxEntryRealRiPPw
61E49D74  wxmsw293ud_gcc_custom.dll:61E49D74  _Z7wxEntryRiPPw
61E4A062  wxmsw293ud_gcc_custom.dll:61E4A062  _Z7wxEntryP11HINSTANCE__S0_Pci
00443FB7  Test.exe:00443FB7  WinMain@16  Test.cpp:30
int32 WinMain@16(
HINSTANCE hInstance = &{
int32 unused = 9460301
},
HINSTANCE hPrevInstance = &{
int32 unused =
},
int32 nCmdShow = 10
)
...
//////////////////////////////////////////////////////////////////////
// 2010-03-08
> IMPLEMENT_APP(CTestApp)


...

005026CD  Test.exe:005026CD  operator+  gdicmn.h:560
struct wxPoint operator+(
struct wxPoint * p1 = &{
int32 x = 12529593,
int32 y = 0
},
struct wxPoint * p2 = &{
int32 x = ,
int32 y =
}
)
...
{
    return wxPoint(p1.x + p2.x, p1.y + p2.y);
> }

inline wxPoint operator-(const wxPoint& p1, const wxPoint& p2)
...

004013E2  Test.exe:004013E2
768F33CA  kernel32.dll:768F33CA  BaseThreadInitThunk
76F49ED2  ntdll.dll:76F49ED2  RtlInitializeExceptionChain
76F49EA5  ntdll.dll:76F49EA5  RtlInitializeExceptionChain


Tiger

PS interesting side detail in the code, why are you collecing all plugin events in a dispatcher. I can not really see the advantage not to list the functions in the event table?

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #7 on: April 03, 2016, 01:06:55 am »
Finally I found a way to get the debugger working with that scenario.
I just run two instances of CodeBlocks with the same project. The one starts the application.
The other attaches the debugger to the running process.

Works really nice.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #8 on: April 03, 2016, 06:45:13 am »
wxProcess::Kill(..., wxSIGTERM) is not the same as taskkill /F ..., probably it is the same as calling taskkill without /F.

See here: http://docs.wxwidgets.org/trunk/group__group__funcmacro__procctrl.html#gae3a7de5a29e70c77463dd1bc38fb98cf

GenerateConsoleCtrlEvent might help for console applications. But I doubt it is ever executed.

I'm a little confused by your last post. Can you explain in details what are you trying to do?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #9 on: April 03, 2016, 01:42:10 pm »
wxProcess::Kill(..., wxSIGTERM) is not the same as taskkill /F ..., probably it is the same as calling taskkill without /F.
See here: http://docs.wxwidgets.org/trunk/group__group__funcmacro__procctrl.html#gae3a7de5a29e70c77463dd1bc38fb98cf
Unfortunately the docu just talks about Kill, not taskkill. Can only say from what I obverved from the behaviour that both taskkill and taskkill /F closed the application ok, the CB Abort button, aka the wxProcess::Kill did not. And from you feedback I take it that you would be surprised by different behaviour as well.

I'm a little confused by your last post. Can you explain in details what are you trying to do?
I agree it can be a bit confusing by description in pieces only. Maybe that helps
I have this crash effect on application exit and have no idea what happens. I was just trying to find a way to reproduce it in the debugger. But since only the run abort from CB caused that crash, first I was looking for another way to cause that crash. My first idea was to find out what the abort button does and just do the same from the console.
With your help I can see now that CB does what you would expect, send a sigterm to the window. But that is exactly what I think the task manager kill and taskkill also do. But I still get that crash only with the Abort button version, not when stopping the App any other way.

The last post was about an alternative approach I did not see before. Its basically the way I can debug what the Build/Abort button does live. If you want I run the C:B debugging in parallel to CB running the application via the Build/Run command.

So now I can debug the problem. I did not find the bug yet, but I can see that I did not anticipate the way an application is closed by calling wxApp:OnExit() directly, i.e. before any windows know about the app being closed. But thats a pure wxWidgets programming issue and not C:B related.

To make a long story short. We can close that thread, because the issue itself is answered. I know what C::B does.
I still do not know why my App behaves differently between C::B Abort and taskkill but thats out of scope with this thread.
Should I find out sth which relates to C:B I shall add a short Info to this post.

Thanks for your help.




Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #10 on: April 03, 2016, 02:21:04 pm »
The next step is to inspect what wxKill does on windows:)
So look at the code of wxwidgets.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #11 on: April 05, 2016, 03:38:51 am »
I did not find out the difference, as I have no info about what taskmanager and taskkill are doing. But I found the cause of the problem. Its the line wxLogMessage("hello"); somewhere where it is called from MainFrames dtor.

I think its quite interesting. It can be reproduced in the minimal sample by just adding a destructor to MyFrame() with that line.
The program works fine and can be killed by task manager. But it stops when aborted by C::B.  (Win7, WX V2.9.3, GCC)

The interesting question for me would be how to debug that behaviour using the standard C::B toolset. I could not step into the problem as it triggers after wxApp is destructed, Dr.MinGW shows garbage. I am looking for a better method tracking stuff like that than taking apart the whole project bit by bit until almost nothing is left. Hopefully C::B and gcc can do more that I am aware off?

Tiger


Cheers
Hans

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #12 on: April 05, 2016, 10:02:06 am »
You can probably use a second instance of codeblocks and do debug -> attach from it.
Then hit the abort button in the first instance.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #13 on: April 05, 2016, 03:11:50 pm »
You can probably use a second instance of codeblocks and do debug -> attach from it.
Then hit the abort button in the first instance.

That was what I did. I had tried to describe it in that post. Sorry that it was not clear.

Finally I found a way to get the debugger working with that scenario.
I just run two instances of CodeBlocks with the same project. The one starts the application.
The other attaches the debugger to the running process.

Works really nice.

The problem ist that while debugging is possible, I found no way with the debugger (probably
better: its integration in C::B) to get to that point where it crashes. I believe there is a very
high chance that this is due to my inability to effectively work with C::B's debugger integration.

I gave that short example to reproduce the crash hoping I could learn from more experienced
codeblocks users how to the the debugging tools in Codeblocks better than I do today. I would
be relieved to lean that this kind of crash only is debuggable with GDB by working manually with
its command line. That would be well out of scope for me, then.

So this is not meant to be a post about how I lean GDB, but rather what can I do with the integrated
gdb in code blocks. I think its very rare that a crash is reproducable by just a single line added in a wxMinmal
sample, so I though I'd use that opportunity to lean something.

Cheers
Tiger

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #14 on: April 05, 2016, 07:58:07 pm »
Do you have catching of exception enabled in the debugger settings.
If it crashes because of the way cb is killing the app then the debugger should catch it.

If the bug disappears when the debugger is attached to the app then you have either a timing/threading related bug or uninitialized memory/use-after-free bug.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #15 on: April 05, 2016, 11:49:01 pm »
Do you have catching of exception enabled in the debugger settings.
If it crashes because of the way cb is killing the app then the debugger should catch it.

If the bug disappears when the debugger is attached to the app then you have either a timing/threading related bug or uninitialized memory/use-after-free bug.

Cool. Thats the kind of thing I was looking for. I did not have exceptions enabled.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: How does Run abort work
« Reply #16 on: April 06, 2016, 12:05:12 am »
Have you found your problem with the exceptions switch enabled?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline tigerbeard

  • Almost regular
  • **
  • Posts: 190
Re: How does Run abort work
« Reply #17 on: April 06, 2016, 12:30:36 am »
With the exceptions enabled the debugger triggers on the crash. And that even in the double C::B setup with attached dbg. Quite cool  8)

It took me into very final wxLog shutdown. That is matching the cause I had found before (see previous post)
So indeed, with that enabled before I would have saved me a couple of hrs searching!