- More refcounting fixes that now sustain abuse from spider, key is to be careful...
authorWim Taymans <wim.taymans@gmail.com>
Thu, 27 Feb 2003 23:07:30 +0000 (23:07 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 27 Feb 2003 23:07:30 +0000 (23:07 +0000)
Original commit message from CVS:
- More refcounting fixes that now sustain abuse from spider, key is to be
careful when iterating over a list when our current pointer could be
removed.

gst/schedulers/gstoptimalscheduler.c

index 911829b..caea392 100644 (file)
@@ -165,9 +165,12 @@ struct _GstOptSchedulerGroup {
 };
 
 /* some group operations */
-static GstOptSchedulerGroup*   ref_group       (GstOptSchedulerGroup *group);
-static GstOptSchedulerGroup*   unref_group     (GstOptSchedulerGroup *group);
-static void                    destroy_group   (GstOptSchedulerGroup *group);
+static GstOptSchedulerGroup*   ref_group               (GstOptSchedulerGroup *group);
+#ifndef USE_COTHREADS
+static GstOptSchedulerGroup*   ref_group_by_count      (GstOptSchedulerGroup *group, gint count);
+#endif
+static GstOptSchedulerGroup*   unref_group             (GstOptSchedulerGroup *group);
+static void                    destroy_group           (GstOptSchedulerGroup *group);
 
 /* 
  * Scheduler private data for an element 
@@ -460,6 +463,9 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
     GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data;
     walk = g_slist_next (walk);
 
+    GST_INFO (GST_CAT_SCHEDULING, "reparenting group %p from chain %p to %p", 
+                   group, chain2, chain1);
+
     group->chain = NULL;
     chain2->num_groups--;
     chain2 = unref_chain (chain2);
@@ -468,7 +474,9 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
     chain1->groups = g_slist_prepend (chain1->groups, group);
     chain1->num_groups++;
   }
-  chain2 = unref_chain (chain2);
+  g_slist_free (chain2->groups);
+  chain2->groups = NULL;
+  unref_chain (chain2);
 
   return chain1;
 }
@@ -524,6 +532,19 @@ ref_group (GstOptSchedulerGroup *group)
   return group;
 }
 
+#ifndef USE_COTHREADS
+static GstOptSchedulerGroup*
+ref_group_by_count (GstOptSchedulerGroup *group, gint count)
+{
+  GST_INFO (GST_CAT_SCHEDULING, "ref group %p %d->%d", group, 
+                 group->refcount, group->refcount+count);
+
+  group->refcount += count;
+
+  return group;
+}
+#endif
+
 static GstOptSchedulerGroup*
 unref_group (GstOptSchedulerGroup *group)
 {
@@ -744,18 +765,24 @@ gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched)
 
   while (osched->runqueue) {
     GstOptSchedulerGroup *group;
+    gboolean res;
     
     group = (GstOptSchedulerGroup *) osched->runqueue->data;
+
+    /* runqueue hols refcount to group */
     osched->runqueue = g_list_remove (osched->runqueue, group);
 
     GST_INFO (GST_CAT_SCHEDULING, "scheduling %p", group);
 
-    if (!schedule_group (group)) {
+    res = schedule_group (group);
+    if (!res) {
       g_warning  ("error scheduling group %p", group);
       group_error_handler (group);
     }
-
-    GST_INFO (GST_CAT_SCHEDULING, "done scheduling %p", group);
+    else {
+      GST_INFO (GST_CAT_SCHEDULING, "done scheduling %p", group);
+    }
+    unref_group (group);
   }
 
   GST_INFO (GST_CAT_SCHEDULING, "run queue length after scheduling %d", g_list_length (osched->runqueue));
@@ -777,20 +804,22 @@ schedule_chain (GstOptSchedulerChain *chain)
   while (groups) {
     GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) groups->data;
 
-    groups = g_slist_next (groups);
-
     if (!GST_OPT_SCHEDULER_GROUP_IS_DISABLED (group)) {
-
+      ref_group (group);
       GST_INFO (GST_CAT_SCHEDULING, "scheduling group %p in chain %p", 
                group, chain);
 
-      ref_group (group);
 #ifdef USE_COTHREADS
       schedule_group (group);
 #else
       osched->recursion = 0;
-      osched->runqueue = g_list_append (osched->runqueue, group);
-      gst_opt_scheduler_schedule_run_queue (osched);
+      if (!schedule_group (group)) {
+        g_warning  ("error scheduling group %p", group);
+        group_error_handler (group);
+      }
+      else {
+        GST_INFO (GST_CAT_SCHEDULING, "done scheduling %p", group);
+      }
 #endif
 
       GST_INFO (GST_CAT_SCHEDULING, "done scheduling group %p in chain %p", 
@@ -798,6 +827,8 @@ schedule_chain (GstOptSchedulerChain *chain)
       unref_group (group);
       break;
     }
+
+    groups = g_slist_next (groups);
   }
 }
 
@@ -906,6 +937,7 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstBuffer *buffer)
 #else
   GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), buffer);
   if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) {
+    ref_group (group);
     osched->runqueue = g_list_append (osched->runqueue, group);
   }
 #endif
@@ -938,9 +970,11 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
     schedule_group (group);
 #else
     if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) {
-      ref_group (group);
+      ref_group_by_count (group, 2);
       osched->runqueue = g_list_append (osched->runqueue, group);
+      GST_INFO (GST_CAT_SCHEDULING, "recursing into scheduler group %p", group);
       gst_opt_scheduler_schedule_run_queue (osched);
+      GST_INFO (GST_CAT_SCHEDULING, "return from recurse group %p", group);
       group = unref_group (group);
       /* group is gone */
       if (group == NULL) {
@@ -1709,8 +1743,8 @@ gst_opt_scheduler_iterate (GstScheduler *sched)
     chains = osched->chains;
     while (chains) {
       GstOptSchedulerChain *chain = (GstOptSchedulerChain *) chains->data;
-      chains = g_slist_next (chains);
 
+      ref_chain (chain);
       /* if the chain is not disabled, schedule it */
       if (!GST_OPT_SCHEDULER_CHAIN_IS_DISABLED (chain)) {
         schedule_chain (chain);
@@ -1722,6 +1756,11 @@ gst_opt_scheduler_iterate (GstScheduler *sched)
         GST_INFO (GST_CAT_SCHEDULING, "scheduler %p is in error", sched);
         break;
       }
+
+      GST_INFO (GST_CAT_SCHEDULING, "iterate scheduled %p", chain);
+
+      chains = g_slist_next (chains);
+      unref_chain (chain);
     }
 
     /* at this point it's possible that the scheduler state is