Re: [PATCH 1/1] add hog ref before adding to instances

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

 



Hi Scerveau,

On Mon, Apr 20, 2020 at 11:37 AM scerveau <scerveau@xxxxxxxxxxxxx> wrote:
>
> Dear Luiz,
>
> Thanks but see my comment below.
>
> On 20/4/20 19:21, Luiz Augusto von Dentz wrote:
> > Hi Stéphane,
> >
> > On Mon, Apr 20, 2020 at 9:39 AM Stéphane Cerveau <scerveau@xxxxxxxxxxxxx> wrote:
> >>
> >> To avoid a double hog free, need to add a ref
> >> when adding the hog to the slist.
> >>
> >> This bug has been reproduced with gamepad-8718
> >> which was connecting/disconnecting frantically.
> >>
> >> Fix also a typo in the method hog_attach_instance
> >> ---
> >>   profiles/input/hog-lib.c | 8 ++++----
> >>   1 file changed, 4 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
> >> index 9c5c814a7..b9b5d565c 100644
> >> --- a/profiles/input/hog-lib.c
> >> +++ b/profiles/input/hog-lib.c
> >> @@ -1357,7 +1357,7 @@ static struct bt_hog *hog_new(int fd, const char *name, uint16_t vendor,
> >>          return hog;
> >>   }
> >>
> >> -static void hog_attach_instace(struct bt_hog *hog,
> >> +static void hog_attach_instance(struct bt_hog *hog,
> >>                                  struct gatt_db_attribute *attr)
> >>   {
> >>          struct bt_hog *instance;
> >> @@ -1373,14 +1373,14 @@ static void hog_attach_instace(struct bt_hog *hog,
> >>          if (!instance)
> >>                  return;
> >>
> >> -       hog->instances = g_slist_append(hog->instances, instance);
> >> +       hog->instances = g_slist_append(hog->instances, bt_hog_ref(instance));
> >
> > That sounds like like a double ref since bt_hog_new already does add a
>
> Yes but in `hog_attach_instance`, `hog_new` is used and not `bt_hog_new`
> which is indeed reffing. So I dont think there is double ref in this method.

Yep, you are rigth it is not adding a reference, but that seems on
purpose since on it doesn't use bt_hog_unref:

g_slist_free_full(hog->instances, hog_free);

> Unfortunately when I was preparing the patch, I noticed that another
> instance was added to slist and here you are totally right there is a
> double reference. I will remove this from the initial patch.

Right, I see now that is really missing the ref because
destroy_gatt_req does actually unref its own reference but since we
use hog_new that would destroy the instance so adding the ref should
be the right way to fix this.

>
>
> > reference, so chances are that you may be fixing the the symptom not
> > the real problem which seems that we cannot unref the instances
> > because they are not removed from the parent as it they should, in
> > fact we might need to redesign it a little bit since bt_hog might
> > actually be inefficient when there are multiple instances as it does
> > allocate a new uhid instance of each of then so we might do something
> > like:
> >
> > struct bt_hog_instance {
> >      struct bt_hog *parent;
> >      struct gatt_db_attribute *attr;
> >      struct gatt_primary *primary;
> >      GAttrib *attrib;
> >      GSList *reports;
> >      gboolean has_report_id;
> >      uint16_t bcdhid;
> >      uint8_t bcountrycode;
> >      uint16_t proto_mode_handle;
> >      uint16_t ctrlpt_handle;
> >      uint8_t flags;
> >      unsigned int getrep_att;
> >      uint16_t getrep_id;
> >      unsigned int setrep_att;
> >      uint16_t setrep_id;
> > }
> >
> > That way the instances are indenpendent of the bt_hog which should be
> > 1:1 to a device, while we can have multple instances of
> > bt_hog_instance, if you don't have time to do the rework then lets
> > just add a parent pointer added to bt_hog so we can can remove child
> > instances and resolve the double free.
> >
> >>   }
> >>
> >>   static void foreach_hog_service(struct gatt_db_attribute *attr, void *user_data)
> >>   {
> >>          struct bt_hog *hog = user_data;
> >>
> >> -       hog_attach_instace(hog, attr);
> >> +       hog_attach_instance(hog, attr);
> >>   }
> >>
> >>   static void dis_notify(uint8_t source, uint16_t vendor, uint16_t product,
> >> @@ -1528,7 +1528,7 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
> >>                          primary->range.end, find_included_cb, instance);
> >>
> >>          bt_hog_attach(instance, hog->attrib);
> >> -       hog->instances = g_slist_append(hog->instances, instance);
> >> +       hog->instances = g_slist_append(hog->instances, bt_hog_ref(instance));
> >>   }
> >>
> >>   static void primary_cb(uint8_t status, GSList *services, void *user_data)
> >> --
> >> 2.17.1
> >>
> >
> >



-- 
Luiz Augusto von Dentz




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux