I have a c++ app that has to create a gtk based popup on certain event.
Currently, I fork a thread on that event called _displaytask and that thread calls gtk_init().
The call to gtk_init hangs and never returns. Anyone knows here as to why the call hangs?
The gtk version is gtk+-2.0.
void* Gui::displayTask(void *data)
{
IDC_TRACE("Gui::display task tart");
Gui* obj=(Gui *)data;
if(obj!=NULL)
{
if( ! g_thread_supported() )
g_thread_init( NULL );
/* Secure gtk */
gdk_threads_init();
gdk_threads_enter();
IDC_TRACE("doing a gtk init");
gtk_init_check(0,0);
obj->initialise();
The control reaches gtk_init() but never gets past it to reach initialise.
http://www.bassi.io/articles/2014/08/27/gdk-and-threads/
Your order is wrong.
Should be:
enter
init
main
leave
Gui_display:04714807269964847148072699648
errno variable = 0
(process:26070): Gtk-WARNING **: This process is currently running setuid or setgid.
This is not a supported use of GTK+. You must create a helper
program instead. For further details, see:
http://www.gtk.org/setuid.html
Refusing to initialize GTK+.
I did not know this earlier.Got this error message.Now, the only way to do it would be in a different process
Related
Introduction
I am new to multithreading. I have an created a GUI application in c++ on windows 10 using wxWidgets. A worker thread communicates in the background via sockets and appends events to some event handlers from the main thread (GUI); I have two available protocols for the communication, and I allow the user to choose among those at the beginning (before instantiating the thread). To append events, I have a few shared pointers on the event handlers; a bit like in this tutorial, where it keeps a pointer of the m_parent. To communicate with the working thread, I created a queue using a mutex and semaphore, also like in the tutorial. For now, everything works.
Now, I want to let the user change the protocol while the application runs. I have thus a menu with a related button. This button calls the following function (create_app()) that deletes the top window and the communication thread and recreates everything. That is where I have problems.
bool cApp::create_app() {
wxWindow* main_window = GetTopWindow();
// If there is already a window, delete everything before creation
if(main_window) {
//thread_communication->Wait(); // Should I wait for the thread to finish? I shouldn't
if (thread_communication->Delete() != wxTHREAD_NO_ERROR) { // Should I delete it since it should be destroyed when Entry is finished
std::cerr << "DELETE IMPOSSIBLE!" << std::endl;
return false;
}
if (main_window->Destroy() != wxTHREAD_NO_ERROR) { // Here I can't delete the window
std::cerr << "DELETE WINDOW IMPOSSIBLE!" << std::endl; // prints
return false;
}
SetTopWindow(NULL);
}
// Create everything
m_frame1 = new MainFrame(*this);
SetTopWindow(m_frame1);
m_frame1->Show();
std::vector<std::shared_ptr<wxEvtHandler>> evt_handlers;
m_frame1->get_handlers(evt_handlers);
// Construct the working thread with the evt handlers and the queue from the main window
thread_communication = std::unique_ptr<ThreadCom>(new ThreadCom(evt_handlers, m_frame1->get_queue());
wxThreadError err = thread_communication->Create();
...
err = thread_communication->Run();
...
return true;
}
bool cApp::OnInit() {
return create_app();
}
When the user click the related button, it calls this create_app function but before sends a task via the queue to the working thread with the highest priority (meaning it will be the next task achieved by it); afterwards, in the working thread, it exits after poping the task the while loop in Entry. Thus, the working thread should terminate there.
Problem
I have problem when deleting the thread and the application. I have memory leaks since, I guess, they share common material (pointers).
When I try to use Wait, I have first a assert !IsDetached. That is because I cannot wait for a detached thread. If I continue, the programm crashes (Access violation reading location) during the thread->Delete() call.
If I don't use Wait, the thread->Delete() call works fine. Afterwards, the program crashes at main_window->Destroy(); the return code is not ok thus it prints "DELETE WINDOW IMPOSSIBLE" with an Unhandled exception thrown: read access violation message.
So, how should I proceed? Should I implement destructors in the classes? How can I delete the thread and the app safely?
Thanks in advance for your help.
I'm trying to execute a function on user logout, but the program close before function call, is there any way to wait function finish the function execution?
#include "stdafx.h"
#include <windows.h>
#include <fstream>
using namespace std;
bool done = false;
void createFile() {
ofstream outfile("test.txt");
outfile << "test" << std::endl;
outfile.close();
}
BOOL WINAPI consoleHandler(DWORD signal) {
switch (signal)
{
case CTRL_LOGOFF_EVENT:
printf("Logoff");
done = true;
Sleep(20000); // force exit after 20 seconds
return TRUE;
case CTRL_C_EVENT:
printf("Ctrl+c");
done = true;
Sleep(20000); // force exit after 20 seconds
return TRUE;
case CTRL_CLOSE_EVENT:
printf("close");
done = true;
Sleep(20000); // force exit after 20 seconds
return TRUE;
default:
// Pass signal on to the next handler
return FALSE;
}
}
int main()
{
if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
printf("\nERROR: Could not set control handler");
return 1;
}
printf("Runing");
while (!done) {
printf(".");
Sleep(1000);
}
createFile(); //Dont called on user logout but called on close and ctrl+c
printf("\nEnding\n");
Sleep(1000);
return 0;
}
On CTRL_C_EVENT and CTRL_CLOSE_EVENT
The file test.txt is created but on
CTRL_LOGOFF_EVENT
The program close instantly, without call the function.
First, let me apologise : I'll not answer the specific 'CTRL_LOGOFF_EVENT' you are referring, but the generic feature you're trying to accomplish : 'execute a function on user logout'.
A generic way to do:
As far as I know, there is no generic way to do.
You may try various solutions :
catching events as you did
using try catch / finally
spawn windows timers and react to it
spawn threads that will wait for the main thread to end
But (as far as I know) all of them have a weakness to a way to close or another.
For instance, I recently had to struggle with a poorly coded dll I had to use. This dll was calling "exit(0)". I found no elegant way to gracefully handle this behaviour.
I had to launch it in a separated process (not thread), that I was monitoring from my main process. It's a lot of work to implement and to maintain for a simple result.
Another approach:
Depending on what you are trying to do, it may be a good practice to make your "final" operation gradually, using a format that allows you to recover partially written files.
It's what I would generally do, but it always depends on what you are trying to achieve.
For instance, if you're trying to clean your workspace, you may want to:
do it at start in the case it was not done in the previous run
work in temporary folders
Another case, if you have a very long process and want to generate summary file, you may want to:
generate a partial summary file from time to time
as you generate a new file, you move the previous one
that way, you'll have a partial summary file at every step of your process.
Since my answer has been down voted, I guess I need to be more pedantic.
first of all, since you are not getting the CTRL_LOGOFF_EVENT you may want to consult the this doc (https://learn.microsoft.com/en-us/windows/console/setconsolectrlhandler). The critical section being:
If a console application loads the gdi32.dll or user32.dll library, the
HandlerRoutine function that you specify when you call SetConsoleCtrlHandler
does not get called for the CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT events. The
operating system recognizes processes that load gdi32.dll or user32.dll as Windows
applications rather than console applications. This behavior also occurs for
console applications that do not call functions in gdi32.dll or user32.dll
directly, but do call functions such as Shell functions that do in turn call
functions in gdi32.dll or user32.dll.
To receive events when a user signs out or the device shuts down in these
circumstances, create a hidden window in your console application, and then handle
the WM_QUERYENDSESSION and WM_ENDSESSION window messages that the hidden window
receives. You can create a hidden window by calling the CreateWindowEx method with
the dwExStyle parameter set to 0.
You might also want to read ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa376890(v=vs.85).aspx ).
Now, what I had previously suggested is to use the SetWindowsHookEx which should work as all windows messages pass through it (it is what Spy uses to view the message queues (https://blogs.msdn.microsoft.com/vcblog/2007/01/16/spy-internals/)). 20 years ago, you would have to do something like this for certain messages that were not passed through to your window - as in your case where the windows message is processed up stream of the current window. You may come across old code that does this, or there may be situations that you still need to do this.
We are building a content editor that brings up a "cocos Player" in an NSWindow for test purposes. The user can test some content and then close the window.
So I need to be able to shutdown cocos and re-start within the same app.
Everything is working if I use the CC_MAC_USE_DISPLAY_LINK_THREAD threading model. I had to make a fix in CCDirectorMac to get this working. In CCDirectorMac | stopAnimation I had to set the _runningThread to nil since it is not set to nil by the #if and #elif when using CC_MAC_USE_DISPLAY_LINK_THREAD.
Anyway so now I am able to "end" a director and then re-start it later with no issues.
My question though is this: If I am building an AppKit editor with occasional use of cocos2D whould my threading model really be CC_MAC_USE_MAIN_THREAD as is suggested in the documentation?
When I do use CC_MAC_USE_MAIN_THREAD I get a HANG in in stopAnimation on the line:
CVDisplayLinkStop(displayLink);
I think the main thread would be fine and would avoid threading issues for our tool. Performance is not a concern. I can't find any sample code that shuts down and restarts cocos2d in an NSWindow ... so my assumption here is that I am in untested waters (or little tested waters).
My steps to shutdown/restart are:
Call [[CCDirector sharedDirector] end]
This calls stopAnimation
Then re-initialize cocos2d the same way I did originally
Any advice on threading models for a Mac desktop app ... and why CVDisplayLinkStop hangs would be greatly appreciated.
Thanks in advance.
Ok, I figured it out after reading this post and its answers on the Apple mailing list: http://lists.apple.com/archives/quartz-dev/2006/Oct/msg00056.html
When using CC_MAC_USE_MAIN_THREAD, the display link thread uses performSelector:onThread:waitUntilDone: to run drawScene: on the main thread. It passes YES for the waitUntilDone: parameter, so the display link thread blocks until the main thread can process the drawScene: call.
Here's the relevant fragment of the cocos2d code. MyDisplayLinkCallback is called on the display link thread.
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
CVReturn result = [(CCDirectorDisplayLink*)displayLinkContext getFrameForTime:outputTime];
return result;
}
- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
{
#if (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_DISPLAY_LINK_THREAD)
...
#else
// Display link thread blocks here:
[self performSelector:#selector(drawScene) onThread:_runningThread withObject:nil waitUntilDone:YES];
#endif
return kCVReturnSuccess;
}
The problem appears when the main thread tries to run CVDisplayLinkStop() which blocks until the display link callback in the display link thread finishes. Since the callback is at the same time waiting for the main thread to process its drawScene: call, both threads become deadlocked.
- (void) stopAnimation
{
...
if( displayLink ) {
// Main thread blocks here:
CVDisplayLinkStop(displayLink);
...
}
So, now for my workaround. I added a line to run the main thread's runloop in order to force the drawScene: call to be executed, which unblocks the display link thread. That way, when you call CVDisplayLinkStop() you're safe. Here's my addition (CCDirectorMac.m line 473 in cocos2d 2.1 release):
- (void) stopAnimation
{
...
if( displayLink ) {
#if (CC_DIRECTOR_MAC_THREAD != CC_MAC_USE_DISPLAY_LINK_THREAD)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
#endif
CVDisplayLinkStop(displayLink);
...
}
I'm not sure this is the right thing to do, there's probably a better way to deal with this, but this workaround is good enough for me at the moment.
Thanks for this post, it helped me figure out how to solve the same deadlock, in a non-cocos2d app, by processing the display link callback on a separate thread, never on the main thread.
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void *userInfo)
{
static dispatch_queue_t sDisplayQueue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sDisplayQueue = dispatch_queue_create("com.company.app.displayLink", NULL);
});
dispatch_sync(sDisplayQueue, ^{
<stuff>
});
return kCVReturnSuccess;
}
If I know a pid of a certain process that doesn't run the code(say firefox)
how do I assign a signal handler(say SIGINT) to it?
I have now :
pid = fork();
printf("forked and my pid is %d\n",pid);
//check for errors
if (pid<0){
printf("Error: invoking fork to start ss has failed, Exiting\n ");
exit(1);
}
//the child process runs the gulp
if (pid==0){
printf("STARTING THE FIREFOX\n");
//calling signal(somehandler,SIGINT); here will bind the child, which is replaced by the firefox new process,hence won't invoke the "somehandler"
if (execv(args[0],args)<0){
perror("Error: running s with execvp has failed, Exiting\n");
}
//invoking signal(somehandler,SIGINT); will obviously not do anything
printf("IVE BEEN KILLED\n");
}
//dad is here
printf("DAD IS GOING TO KILL\n");
if (pid>0){
sleep(6);
//how do I bind a handler to that signal????
kill(get_pidof(string("firefox")),SIGINT);
}
You can only establish a signal handler from within the process. Put another way, you can't make firefox call your signal handler when it gets a SIGINT.
EDIT
As you noticed, indeed signal handlers are not kept after an exec - the image of the process is replaced so it wouldn't make sense. So, like I said before: you can't make firefox call your handler even if you control its parent.
I need my program to run another program(say firefox), and to know
when the firefox died or crashed
In that case you want to establish a signal handler for SIGCHLD: your process will jump to it when the child dies.
As Cnucitar answered here, you can only change signal handler from inside the process.
If you wanted to make a signal handler inside firefox, you could patch it, perhaps thru a plugin. But I am sure that would be a bad idea.
My application (the bootstrap application for an installer that I'm working on needs to launch some other applications (my installer and third party installers for my installer's prerequisites) and wait for them to complete. In order to allow the GUI to do screen updates while waiting for an app to complete, I put a message pump in the wait loop using the 'MFC-compatible' example in the Visual Studio documentation on idle loop processing as a guideline. My code (which is in a member function of a CWinApp-derived class) is as follows:
if (::CreateProcess(lpAppName, szCmdLineBuffer, NULL, NULL, TRUE, 0, NULL, NULL,
&StartupInfo, &ProcessInfo))
{
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
if (bWait)
while (dwExitCode == STILL_ACTIVE)
{
// In order to allow updates of the GUI to happen while we're waiting for
// the application to finish, we must run a mini message pump here to
// allow messages to go through and get processed. This message pump
// performs much like MFC's main message pump found in CWinThread::Run().
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!PumpMessage())
{
// a termination message (e.g. WM_DESTROY)
// was processed, so we need to stop waiting
dwExitCode = ERROR_CANT_WAIT;
::PostQuitMessage(0);
break;
}
}
// let MFC do its idle processing
LONG nIdle = 0;
while (OnIdle(nIdle++))
;
if (dwExitCode == STILL_ACTIVE) // was a termination message processed?
{
// no; wait for .1 second to see if the application is finished
::WaitForSingleObject(ProcessInfo.hProcess, 100);
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
}
}
::CloseHandle(ProcessInfo.hProcess);
::CloseHandle(ProcessInfo.hThread);
}
else
dwExitCode = ::GetLastError();
The problem that I'm having is that, at some point, this message pump seems to free up window and menu handles on the window that I have open at the time this code is run. I did a walk through in the debugger, and at no time did it ever get into the body of the if (!PumpMessage()) statement, so I don't know what's going on here to cause the window and menu handles to go south. If I don't have the message pump, everything works fine, except that the GUI can't update itself while the wait loop is running.
Does anyone have any ideas as to how to make this work? Alternatively, I'd like to launch a worker thread to launch the second app if bWait is TRUE, but I've never done anything with threads before, so I'll need some advice on how to do it without introducing synchronization issues, etc. (Code examples would be greatly appreciated in either case.)
I've also posted this question on the Microsoft forums, and thanks to the help of one Doug Harris at Microsoft, I found out my problem with my HWND and HMENU values was, indeed due to stale CWwnd* and CMenu* pointers (obtained using GetMenu() and GetDialogItem() calls. Getting the pointers again after launching the second app solved that problem. Also, he pointed me to a web site* that showed a better way of doing my loop using MsgWaitForMultipleObjects() to control it that doesn't involve the busy work of waiting a set amount of time and polling the process for an exit code.
My loop now looks like this:
if (bWait)
{
// In order to allow updates of the GUI to happen while we're
// waiting for the application to finish, we must run a message
// pump here to allow messages to go through and get processed.
LONG nIdleCount = 0;
for (;;)
{
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
PumpMessage();
else //if (!OnIdle(nIdleCount++))
{
nIdleCount = 0;
if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
DWORD nRes = ::MsgWaitForMultipleObjects(1, &ProcessInfo.hProcess,
FALSE, INFINITE, QS_ALLEVENTS);
if (nRes == WAIT_OBJECT_0)
break;
}
}
}
}
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
*That Web site, if you're curious, is: http://members.cox.net/doug_web/threads.htm
I think your problem is in WaitForSingleObject
Looking in MSDN you see this
Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.
In my code in the message pump use use MsgWaitForMultipleObjects (doc).
With a call this call.
MsgWaitForMultipleObjects(1, &ProcessInfo.hProcess, FALSE, 100, QS_ALLEVENTS);
This should stop your problem with the resources dissapearing.
When you say that window and menu handles seem to be being freed, do you mean that you've got actual HWND and HMENU values that no longer seem to work, or have you got MFC CWnd* and CMenu* variables that fail?
If the latter, the problem is most likely that you're getting the CWnd* pointers by calling CWnd::FromHandle() (or CMenu::FromHandle()) somewhere (or calling something that calls them), and OnIdle() is discarding them.
The underlying reason is that MFC maintains a map from window (or menu, etc.) handles to CWnd* objects in the system. When CWnd::FromHandle() is called, it looks for a match in the map: if one is found, it's returned. If not, a new, temporary CWnd is created, added to the map, and returned. The idea behind OnIdle() is that when it's called all message processing is done, so OnIdle() discards any of these temporary CWnd objects that still exist. That's why the CWnd::FromHandle() documentation warns that the returned pointer may be temporary.
The "correct" solution to this is to not hang onto the CWnd* pointers returned from CWnd::FromHandle(). Given the simplicity of your application, it might be easier to just remove the call OnIdle(): this shouldn't have any negative effects on an installer.
Of course, this is all something of a guess, but it sounds plausible...
There is a Windows function called DisableProcessWindowsGhosting (see http://msdn.microsoft.com/en-us/library/ms648415(v=vs.85).aspx) that prevents Windows from 'ghosting' your window, and continue updating the window (your animation).