See important edit below!
Hi all I'm having trouble figuring out why this segfault is happening. I'm using the Ogre and OIS library. Here is the code that causes it:
bool Troll::Application::keyPressed(const OIS::KeyEvent& event) {
//TODO: Segfault here!
Troll::State* state = mStateManager->peek();
state->key_pressed(event); //This causes the SEGFAULT!!!
return true;
};
And the key_pressed function:
void Troll::RootState::key_pressed(const OIS::KeyEvent& event) {
std::cout << "You got here" << std::endl; //this isnt printed!
std::cout << "Key Pressed: " << event.key << std::endl;
};
Because the segfault is happening on key_pressed but the first line of key_pressed isn't being executed, I can only guess that it is passing the const OIS::KeyEvent& that is causing it.
And the weird thing about this is I have three other functions that are almost identical (but for the mouse) which work perfectly.
bool Troll::Application::mouseMoved(const OIS::MouseEvent& event) {
mStateManager->peek()->mouse_moved(event);
return true;
};
void Troll::RootState::mouse_moved(const OIS::MouseEvent& event) {
std::cout << "Mouse Moved: rel x = " << event.state.X.rel << std::endl;
std::cout << " rel y = " << event.state.Y.rel << std::endl;
std::cout << " abs x = " << event.state.X.abs << std::endl;
std::cout << " abs y = " << event.state.Y.abs << std::endl;
};
I'm creating a basic state system so I can start writing applications for Ogre3D using the OIS library for input. I have an Application class which acts as an input listener for the mouse and keyboard. Here is how its setup...
void Troll::Application::setup_ois() {
//create a parameter list for holding the window handle data
OIS::ParamList pl;
size_t windowHnd = 0;
//we need the window handle to setup OIS
std::ostringstream windowHndStr;
mWindow->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
//add the handle data into the parameter list
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
//create the input system with the parameter list (containing handle data)
mInputManager = OIS::InputManager::createInputSystem(pl);
//true in createInputObject means we want buffered input
mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));
//set this as an event handler
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
};
The application class relays the mouse moves, button pressed and key strokes to the Troll::State (the framework I'm making is called Troll) at the top of the state stack which is inside the Troll:: StateManager (which is merely a wrapper for an std::stack with memory allocation and startup() and shutdown() calls)
Sorry for any confusion the difference of the naming conventions causes for some reason I decided to use_underscores_for_some_reason and I haven't got round to changing it. Thanks in advance, ell. Hope you can solve my problem and please inform me if I haven't given enough detail.
EDIT:
After recently upgrading to Ubuntu Natty Narwhal I cannot get the debugger to work properly, it just crashes the computer. I use Code::Blocks and I don't have a clue how to use a debugger or compiler outside the IDE (sad I know, but I'll get round to learning someday). So sorry, I can't use a debugger.
EDIT:
In response to GMan's comment, even if I check for null, I still get segfaults
bool Troll::Application::keyPressed(const OIS::KeyEvent& event) {
//TODO: Segfault here!
Troll::State* state = mStateManager->peek();
if(state == 0) {
std::cout << "State is null!" << std::endl;
};
state->key_pressed(event);
return true;
};
Although I'm not sure thats the correct way to check for null? Also, other methods using peek() work correctly. Thanks again! :)
Important Edit:
It seems that it is in fact the peek function that is causing trouble, but only when called from the keyPressed function. I discovered this by adding a parameter to peek() so that it would print the address of the state object it return as well as the message. By setting the message parameter to the function from where the peek() function is called, I got these results.
Root state is: 0x8fdd470
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x8fdd470 from: Application::mouseMoved
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x936cf88 from: Application::keyPressed
Segmentation fault
Notice that when the keyPressed function calls the peek method, a different address is shown. I cannot see why a different address is being returned only when the keyPress function calls peek? Somebody please help me with this!
What happens when you check for mStateManager being NULL, and for NULL being returned from mStateManager->peek()?
bool Troll::Application::keyPressed(const OIS::KeyEvent& event) {
if (mStateManager == NULL) {
//! set breakpoint on next line
std::cout << "mStateManager is NULL, returning false" << std::endl;
return false;
}
std::cout << "about to call peek" << std::endl;
if (Troll::State* state = mStateManager->peek())
{
std::cout << "about to call key_pressed" << std::endl;
state->key_pressed(event); //Does this still cause a SEGFAULT?
std::cout << "back from key_pressed" << std::endl;
return true;
}
std::cout << "mStateManager->peek() returned NULL, returning false" << std::endl;
return false;
};
EDIT: I edited the code to print each branch, how it was traced through.
Related
I need to run a function with arguments (Installer::install) on a QProcess::finished signal. I've decided to use a lambda as slot, resulting in this:
private:
QProcess* unzip = new QProcess(this);`
void Installer::extract(QString source, QString destination) {
QStringList args;
args.append("x");
args.append(source);
args.append(QString("-o%1").arg(destination));
connect(unzip, &QProcess::finished, this, [=](int code, QProcess::ExitStatus status) {
if (code != 0 || status == QProcess::CrashExit) {
qDebug() << "Installer - Error >> Exit code:" << code;
qDebug() << "Installer - Error >> Status:" << status;
emit error();
}
else
install(destination + "/game.exe");
});
unzip->start("path\to\extractor\program.exe", args);
if (!unzip->waitForStarted()) {
qDebug() << "Installer - Error >> Extractor not started";
qDebug() << "Installer - Error Detail >>" << unzip->error();
emit error();
return;
}
qDebug() << "Sot Installer - Updates - Extractor >> Extracting...";
}
Installer::extract function is called at the end of every extraction. Supposing we have four archives to extract, Installer::extract will be called four times, with four different destination.
For the first archive, all works well. From the second one, the destination variable inside the lambda slot has the value of the first destination while it should have the second destination value. Instead, the destination variable outside the slot (e.g. in the last args.append) has the right value. Why is this happening and how can I solve this?
According to #Igor Tandetnik, connections were stacking up and so were the values of destination. Disconnecting all the connections of unzip before running Installer::extract again solved the problem.
I've recently started working with Qt and am trying to play a sound file using QMediaPlayer.
My program compiles and runs but the sound file is not played, the QMediaPlayer seems stuck in the QMediaPlayer::LoadingMedia state.
Also - and possibly related - the QMediaPlayer doesn't ever seem to emit its mediaStatusChanged or its error signals (though perhaps this is me not connecting them properly?)
When I run the program as below, it reaches the while loop and never leaves. If I query for player->mediaStatus() inside the loop, it constantly returns 2 (QMediaPlayer::LoadingMedia).
When I run it with the while loop omitted, the program continues to run until it reaches end of execution with no run-time errors but - as you may expect - the file is not played.
Interestingly, the two couts before the while loop, which report player's mediaStatus and state show that the mediaStatus changes from 1 (in the first instance, before setting the media) to 2 (after setting the media) but my ChangedStatus slot is never called, despite connecting to the mediaStatusChanged at the start of the run function.
Running: Debian Jessie, Qt5.7/Qt5.9
AudioPlayer.h
#include <QThread>
#include <QMediaPlayer>
class AudioPlayer : public QThread {
Q_OBJECT
public:
AudioPlayer();
public slots:
void ChangedStatus(QMediaPlayer::MediaStatus);
void MediaError(QMediaPlayer::Error);
protected:
void run();
};
AudioPlayer.cpp:
AudioPlayer::AudioPlayer(){}
void AudioPlayer::run()
{
QMediaPlayer* player = new QMediaPlayer();
connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(ChangedStatus(QMediaPlayer::MediaStatus)));
connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(MediaError(QMediaPlayer::Error)));
std::cout << "Got player!" << std::endl;
std::cout << "\n\n\tPlayer state: " << player->state() << "\n\tMediaState: " << player->mediaStatus() << std::endl;
player->setMedia(QUrl::fromLocalFile("/home/me/test.wav") );
std::cout << "Set source" << std::endl;
std::cout << "\n\n\tPlayer state: " << player->state() << "\n\tMediaState: " << player->mediaStatus() << std::endl;
while(player->mediaStatus() != QMediaPlayer::MediaStatus::LoadedMedia)
{//
}
player->setVolume(100);
std::cout << "Set volume" << std::endl;
player->play();
std::cout << "Played" << std::endl;
}
void AudioPlayer::MediaError(QMediaPlayer::Error error)
{
std::cout << "Media Error: " << error << std::endl;
}
void AudioPlayer::ChangedStatus(QMediaPlayer::MediaStatus status)
{
std::cout << "Status changed to: " << status << std::endl;
}
main.cpp:
#include "audioplayer.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
AudioPlayer myAudioPlayer;
myAudioPlayer.start();
std::cout << "myAudioPlayer started. Waiting...." << std::endl;
myAudioPlayer.wait();
std::cout << "myAudioPlayer returned." << std::endl;
return 0;
}
Extra Info:
Now, initially, I hadn't used QThread and was trying to do this all in main.cpp (just declaring a QMediaPlayer and attempting to set the media and play) but this was giving me QObject::startTimer: timers cannot be started from another thread warning run-time errors in a couple of places (declaration of the QMediaPlayer and, I think, the play command), so I adopted the above approach - although I'm not sure that subclassing QThread is, necessarily, the best way. This is also why everything (declarations etc.) is done in the run function - having the QMediaPlayer as a member of AudioPlayer and initialising it in the constructor gave the same error.
I have compiled and run Qt's Player example (from multimediawidgets) and, by browsing and selecting my test.wav, it can play the file so I don't think it's a compatibility issue. I looked through the Player example source but couldn't see anything jumping out which I had missed and which looked like the cause of my problem.
You should create an QApplication object and use it's message loop. I would suggest you to test following:
#include "audioplayer.h"
using namespace std;
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
AudioPlayer myAudioPlayer;
myAudioPlayer.start();
return a.exec();
}
You will at least get your signals raised. If the media state reaches QMediaPlayer::StoppedState or any error occured, you could call QApplication::instance()->quit() to stop your application.
Edit: Better use the new style connections like:
connect(player, &QMediaPlayer::mediaStatusChanged, this, &QMediaPlayer::ChangedStatus);
It is more reliable and you don't have to register specific parameter types like QMediaPlayer::MediaStatus with Q_DECLARE_METATYPE()
Because QMediaPlayer class contains another method called error with a different signature, signal connection is a bit more complicated. This is because the compiler don't know which error method you are referring to. In this case static_cast is the way to solve this ambiguity:
connect(
player,
static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error )>(&QMediaPlayer::error),
this,
&AudioPlayer::MediaError
);
Please note, a Wave file is only a container file that can contain an arbitrary compressed data stream. It may be necessary to install the appropriate operating system multimedia codec first. In Microsoft Windows Qt-Framework relies on installed multimedia codecs (.ax file).
Your AudioPlayer::run method will end without waiting for the media being played. So you should wait for the Stopped status some where before the thread ends. However it is better not to use the run method directly but using QThreads message loop instead.
class AudioPlayer : public QThread {
public:
AudioPlayer() : _Player(nullptr) {
moveToThread(this); // AudioPlayer object become part of this new thread
}
public slots:
void setVolume(int);
void load(QString Media);
// ...
void play() {
// Never directly access any members since they may belong to a different thread
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
} else {
_Player->play();
}
}
void stop() {
quit(); // Quiting thread message loop
}
private:
QMediaPlayer* _Player;
void run() {
_Player = new QMediaPlayer(this);
connect(...) // All connections go here...
int Result = QThread::exec();
_Player->stop();
delete _Player;
}
private slots:
void HandleStatusChange(QMediaPlayer::MediaStatus Status) {
emit statusChanged(Status); // Redirect so that the main application can handle this signal too
}
signals:
void statusChanged((QMediaPlayer::MediaStatus);
};
My program (in C++) uses libev event loop. And I need to watch on a specific folder (say foo) for new files.
I cannot use Inotify::WaitForEvents() in block mode because I do not want to block my libev event loop. As suggested in inotify documentation,I use Inotify::SetNonBlock(true) to make it non-block. The inotify file descriptor is then passed to libev EV_STAT to watch on (as suggested in libev documentation).
The libev callback for EV_STAT is indeed called when there are new files in the folder foo. However, when I use Inotify::WaitForEvents() followed by Inotify::GetEventCount(), I get zero event.
I suspect that libev already consumed the event and convert it to EV_STAT event. If this is the case, how can I get the names of those new files?
I knew there is inode number in EV_STAT callback parameters, but getting file name from inode number is not trivial. So it is better if I can get file name instead.
Any suggestions?
EDIT
I wrote a small program to reproduce this problem. It seems the events are not lost. Instead, inotify events do not come yet when libev callback is called. The event can re-appear when you copy in a new file.
The program to reproduce the issue:
#include <ev++.h>
#include "inotify-cxx.h"
#include <iostream>
const char * path_to_watch = "/path/to/my/folder";
class ev_inotify_test
{
InotifyWatch m_watch;
Inotify m_notify;
// for watching new files
ev::stat m_folderWatcher;
public:
ev_inotify_test() : m_watch(path_to_watch, IN_MOVED_TO | IN_CLOSE_WRITE),
m_notify()
{
}
void run()
{
try {
start();
// run the loop
ev::get_default_loop().run(0);
}
catch (InotifyException & e) {
std::cout << e.GetMessage() << std::endl;
}
catch (...) {
std::cout << "got an unknown exception." << std::endl;
}
}
private:
void start()
{
m_notify.SetNonBlock(true);
m_notify.Add(m_watch);
m_folderWatcher.set<ev_inotify_test, &ev_inotify_test::cb_stat>(this);
m_folderWatcher.set(path_to_watch);
m_folderWatcher.start();
}
void cb_stat(ev::stat &w, int revents)
{
std::cout << "cb_stat called" << std::endl;
try {
m_notify.WaitForEvents();
size_t count = m_notify.GetEventCount();
std::cout << "inotify got " << count << " event(s).\n";
while (count > 0) {
InotifyEvent event;
bool got_event = m_notify.GetEvent(&event);
std::cout << "inotify confirm got event" << std::endl;
if (got_event) {
std::string filename = event.GetName();
std::cout << "test: inotify got file " << filename << std::endl;
}
--count;
}
}
catch (InotifyException &e) {
std::cout << "inotify exception occurred: " << e.GetMessage() << std::endl;
}
catch (...) {
std::cout << "Unknown exception in inotify processing occurred!" << std::endl;
}
}
};
int main(int argc, char ** argv)
{
ev_inotify_test().run();
}
When I copy in a tiny file (say 300 bytes), the file is detected immediately. But if I copy a bigger file (say 500 kB), there is no event until I copy another file in and then I get two events.
The output looks like:
cb_stat called # test_file_1 (300 bytes) is copied in
inotify got 1 event(s).
inotify confirm got event
test: inotify got file test_file_1
cb_stat called # test_file_2 (500 KB) is copied in
inotify got 0 event(s). # no inotify event
cb_stat called # test_file_3 (300 bytes) is copied in
inotify got 2 event(s).
inotify confirm got event
test: inotify got file test_file_2
inotify confirm got event
test: inotify got file test_file_3
I finally figured out the problem: I should use ev::io to watch the file descriptor of inotify, instead of using ev::stat to watch the folder.
In the example code, the definition of m_folderWatcher should be:
ev::io m_folderWatcher;
instead of
ev::stat m_folderWatcher;
And it should be initialized as:
m_folderWatcher.set(m_notify.GetDescriptor(), ev::READ);
instead of
m_folderWatcher.set(path_to_watch);
I'm debugging an example app that deploys an Windows Metro App Package (".Appx" file). It call a WinRT method "PackageManager.AddPackageAsync" which fails with detailed error code text (retrieved from the call return value after the operation was finished):
error 0x80070002: Windows cannot register the package because of an
internal error or low memory.
My target is to find where exactly this error arises in the WinRT call. I think the best way for achieving this is by finding where the error code is set. I've done this before with the old simple Win32 API but now with this new complex com-based, async Interface I got completely lost.
The example project files can be found at. Its main function looks like this:
[MTAThread]
int __cdecl main(Platform::Array<String^>^ args)
{
wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl;
wcout << L"AddPackage sample" << endl << endl;
if (args->Length < 2)
{
wcout << "Usage: AddPackageSample.exe packageUri" << endl;
return 1;
}
HANDLE completedEvent = nullptr;
int returnValue = 0;
String^ inputPackageUri = args[1];
try
{
completedEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (completedEvent == nullptr)
{
wcout << L"CreateEvent Failed, error code=" << GetLastError() << endl;
returnValue = 1;
}
else
{
auto packageUri = ref new Uri(inputPackageUri);
auto packageManager = ref new PackageManager();
auto deploymentOperation = packageManager->AddPackageAsync(packageUri, nullptr, DeploymentOptions::None);
deploymentOperation->Completed =
ref new AsyncOperationWithProgressCompletedHandler<DeploymentResult^, DeploymentProgress>(
[&completedEvent](IAsyncOperationWithProgress<DeploymentResult^, DeploymentProgress>^ operation, AsyncStatus)
{
SetEvent(completedEvent);
});
wcout << L"Installing package " << inputPackageUri->Data() << endl;
wcout << L"Waiting for installation to complete..." << endl;
WaitForSingleObject(completedEvent, INFINITE);
if (deploymentOperation->Status == AsyncStatus::Error) //Here I decided to track "deploymentOperation->Status"
{
auto deploymentResult = deploymentOperation->GetResults();
wcout << L"Installation Error: " << deploymentOperation->ErrorCode.Value << endl;
wcout << L"Detailed Error Text: " << deploymentResult->ErrorText->Data() << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Canceled)
{
wcout << L"Installation Canceled" << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Completed)
{
wcout << L"Installation succeeded!" << endl;
}
}
}
catch (Exception^ ex)
{
wcout << L"AddPackageSample failed, error message: " << ex->ToString()->Data() << endl;
returnValue = 1;
}
if (completedEvent != nullptr)
CloseHandle(completedEvent);
return returnValue;
}
As the operation (PackageManager.AddPackageAsync) should be async and am not really sure how to track the code executed in the new thread I decided to search where the "deploymentOperation->Status" variable was set (it appeared that this was actually a function call) to "AsyncStatus::Error" (or the integer 3). After I gone through a LOT of code and function calls I understand that whenever this variable will be set or no (it seems it doesn't matter BUT it's certain that this function retrieves the operation error data) depends of a member of variable initialised by an Undocumented ntdll function call named "NtGetCompleteWnfStateSubscription" by it's pointer. It was called from ntdll too. The structure of the variable member I mentioned is the following:
struct Unknown
{
AsyncStatus /*? 32bit long*/ dw0; // it was set to '3' during the current operation as the AsyncStatus::error enum value so I think it should belong to it
DWORD dw4; //was set to 0x5F
DWORD dw8; //was set to 0x80073CF6 (some generic error)
} ;
The code in ntdll where the "NtGetCompleteWnfStateSubscription" function was called, initing the variable which member have this structure type (in assembly, IDA PRO generated):
ntdll.dll:77906200 loc_77906200: ; CODE XREF: ntdll.dll:ntdll_strncpy_s+1A3j
ntdll.dll:77906200 push 1030h
ntdll.dll:77906205 push esi ; the variable pointer
ntdll.dll:77906206 push edi
ntdll.dll:77906207 push eax
ntdll.dll:77906208 lea eax, [ebp-0Ch]
ntdll.dll:7790620B push eax
ntdll.dll:7790620C push ebx
ntdll.dll:7790620D call near ptr ntdll_NtGetCompleteWnfStateSubscription
ntdll.dll:77906212 test eax, eax ; now "[esi+2Ch] + esi" contains data from the "Unkown" structure and contains the operation error data
ntdll.dll:77906214 jns short loc_7790623F
The above code is actually called 3 times but with the same "esi" pointer. So now my question is how to find where the error code is set to be retrieved using this function. I tried capturing most of the function in ntdll that looks like doing this but without success. I can't debug NtGetCompleteWnfStateSubscription for some strange reason. Any suggestions will be helpful. I'm using IDA PRO 6.5, VS 2013 U1, Windows 8.1 x64 U1.
EDIT: If you don't want to bother with problem specific details my generic question is how to locate where WinRT async methods sets the "IAsyncInfo::Status" property or what function or method is called when an error arrises while executing them.
When I do a get GetWindowPlacement, the WINDOWPLACEMENT::showCmd seems to be always 1, which is SW_SHOWNORMAL.
Does anyone know why is this so and if it is updated? Does anyone know if this variable is maintained by the application itself or by the operating system?
I am running this on Windows 7.
I am using this to achieve the same purpose as mentioned in this thread: I am trying to undo hidden windows that were previously shown without storing the hidden windows in memory (hide/show will be called in different run sessions) or on disk.
void hide(const unsigned int pid){
std::list<HWND> windowList = getWindowbyPID(pid);
for(std::list<HWND>::iterator it = windowList.begin(); it != windowList.end(); it++){
if(IsWindowVisible(*it)){ std::cout << "Hid WIN#" << *it << std::endl; ShowWindow(*it,SW_HIDE); }
}
}
void show(const unsigned int pid){
std::list<HWND> windowList = getWindowbyPID(pid);
for(std::list<HWND>::iterator it = windowList.begin(); it != windowList.end(); it++){
//if(IsWindowVisible(*it)){ ShowWindow(*it,SW_SHOW); }
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
wp.showCmd = 0; // Just to clear showCmd before reading.
std::cout << *it << std::endl;
std::cout << "BEFORE: " << wp.showCmd << std::endl;
GetWindowPlacement(*it,&wp);
std::cout << "AFTER: " << wp.showCmd << std::endl;
}
}
Output of one example that I did (pid of notepad.exe) after hiding hwnd#00060CD0:
003D0642
BEFORE: 0
AFTER: 1
000B0682
BEFORE: 0
AFTER: 1
00060CD0
BEFORE: 0
AFTER: 1
I am trying to use GetWindowPlacement to differentiate the windows that were always hidden and the windows that were previously shown. It never seems to be 0 even for windows that were always hidden.
There are only three possible values of the showCmd after calling GetWindowPlacement.
From the MSDN documentation on GetWindowPlacement (emphasis mine):
The flags member of WINDOWPLACEMENT retrieved by this function is always zero. If the window identified by the hWnd parameter is maximized, the showCmd member is SW_SHOWMAXIMIZED. If the window is minimized, showCmd is SW_SHOWMINIMIZED. Otherwise, it is SW_SHOWNORMAL.
Therefore, it appears that the window you're asking for placement info on is in a state other than maximized or minimized when you're calling GetWindowPlacement.
I'd suspect what you're actually looking for is IsWindowVisible.