Avoid glibmm GSource bug/crash (#697727)

The glibmm GSource wrappers have a bug where they do not do
reference counting properly, and have a race condition where
the background thread can try to touch the source after the
main thread has already processed and destroyed it.  This
results in writes to freed memory and sometimes this causes
crashes or other erratic behavior.  Avoid using the glibmm
wrappers and use glib directly.  See bug #561885 for details
of the glibmm bug.

Bug #697727 - Segfault in livecd Gparted v 0.15.0-3 when copying partition
This commit is contained in:
Phillip Susi 2013-04-16 11:43:41 -04:00 committed by Curtis Gedak
parent 50ca2e5f13
commit c36934aca5
3 changed files with 16 additions and 10 deletions

View file

@ -40,12 +40,12 @@ class copy_blocks {
Glib::Timer timer_total;
bool success;
Glib::ustring error_message;
bool set_progress_info();
void copy_thread();
bool cancel;
bool cancel_safe;
void set_cancel( bool force );
public:
bool set_progress_info();
copy_blocks( const Glib::ustring & in_src_device,
const Glib::ustring & in_dst_device,
Sector src_start,

View file

@ -94,6 +94,12 @@ static bool mainquit(copy_blocks *cb)
return false;
}
static gboolean _set_progress_info( gpointer data )
{
copy_blocks *cb = (copy_blocks *)data;
return cb->set_progress_info();
}
void copy_blocks::copy_thread()
{
if ( ped_device_open( lp_device_src ) &&
@ -132,9 +138,7 @@ void copy_blocks::copy_thread()
copy_block();
if ( timer_progress_timeout .elapsed() >= 0.5 )
{
Glib::signal_idle().connect( sigc::mem_fun(
*this,
&copy_blocks::set_progress_info) );
g_idle_add( _set_progress_info, this );
timer_progress_timeout.reset();
}
}
@ -151,9 +155,7 @@ void copy_blocks::copy_thread()
}
//set progress bar current info on completion
Glib::signal_idle().connect( sigc::mem_fun(
*this,
&copy_blocks::set_progress_info) );
g_idle_add( _set_progress_info, this );
g_idle_add( (GSourceFunc)mainquit, this );
}

View file

@ -453,6 +453,12 @@ static void set_locale()
setenv( "LC_ALL", "C", 1 );
}
static void _store_exit_status( GPid pid, gint status, gpointer data )
{
utils_execute_command_status *sp = (utils_execute_command_status *)data;
sp->store_exit_status( pid, status );
}
int Utils::execute_command( const Glib::ustring & command,
Glib::ustring & output,
Glib::ustring & error,
@ -482,9 +488,7 @@ int Utils::execute_command( const Glib::ustring & command,
}
fcntl( out, F_SETFL, O_NONBLOCK );
fcntl( err, F_SETFL, O_NONBLOCK );
Glib::signal_child_watch().connect( sigc::mem_fun(
status, &utils_execute_command_status::store_exit_status ),
pid );
g_child_watch_add( pid, _store_exit_status, &status );
output.clear();
error.clear();
//Lock mutex so we have time to setup pipecapture for output and error streams