Why is my code not completing the Sound::release() call? - c++

I am creating a simple MP3 player and using the FMOD Core API for managing the audio. I have written a simple program to test the play() function.
I have two functions freeSound() and freeSystem() to free the sound and the system handle respectively. Both are called through the function cleanUp() in the destructor.
I have used gdb to figure out that for some reason, my program gets stuck in the Sound::release() call in freeSound() when the destructor is called.
This problem occurs only when freeSystem() is called before freeSound(). Simply calling the latter first fixes this issue.
I have shared as little code as I thought was possible to show this problem. If more/less is required I will add/remove.
The main() function:
int main()
{
musicPlayer p{"music.mp3"};
std::cout << "load success\n";
p.play();
std::cout << "press enter to quit\n";
std::cin.get();
}
The class declaration (includes only relevant bits):
class musicPlayer
{
private:
FMOD::System *m_system = nullptr;
FMOD::Sound *m_sound = nullptr;
/*Some more functions*/
void cleanUp();
void freeSystem();
void freeSound();
public:
~musicPlayer();
/*Some more functions*/
};
Destructor:
musicPlayer::~musicPlayer()
{
cleanUp();
m_channel = nullptr;
}
cleanUp():
void musicPlayer::cleanUp()
{
freeSystem();
freeSound();
}
freeSound() and freeSystem():
void musicPlayer::freeSystem()
{
if(m_system == nullptr)
return;
FMOD_RESULT result = m_system -> release();
if(result != FMOD_OK){
std::cerr << "freeSystem() Error: " << FMOD_ErrorString(result) << "\n";
return;
}
else
m_system = nullptr;
}
void musicPlayer::freeSound()
{
if(m_sound == nullptr)
return;
FMOD_RESULT result = m_sound -> release();
if(result != FMOD_OK){
std::cerr << "freeSound() Error: " << FMOD_ErrorString(result) << "\n";
return;
}
else
m_sound = nullptr;
}
I expect the audio to stop playing and the program to immediately quit when enter is pressed.
Instead, on pressing enter, the audio stops and the program does not quit.
UPDATE:
Earlier, I wrote:
Blockquote
I have written little test programs where I have called System::release() before Sound::release(). Such programs do not exhibit this issue.
I was wrong. The issue can be reproduced by playing a sound, calling cin.get() and then freeing the resources in the order wrong order.

The FMOD reference FMOD System::close should explain the behaviour:
"Closing renders objects created with this System invalid. Make sure any Sound, ChannelGroup, Geometry and DSP objects are released before calling this.".
System::close is called by System::release so when releasing the system before the components you stumble into problems. As you have found out yourself simply free everything before you release the system.

Related

How to terminate an application when an error happnes?

I am using a Graphics Library called Irrlicht
at some point i have to write this code
if(!device){
//error code here`
}
i am not in the main function but want to close the application when this error happens
please keep in mind that I am a beginner so this question might sound dumb
i see some people do this:
int main(){
if(!device){
return 1;
}
return 0;
}
i am not in the main function and want to exit the application outside of the main function
The following example give you an idea about some of the possibilities.
You can simply copy and paste it and play around with it. Simply use only one line of the "termination actions" like throw or exit. If you don't have the try catch block in the main function, your application will also terminate because the exception will not be caught.
struct DeviceNotAvailable {};
struct SomeOtherError{};
void func()
{
void* device = nullptr; // only for debug
if (!device)
{
// use only ONE of the following lines:
throw( DeviceNotAvailable{} );
//throw( SomeOtherError{} );
//abort();
//exit(-1);
}
}
int main()
{
// if you remove the try and catch, your app will terminate if you
// throw somewhere
try
{
func();
}
catch(DeviceNotAvailable)
{
std::cerr << "No device available" << std::endl;
}
catch(SomeOtherError)
{
std::cerr << "Some other error" << std::endl;
}
std::cout << "normal termination" << std::endl;
}

Program with a separate thread is being killed

After declaring an object in my main and running its function in a separate thread, my program crashes.
I have read other question on SO but due to my lack of knowledge in multithreading, I cannot understand what is my specific problem.
Here is my class called UART (without header files and only showing the required cpp declaration):
void UART::run()
{
while(true)
{
_letter = _serial.read();
if (_letter == "!")
{
_line = _serial.readline();
_words.clear();
std::istringstream f(_line);
std::string s;
//std::cout << _letter << std::endl;
while (getline(f,s,'\t'))
{
_words.push_back(s);
}
this->fillVars();
}
}
}
void UART::fillVars()
{
if (_words[0] == "s")
{
_effort[0] = std::stoi(_words[1]);
_effort[1] = std::stoi(_words[2]);
}
else if (_words[0] == "e")
{
this->convertToMeters();
}
}
void UART::convertToMeters()
{
std::cout << _position[0];
_position[0] = std::stod(_words[1]); // / _tick_meters;
_position[1] = std::stod(_words[2]) / _tick_meters;
}
double UART::getPosition(std::string wheel)
{
if (wheel == "LEFT") return _position[0];
else return _position[1];
}
And my main cpp looks like this:
int main(int argc, char** argv)
{
ros::init(argc, argv, "joint_node");
std::string port("/dev/ttyACM0");
unsigned long baud = 115200;
try
{
serial::Serial my_serial(port, baud, serial::Timeout::simpleTimeout(1000));
if(my_serial.isOpen()) ROS_INFO("Serial is %s", "open");
genius::UART uart(my_serial, 380);
std::thread uart_run(&genius::UART::run, uart);
std::cout << uart.getPosition("LEFT") <<std::endl;
} catch (std::exception &e)
{
std::cerr << "Unhandled Exception: " << e.what() << std::endl;
}
return 0;
}
My understanding is that after creating an object uart, I want to run its function run() in a separate thread as I want its values to be updated with no interruption on a background. So whenever I access its values like using its function uart.getPosition("LEFT") I will get the last up-to date data. I guess I do not need .join() this thread as I do not want to wait for it as it never ends.
But for some reason after calling the uart.getPosition("LEFT") my program crashes and also function getPosition() never gets executed and I always get value of 0.

Pause and resume a c++ function

I'm facing a problem in programmation where I did not find any convenient and fast execution solutions.
I'm trying to implement some kind of state machine : take one byte in entry, process it, change state, loop, etc... The purpose is to process byte stream without requiring any memory buffer (processing byte per byte).
The class should looks like this :
class Decoder {
void next() {
int i = 0;
std::cout << i << "\n";
i++;
yield(); // pseudo code => should stop the function and save the current state (or simply not freeing allocated variables)
std::cout << i << "\n";
}
};
Decoder decoder = Decoder();
decoder.next(); // print 1
std::cout << "1.5" << "\n"; // print 1.5
decoder.next(); // print 2
A solution could be to create a step property to save the step and then resume with a switch but the performances would be strongly impacted. I would like to know if there is a way to exit the execution of a function and then resume it later ?
To be clear, I don't want to pause the entire program, only a function. Pausing such a function would return to the caller and continue the execution of the program until the next next is called.
Moreover, I would like to avoid thread and std as much (I prefer all environnements code). Finally, if you have any other alternatives to my problem : process byte stream efficiently for the memory, I'm open to your suggestions.
Thanks for your help.
I believe you could achieve just that using these two ways:
Option 1: Member state
Split the state machine object into a separate object, and convert all your local variables to members.
For each step of the way, save a State member, signifying where are you now throughout the execution of your program.
Each time you enter next() check your state against a switch and call the designated inner method for that step.
Each such step method simulates code execution between to consecutive yields.
struct Decoder {
void next() {
switch (_step) {
case s1:
step1();
_step = s2;
return;
case s2:
step2();
_step = s1;
return;
default:
return; // handle error...
}
}
private:
enum Step { s1, s2 };
Step _step = s1;
int _i = 1;
void step1() {
std::cout << _i << "\n";
_i++;
}
void step2() {
std::cout << _i << "\n";
}
};
int main() {
Decoder decoder = Decoder();
decoder.next(); // print 1
std::cout << "1.5" << "\n"; // print 1.5
decoder.next(); // print 2
}
Option 2: Thread and signalling
Use a thread, which you could of course run using native APIs (e.g. pthread_create on POSIX platforms).
Inside your thread, every time you want to yield, wait on a conditional variable, e.g:
struct Decoder {
Decoder() {
_thread = std::thread { &Decoder::worker, this };
}
~Decoder() {
_thread.join();
}
void next() {
std::lock_guard<std::mutex> lock(_mutex);
_work = true;
}
private:
void wait() {
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock, [this](){return _work;});
}
void worker() {
wait();
int i = 0;
std::cout << i << "\n";
i++;
wait();
std::cout << i << "\n";
}
std::thread _thread;
std::mutex _mutex;
std::condition_variable _cond;
bool _work = false;
};
int main() {
Decoder decoder;
decoder.next(); // print 1
std::cout << "1.5" << "\n"; // print 1.5
decoder.next(); // print 2
}

what tools to use to find c++ bug when compile for release. boost::asio, cmake. vs2012. crossroads / 0mq

I have having some sort of memory or winsock issue that only occurs when c++ code is compiled in release mode.
Evidence that its a memory issue:
A previous unknown bug was fixed, by commenting out two lines of code. These two lines of code seem harmless. they were left overs from old versions. This indicates that somewhere I am using un-initialized memory. XS_Client is used as a base class.
class XS_Client
{
private:
/* these two lines of comments fixed the bug */
/***********************************************
enum { max_length = 1024 };
char data_[max_length];
**********************************************/
void * context_;
void * socket_;
boost::thread t_;
volatile bool should_run_;
public:
XS_Client(void *context, short type, const std::string &address)
: context_(context), socket_(XS_Socket::NewSocket(context_,type))
{
XS_Socket::Connect(socket_,address);
#ifdef _OUTPUTD
std::cout << address << " XS_Client: " << GetCurrentThreadId() << std::endl;
#endif
boost::thread t(boost::bind(&XS_Client::thread_func, this));
t_.swap(t);
}
void SetSockOpt(int option, const void *optval,size_t optvallen)
{
int rc = xs_setsockopt(socket_,option,optval,optvallen);
if ( rc != 0 )
std::cout << "xs_setsockopt error: " << xs_strerror(errno) << std::endl;
}
virtual ~XS_Client()
{
if ( should_run_ )
Stop();
}
void thread_func() {
/* Create an empty message */
xs_msg_t msg;
while (should_run_)
{
//int bytes_recvd = xs_recv(socket_,data_,max_length,0);
int rc = xs_msg_init (&msg);
if ( rc != 0 )
std::cout << "xs_msg_init error: " << xs_strerror(errno) << std::endl;
assert (rc == 0);
/* Block until a message is available to be received from socket */
int bytes_recvd = xs_recvmsg (socket_, &msg, 0);
#ifdef _DEBUG
std::cout << "received " << bytes_recvd << std::endl;
#endif;
if ( bytes_recvd == -1 )
{
if ( xs_errno() == ETERM )
{
should_run_ = false;
std::cout << "ETERM received" << xs_strerror(errno) << std::endl;
break;
}
if ( !should_run_ )
xs_msg_close (&msg);
else
{
std::cout << "receive error!" << xs_strerror(errno) << std::endl;
boost::this_thread::sleep(boost::posix_time::milliseconds(100u));
}
}
else
{
#ifdef _DEBUG
//std::cout << "received " << xs_msg_data(&msg) << std::endl;
#endif;
OnMsg(xs_msg_data(&msg),bytes_recvd);
/* Release message */
xs_msg_close (&msg);
}
}
int rc = xs_close (socket_);
if ( rc != 0 )
std::cout << "xs_close error: " << xs_strerror(errno) << std::endl;
Cleanup();
}
virtual void OnMsg(const void *msg, int bytes_recvd)
{
std::cout << "virtual void OnMsg received " << bytes_recvd << std::endl;
}
virtual void Stop()
{
should_run_ = false;
t_.timed_join(boost::posix_time::milliseconds(2000));
}
virtual void Cleanup()
{
}
};
Evidence that its a windows/socket issue:
The real bug is that my tcp socket (localhost) never gets data. However this only occurs when I am using both boost::asio and crossroads/0mq in same process. Also, the bug does not occur if I start the process through the debugger.
So when I compile in "realesewithdebuginfo" mode the bug only occurs when not in the debugger. same exact compiled code.
question1: what tool is recommended for c++ code analysis and/or windows api call analysis? Also, the problem is not easily recreated, so a static analysis may be best. i use lots of templates, boost::asio::udp, multiple treading libraries. multiple socket/io libraries.
question2: what is available on the windows side to see if I am causing a deadlock due to socket i/o mis-us-sages by external libraries?
tyvm4yh
The main difference between running under a debugger and not is the debug heap. To switch the debug heap off, you can use the _NO_DEBUG_HEAP environment variable. You can set this globally, but you're much better off doing it just for your debugging runs, as in this answer:
https://stackoverflow.com/a/1060929/1618406
If this reproduces the bug, but you're having difficulty actually debugging (because of the optimised code), I'd just temporarily disable optimisations for your release build. Just don't forget to switch them back on again...
Pretty much every time, switching the debug heap off and disabling optimisations has let me reproduce this kind of bug in the debugger, and then debug it without too much hassle.
Additionally, if you use Windows 7, you may find the Program Compatibility Assistant is stepping in and doing something that makes your program work, even though it shouldn't:
http://www.virtualdub.org/blog/pivot/entry.php?id=319
You can supposedly disable this in your program's manifest, but I prefer to have it disabled using the Group Policy Editor, e.g.:
http://www.howtogeek.com/howto/4161/disable-program-compatibility-assistant-in-windows-7-and-vista/
Disabling the Program Compatibility Assistant is highly recommended if you ever run your program outside the debugger...

deadlock and\or return before thread is dead

I'm stuck for about 2 days in the same situation and i'd really appreciate any help.
The main thread is calling the initDevice() function, which is opening the file and creating a new thread, which he will be the "writing" thread, with the writeToDeviceHandler() function.
The write2device() is called from main() and should insert new tasks to write (in the future) to a map<int,Task*>. The problem is, that sometimes the application is stuck at some kind of an inifinite loop or a deadlock and sometimes it writes <(# of tasks) to write.
Can anyone see if there's anything wrong in the code?
THANKS!
int write2device(char *buffer, int length)
{
if(is_running)
{
pthread_mutex_lock(&tasks_mutex);//LOCK
int curr_id = getNextAvailableId();
Task* new_task = new Task(buffer,length, curr_id);
tasks[curr_id] = new_task;
pthread_cond_signal(&tasks_cv);
given_ids.insert(curr_id);
pthread_mutex_unlock(&tasks_mutex);//UNLOCK
return curr_id;
}
return FAIL;
}
int initdevice(char *filename)
{
is_running = true;
pthread_cond_signal(&tasks_cv);
output_file.open(filename);
if(!output_file.is_open())
{
cerr << "Error opening file" << endl;
is_running = false;
return SYSTEM_ERROR;
}
int res = pthread_create(&writing_thread, NULL, writeToDeviceHandler, NULL);//Create the writing to file thread.
if(res != 0)
{
cerr << "Error creating the writing thread" <<endl;
exit(FAIL);
}
return SUCCESS;
}
void *writeToDeviceHandler(void *arg)
{
Task* curr_task;
while(is_running)
{
pthread_mutex_lock(&tasks_mutex);
cout << "IN LOOP - size of db: " << tasks.size() << endl;
if(tasks.empty())
{
pthread_cond_wait(&tasks_cv, &tasks_mutex);
}
if(tasks.empty()) cout << "Empty, still finding thread" <<endl;
curr_task = tasks.begin()->second;
if(curr_task == NULL)
{
pthread_mutex_unlock(&tasks_mutex);
continue;
}
//copy from tasks to file
output_file.write(curr_task->getBuff(), curr_task->getLength());
ids.remove(curr_task->getId());
tasks.erase(curr_task->getId());
delete curr_task;
pthread_mutex_unlock(&tasks_mutex);
}
pthread_exit(NULL);
return NULL;
}
Your code is not correct in that it does not have a loop around the pthread_cond_wait call. The pthread_cond_wait call can return on spurious wakeup. You have to check for your wakeup condition after it returns. In your case it looks like it should be something like this:
while (task.empty ())
pthread_cond_wait(&tasks_cv, &tasks_mutex);
Your code also lacks error checking. Do check all return values of all functions for errors.
Your writeToDeviceHandler code does all its work while holding the mutex, defeating the point of having the thread at all. If another thread wants to give this thread work to do, it will have to acquire the tasks_mutex. To do that, it will have to finish until this thread finishes writing and releases the mutex. So why bother with this thread at all?
When you have a mutex that protects work that needs to be done, the whole point is to actually do the work with the mutex released. That way, other threads don't have to wait while you finish the work.