Segmentation Fault in Referencer



Hi, everyone,

I am trying to fix a strange segmentation fault in Referencer
( http://icculus.org/referencer/ ).

The segfault happens predictably in one particular function, but not at
the same spot. However, I managed to isolate the culprit to GTKMM API
calls.

So, the error happens in a function called 'load'. However, it works
fine if I simply remove all UI code from it (comment it out, or just
make sure the UI bits don't get executed). Note that the UI code just
asks the user a simple question and updates the progress bar.

Please find the (abridged) code of the 'load' function attached in
'load.C', I will refer to it now:

So, if I comment out lines 3, 5, 8, 32 and also make sure the execution
never goes into the 'if' in line 10 (that is, if I make sure 'something'
is always false), then things will work fine. However, if I don't
comment out the above lines, it will segfault randomly within the
for-loop (because of calls to 'progress'). Also, if I don't ensure that
'something' is always false, then the code will segfault exactly when we
want show the message box.

The above 'load' function is called within 'onOpenLibrary', which is
registered to an action group like this:

	actiongroup_->add( Gtk::Action::create("OpenLibrary",
		Gtk::Stock::OPEN, _("_Open...")),
  	sigc::mem_fun(*this, &RefWindow::onOpenLibrary));

Thank you very much,
---
Matej
/*
 * Referencer is released under the GNU General Public License v2
 * See the COPYING file for licensing details.
 *
 * Copyright 2007 John Spray
 * (Exceptions listed in README)
 *
 */



#include <iostream>

#include <libgnomemm/main.h>

#include "RefWindow.h"

#include "Progress.h"


Progress::Progress (RefWindow &refwindow)
	: win_ (refwindow)
{
	finished_ = true;
}


Progress::~Progress ()
{
	if (!finished_)
		finish ();
}


void Progress::start (Glib::ustring const &text)
{
	// Flag that the loop thread waits for
	finished_ = false;
	win_.setSensitive (false);
	win_.getProgressBar()->set_fraction (0.0);
	msgid_ = win_.getStatusBar()->push (text);
}


void Progress::finish ()
{
	finished_ = true;
	win_.getProgressBar()->set_fraction (1.0);
	win_.setSensitive (true);
	win_.getStatusBar()->remove_message (msgid_);
}


void Progress::update (double status)
{
	win_.getProgressBar()->set_fraction (status);
	flushEvents ();
}


void Progress::update ()
{
	win_.getProgressBar()->pulse ();
	flushEvents ();
}


void Progress::flushEvents ()
{
	while (Gnome::Main::events_pending())
		Gnome::Main::iteration ();
}


/*
 * Referencer is released under the GNU General Public License v2
 * See the COPYING file for licensing details.
 *
 * Copyright 2007 John Spray
 * (Exceptions listed in README)
 *
 */


#ifndef PROGRESS_H
#define PROGRESS_H

#include <gtkmm.h>

class RefWindow;

class Progress {
	public:
	Progress (RefWindow &tagwindow);
	~Progress ();

	void start (Glib::ustring const &text);
	void update (double status);
	void update ();
	void finish ();

	private:
	void flushEvents ();

	bool finished_;
	RefWindow &win_;
	int msgid_;
};

#endif

bool Library::load(Glib::ustring const &libfilename) {
    // See the 'Progess.h' and 'Progress.C' files for more info on 'progress'.
    Progress progress(tagwindow_);
    // Do some stuff..
    progress.update(0.2);
    // Dome some more stuff...
    for (; docit != docend; ++docit) {
        progress.update(...next step...);
        // Do even more stuff...
        if (something) {
            Gtk::MessageDialog dialog(message, true, Gtk::MESSAGE_QUESTION,
                    Gtk::BUTTONS_NONE, true);

            Gtk::CheckButton applytoall(_(
                    "Apply choice to all ambiguous locations"));
            dialog.get_vbox()->pack_start(applytoall, 0, false, false);
            applytoall.show();

            dialog.add_button(_("Keep _Original"), ORIG_LOC);
            dialog.add_button(_("Use _New"), NEW_LOC);
            dialog.set_default_response(ORIG_LOC);

            action = (ambiguouschoice) dialog.run();
            if (applytoall.get_active()) {
                something = false;
            }
        }
        if (action == NEW_LOC) {
            docit->setFileName(relfilename);
        }
    }
    progress.finish();
    return true;
}

Attachment: signature.asc
Description: This is a digitally signed message part



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]