[Vala] Problem with Closure in Coroutine
- From: Michael 'Mickey' Lauer <mickey vanille-media de>
- To: Vala-list <Vala-list gnome org>
- Subject: [Vala] Problem with Closure in Coroutine
- Date: Sat, 12 Dec 2009 19:18:59 +0100
Gnome bugzilla is down today, so after the deafening silence on IRC I
figured I might give mail a chance. This function:
========================================================================
public override async void play_sound( string name, int loop, int
length ) throws FreeSmartphone.Device.AudioError, FreeSmartphone.Error
{
PlayingSound sound = sounds[name];
if ( sound != null )
{
throw new
FreeSmartphone.Device.AudioError.ALREADY_PLAYING( "%s is already
playing".printf( name ) );
}
var parts = name.split( "." );
if ( parts.length == 0 )
{
throw new FreeSmartphone.Error.INVALID_PARAMETER( "Could not
guess media format; need an extension" );
}
var extension = parts[ parts.length - 1 ]; // darn, I miss
negative array indices
var decoder = decoders[extension];
assert( decoder != null );
assert( this != null );
try
ERROR:plugin.c:464:_lambda1_: assertion failed: (self != NULL)
Aborted
{
var pipeline = Gst.parse_launch( @"filesrc location=\"$name
\" ! $decoder ! alsasink" );
sound = new PlayingSound( name, loop, length,
(uint32)pipeline );
Gst.Bus bus = pipeline.get_bus();
bus.add_watch( ( bus, message ) => {
assert( this != null );
return onGstreamerMessage( bus, message, sound );
} );
pipeline.set_state( Gst.State.PLAYING );
}
catch ( GLib.Error e )
{
FsoFramework.theLogger.warning( @"Could not create/launch
GStreamer pipeline: $(e.message)" );
return;
}
}
========================================================================
bails out at runtime with:
ERROR:plugin.c:464:_lambda1_: assertion failed: (self != NULL)
Aborted
========================================================================
The problem seems to be that the data for the closure (_data_->_data2_)
gets unref'ed when the function ends; however Gst is calling the
callback later on and then the instance is 0x0. The C code for this
function is:
========================================================================
static gboolean player_gstreamer_real_play_sound_co
(PlayerGstreamerPlaySoundData* data) {
switch (data->_state_) {
default:
g_assert_not_reached ();
case 0:
{
data->_data2_ = g_slice_new0 (Block2Data);
data->_data2_->_ref_count_ = 1;
data->_data2_->self = g_object_ref (data->self);
data->_data2_->sound = (FsoDevicePlayingSound*) gee_abstract_map_get
((GeeAbstractMap*) ((FsoDeviceBaseAudioPlayer*) data->self)->sounds,
data->name);
if (data->_data2_->sound != NULL) {
data->_inner_error_ = (data->_tmp1_ = g_error_new_literal
(FREE_SMARTPHONE_DEVICE_AUDIO_ERROR,
FREE_SMARTPHONE_DEVICE_AUDIO_ERROR_ALREADY_PLAYING, data->_tmp0_ =
g_strdup_printf ("%s is already playing", data->name)), _g_free0
(data->_tmp0_), data->_tmp1_);
if (data->_inner_error_ != NULL) {
if ((data->_inner_error_->domain ==
FREE_SMARTPHONE_DEVICE_AUDIO_ERROR) || (data->_inner_error_->domain ==
FREE_SMARTPHONE_ERROR)) {
g_simple_async_result_set_from_error (data->_async_result,
data->_inner_error_);
g_error_free (data->_inner_error_);
block2_data_unref (data->_data2_);
{
if (data->_state_ == 0) {
g_simple_async_result_complete_in_idle
(data->_async_result);
} else {
g_simple_async_result_complete
(data->_async_result);
}
g_object_unref (data->_async_result);
return FALSE;
}
} else {
block2_data_unref (data->_data2_);
g_critical ("file %s: line %d: uncaught error: %s", __FILE__,
__LINE__, data->_inner_error_->message);
g_clear_error (&data->_inner_error_);
return FALSE;
}
}
}
data->parts = (data->_tmp3_ = data->_tmp2_ = g_strsplit (data->name,
".", 0), data->parts_length1 = _vala_array_length (data->_tmp2_),
data->parts_size = data->parts_length1, data->_tmp3_);
if (data->parts_length1 == 0) {
data->_inner_error_ = g_error_new_literal (FREE_SMARTPHONE_ERROR,
FREE_SMARTPHONE_ERROR_INVALID_PARAMETER, "Could not guess media format;
need an extension");
if (data->_inner_error_ != NULL) {
if ((data->_inner_error_->domain ==
FREE_SMARTPHONE_DEVICE_AUDIO_ERROR) || (data->_inner_error_->domain ==
FREE_SMARTPHONE_ERROR)) {
g_simple_async_result_set_from_error (data->_async_result,
data->_inner_error_);
g_error_free (data->_inner_error_);
data->parts = (_vala_array_free (data->parts,
data->parts_length1,
(GDestroyNotify) g_free), NULL);
block2_data_unref (data->_data2_);
{
if (data->_state_ == 0) {
g_simple_async_result_complete_in_idle
(data->_async_result);
} else {
g_simple_async_result_complete
(data->_async_result);
}
g_object_unref (data->_async_result);
return FALSE;
}
} else {
data->parts = (_vala_array_free (data->parts,
data->parts_length1,
(GDestroyNotify) g_free), NULL);
block2_data_unref (data->_data2_);
g_critical ("file %s: line %d: uncaught error: %s", __FILE__,
__LINE__, data->_inner_error_->message);
g_clear_error (&data->_inner_error_);
return FALSE;
}
}
}
data->extension = g_strdup (data->parts[data->parts_length1 - 1]);
data->decoder = (char*) gee_abstract_map_get ((GeeAbstractMap*)
data->self->priv->decoders, data->extension);
g_assert (data->decoder != NULL);
g_assert (data->self != NULL);
{
data->pipeline = (data->_tmp5_ = gst_parse_launch (data->_tmp4_ =
g_strconcat ("filesrc location=\"", string_to_string (data->name), "\" !
", string_to_string (data->decoder), " ! alsasink", NULL),
&data->_inner_error_), _g_free0 (data->_tmp4_), data->_tmp5_);
if (data->_inner_error_ != NULL) {
goto __catch1_g_error;
goto __finally1;
}
data->_data2_->sound = (data->_tmp6_ = fso_device_playing_sound_new
(data->name, data->loop, data->length, (guint32) data->pipeline),
_fso_device_playing_sound_unref0 (data->_data2_->sound), data->_tmp6_);
data->bus = gst_element_get_bus (data->pipeline);
gst_bus_add_watch (data->bus, __lambda1__gst_bus_func,
data->_data2_);
gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
_gst_object_unref0 (data->pipeline);
_gst_object_unref0 (data->bus);
}
goto __finally1;
__catch1_g_error:
{
data->e = data->_inner_error_;
data->_inner_error_ = NULL;
{
fso_framework_logger_warning (fso_framework_theLogger, data->_tmp7_
= g_strconcat ("Could not create/launch GStreamer pipeline: ",
string_to_string (data->e->message), NULL));
_g_free0 (data->_tmp7_);
_g_error_free0 (data->e);
data->parts = (_vala_array_free (data->parts, data->parts_length1,
(GDestroyNotify) g_free), NULL);
_g_free0 (data->extension);
_g_free0 (data->decoder);
block2_data_unref (data->_data2_);
{
if (data->_state_ == 0) {
g_simple_async_result_complete_in_idle
(data->_async_result);
} else {
g_simple_async_result_complete (data->_async_result);
}
g_object_unref (data->_async_result);
return FALSE;
}
_g_error_free0 (data->e);
}
}
__finally1:
if (data->_inner_error_ != NULL) {
if ((data->_inner_error_->domain ==
FREE_SMARTPHONE_DEVICE_AUDIO_ERROR) || (data->_inner_error_->domain ==
FREE_SMARTPHONE_ERROR)) {
g_simple_async_result_set_from_error (data->_async_result,
data->_inner_error_);
g_error_free (data->_inner_error_);
data->parts = (_vala_array_free (data->parts, data->parts_length1,
(GDestroyNotify) g_free), NULL);
_g_free0 (data->extension);
_g_free0 (data->decoder);
block2_data_unref (data->_data2_);
{
if (data->_state_ == 0) {
g_simple_async_result_complete_in_idle
(data->_async_result);
} else {
g_simple_async_result_complete (data->_async_result);
}
g_object_unref (data->_async_result);
return FALSE;
}
} else {
data->parts = (_vala_array_free (data->parts, data->parts_length1,
(GDestroyNotify) g_free), NULL);
_g_free0 (data->extension);
_g_free0 (data->decoder);
block2_data_unref (data->_data2_);
g_critical ("file %s: line %d: uncaught error: %s", __FILE__,
__LINE__, data->_inner_error_->message);
g_clear_error (&data->_inner_error_);
return FALSE;
}
}
data->parts = (_vala_array_free (data->parts, data->parts_length1,
(GDestroyNotify) g_free), NULL);
_g_free0 (data->extension);
_g_free0 (data->decoder);
*** block2_data_unref (data->_data2_);
}
{
if (data->_state_ == 0) {
g_simple_async_result_complete_in_idle (data->_async_result);
} else {
g_simple_async_result_complete (data->_async_result);
}
g_object_unref (data->_async_result);
return FALSE;
}
}
}
========================================================================
and the problem seems to be triggered by the line I have marked (***).
Is this a bug in Vala or am I using the closure wrongly?
Thanks,
--
:M:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]