authd: refcounting fixes

This commit is contained in:
Elizabeth Myers 2016-04-06 09:52:25 -05:00
parent 34f65493cd
commit 45e6c74631

View file

@ -166,33 +166,36 @@ cancel_providers(struct auth_client *auth)
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers) RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
{ {
if(provider->cancel && is_provider_running(auth, provider->id)) if(provider->cancel != NULL && is_provider_running(auth, provider->id))
/* Cancel if required */ /* Cancel if required */
provider->cancel(auth); provider->cancel(auth);
} }
auth->refcount = 0;
rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid)); rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid));
rb_free(auth->data); rb_free(auth->data);
rb_free(auth); rb_free(auth);
} }
/* Provider is done - WARNING: do not use auth instance after calling! */ /* Provider is done
* WARNING: do not use auth instance after calling! */
void void
provider_done(struct auth_client *auth, uint32_t id) provider_done(struct auth_client *auth, uint32_t id)
{ {
rb_dictionary_iter iter; rb_dictionary_iter iter;
struct auth_provider *provider; struct auth_provider *provider;
set_provider_done(auth, id); if(auth->refcount == 1 && !auth->providers_starting)
if(!auth->refcount)
{ {
if(!auth->providers_starting) /* Providers aren't being executed and refcount is 1 (last provider), accept */
/* Providers aren't being executed and refcount is 0, accept */ accept_client(auth, id);
accept_client(auth, -1);
return; return;
} }
set_provider_done(auth, id);
/* It's safe to use auth below, since refcount will be > 0, per above
* Thus the object will still be live */
RB_DICTIONARY_FOREACH(provider, &iter, auth_providers) RB_DICTIONARY_FOREACH(provider, &iter, auth_providers)
{ {
if(provider->completed != NULL && is_provider_running(auth, provider->id)) if(provider->completed != NULL && is_provider_running(auth, provider->id))
@ -201,10 +204,12 @@ provider_done(struct auth_client *auth, uint32_t id)
} }
} }
/* Reject a client - WARNING: do not use auth instance after calling! */ /* Reject a client
* WARNING: do not use auth instance after calling! */
void void
reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...) reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...)
{ {
unsigned int refcount = auth->refcount;
char buf[BUFSIZE]; char buf[BUFSIZE];
va_list args; va_list args;
@ -225,16 +230,23 @@ reject_client(struct auth_client *auth, uint32_t id, const char *data, const cha
data, buf); data, buf);
set_provider_done(auth, id); set_provider_done(auth, id);
if(--refcount > 0)
/* We have providers remaining, let them clean up */
cancel_providers(auth); cancel_providers(auth);
} }
/* Accept a client, cancel outstanding providers if any - WARNING: do nto use auth instance after calling! */ /* Accept a client, cancel outstanding providers if any
* WARNING: do not use auth instance after calling! */
void void
accept_client(struct auth_client *auth, uint32_t id) accept_client(struct auth_client *auth, uint32_t id)
{ {
unsigned int refcount = auth->refcount;
rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname);
set_provider_done(auth, id); set_provider_done(auth, id);
if(--refcount > 0)
/* We have providers remaining, let them clean up */
cancel_providers(auth); cancel_providers(auth);
} }