Summary: | Shows phone clienttype when the remote user is logged in with both a phone and a pc | ||
---|---|---|---|
Product: | Telepathy | Reporter: | Sjoerd Simons <sjoerd> |
Component: | gabble | Assignee: | Telepathy bugs list <telepathy-bugs> |
Status: | RESOLVED FIXED | QA Contact: | Telepathy bugs list <telepathy-bugs> |
Severity: | normal | ||
Priority: | medium | Keywords: | patch |
Version: | git master | ||
Hardware: | Other | ||
OS: | All | ||
URL: | http://cgit.collabora.co.uk/git/user/wjt/telepathy-gabble-wjt.git/log/?h=client-types | ||
Whiteboard: | |||
i915 platform: | i915 features: |
Description
Sjoerd Simons
2010-12-06 08:48:33 UTC
This shouldn't happen. I just had a little look at the client-types.py test and it appears to be testing exactly what you're describing. Could you take a look at it and let me know what that's missing or something like that? Cheers. Quite a few big changes here. I've added another test for this bug too. - for (l = waiters; l != NULL; l = l->next) + for (l = waiter_list; l != NULL; l = l->next) { - DiscoWaiter *w = l->data; + GList *j; - if (w != NULL && w->handle == handle && !tp_strdiff (w->resource, resource)) + for (j = l->data; j != NULL; j = j->next) { - out = TRUE; - break; + DiscoWaiter *w = j->data; + + if (w != NULL && w->handle == handle && !tp_strdiff (w->resource, resource)) + { + out = TRUE; + break; + } } } Your 'break' only jumps out of the inner loop, not out of the outer one. This code is still functionally correct, but wasteful. You could either use a goto, or (and I would prefer this) you could include '!out' in both loops' condition. (Also I would slightly like a better name than 'out'.) + signals[CLIENT_TYPES_UPDATED] = g_signal_new ( + "client-types-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, TP_TYPE_HANDLE); Shouldn't this signal include the list/bitfield of client types? + if (best == NULL) + best = r; /* trump existing status & message if it's more present * or has the same presence and a more recent last activity * or has the same presence and a higher priority */ - if (r->status > presence->status || - (r->status == presence->status && r->last_activity > activity) || - (r->status == presence->status && r->priority > prio)) + if (r->status > best->status || + (r->status == best->status && r->last_activity > activity) || + (r->status == best->status && r->priority > prio) || + (r->client_type & GABBLE_CLIENT_TYPE_PC + && !(best->client_type & GABBLE_CLIENT_TYPE_PC))) The second if block should be else if, because it's a no-op if r == best. - if (client_types != NULL) - { - g_ptr_array_unref (client_types); - _signal_presences_updated (cache, handle); - } + if (out_types != NULL) + *out_types = client_types; So yeah, I think this means you're leaking client_types if out_types != NULL. I generally am not overly confident about the GPtrArray refcounting in cf067b1. + /* Do this in an idle because the presence cache can make disco + * requests after dealing with the incoming presence stanza, so we + * can reach this point before the disco request has been made and + * disco_in_progress will return FALSE and we will signal with no + * client types which is a bit annoying. If we do this bit in an + * idle then the disco request will have been made by the time the + * idle source function is actually called. */ Eww. You should take a ref on at least the connection, if not the cache too. I really don't like this though. + if (array != empty_array) + g_ptr_array_unref (array); This is silly. gabble_presence_get_client_types_array() should return a ref to a GPtrArray and then the cleanup path can be the same either way. Or, gabble_presence_get_client_types_array() could be guaranteed to return non-NULL. I know this is existing code, but. Well, I took over this branch, fixed most of my review comments, found and fixed some bugs, and did some cleanup. (In reply to comment #3) > - for (l = waiters; l != NULL; l = l->next) > + for (l = waiter_list; l != NULL; l = l->next) > { > - DiscoWaiter *w = l->data; > + GList *j; > > - if (w != NULL && w->handle == handle && !tp_strdiff (w->resource, > resource)) > + for (j = l->data; j != NULL; j = j->next) > { > - out = TRUE; > - break; > + DiscoWaiter *w = j->data; > + > + if (w != NULL && w->handle == handle && !tp_strdiff (w->resource, > resource)) > + { > + out = TRUE; > + break; > + } > } > } > > Your 'break' only jumps out of the inner loop, not out of the outer one. This > code is still functionally correct, but wasteful. You could either use a goto, > or (and I would prefer this) you could include '!out' in both loops' condition. > (Also I would slightly like a better name than 'out'.) Fixed in my branch. > + signals[CLIENT_TYPES_UPDATED] = g_signal_new ( > + "client-types-updated", > + G_TYPE_FROM_CLASS (klass), > + G_SIGNAL_RUN_LAST, > + 0, > + NULL, NULL, > + g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, TP_TYPE_HANDLE); > > Shouldn't this signal include the list/bitfield of client types? It turned out not to be very useful to include the client types, due mainly to the idle hack. > > + if (best == NULL) > + best = r; > > /* trump existing status & message if it's more present > * or has the same presence and a more recent last activity > * or has the same presence and a higher priority */ > - if (r->status > presence->status || > - (r->status == presence->status && r->last_activity > activity) || > - (r->status == presence->status && r->priority > prio)) > + if (r->status > best->status || > + (r->status == best->status && r->last_activity > activity) || > + (r->status == best->status && r->priority > prio) || > + (r->client_type & GABBLE_CLIENT_TYPE_PC > + && !(best->client_type & GABBLE_CLIENT_TYPE_PC))) > > The second if block should be else if, because it's a no-op if r == best. This actually wasn't true, but I refactored this code to make it more (obviously) right. > > > - if (client_types != NULL) > - { > - g_ptr_array_unref (client_types); > - _signal_presences_updated (cache, handle); > - } > + if (out_types != NULL) > + *out_types = client_types; > > So yeah, I think this means you're leaking client_types if out_types != NULL. I > generally am not overly confident about the GPtrArray refcounting in cf067b1. I refactored this all to make the GPtrArrays an implementation detail of gabble_presence_get_client_types_array(). > > + /* Do this in an idle because the presence cache can make disco > + * requests after dealing with the incoming presence stanza, so we > + * can reach this point before the disco request has been made and > + * disco_in_progress will return FALSE and we will signal with no > + * client types which is a bit annoying. If we do this bit in an > + * idle then the disco request will have been made by the time the > + * idle source function is actually called. */ > > Eww. > > You should take a ref on at least the connection, if not the cache too. I > really don't like this though. I weak-reffed the connection, and improved this comment to explain why it's so difficult to fix things so this idle is not necessary. > > + if (array != empty_array) > + g_ptr_array_unref (array); > > This is silly. gabble_presence_get_client_types_array() should return a ref to > a GPtrArray and then the cleanup path can be the same either way. Or, > gabble_presence_get_client_types_array() could be guaranteed to return > non-NULL. I did the latter. + gchar ***types) ************************** - *types = empty_array; + *types = g_strdupv (empty); Not your code, but perhaps you should check whether types != NULL before setting *types Seems alright otherwise. I pushed a patch to add a g_return_val_if_fail() check. …and just merged the thing: http://cgit.freedesktop.org/telepathy/telepathy-gabble/commit/ |
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.