From 5967b22698c8aeb51131a62c56a2f7fbf1f8e79e Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Wed, 2 Apr 2003 01:22:16 +0000 Subject: [PATCH] h-gethost-r-race-20030401 FIXES 1308 Thanks to Chaskiel Grundman for explaining what was happening: - the connection is old and pre-existing, but has no host structure. - 2 calls come in - the first one enters h_GetHost_r, and h_Lookup_r returns null (but identP is non-null, since rx keeps it around until it gc's the connection) The first thread calls WhoAreYou, which succeeds, it then calls InitCallBackState3 (after H_UNLOCK) note that the host has been inserted into the hashtable - the second thread enters h_GetHost_r, and calls rx_GetSpecific. it then calls h_Lookup_r. h_Lookup_r will block (new host is locked), but eventually returns the new host - InitCallBackState3 returns, and the frees the old identP, replaces it, and unlocks the host. - the first thread returns from h_Lookup_r. boom. the changes: -call rx_GetSpecific after h_Lookup_r returns (and potentially slept) -removes an if wrapping which always is true (since !interfValid is always true) -don't realloc identP if it exists -don't free an old one by calling rx_SetSpecific either --- src/viced/host.c | 69 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/src/viced/host.c b/src/viced/host.c index 7b2f8de..8904910 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -943,8 +943,8 @@ retry: caps.Capabilities_len = 0; code = 0; - identP = (struct Identity *)rx_GetSpecific(tcon, rxcon_ident_key); host = h_Lookup_r(haddr, hport, &held); + identP = (struct Identity *)rx_GetSpecific(tcon, rxcon_ident_key); if (host && !identP && !(host->Console&1)) { /* This is a new connection, and we already have a host * structure for this address. Verify that the identity @@ -1069,39 +1069,50 @@ retry: host = h_Alloc_r(tcon); /* returned held and locked */ h_gethostcps_r(host,FT_ApproxTime()); if (!(host->Console&1)) { - if (!identP || !interfValid) { - H_UNLOCK - code = RXAFSCB_TellMeAboutYourself(host->callback_rxcon, - &interf, &caps); - if ( code == RXGEN_OPCODE ) - code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf); - H_LOCK - if ( code == RXGEN_OPCODE ) { + int pident = 0; + H_UNLOCK + code = RXAFSCB_TellMeAboutYourself(host->callback_rxcon, + &interf, &caps); + if ( code == RXGEN_OPCODE ) + code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf); + H_LOCK + if ( code == RXGEN_OPCODE ) { + if (!identP) identP = (struct Identity *)malloc(sizeof(struct Identity)); - if (!identP) { - ViceLog(0, ("Failed malloc in h_GetHost_r\n")); - assert(0); - } - identP->valid = 0; + else + pident = 1; + + if (!identP) { + ViceLog(0, ("Failed malloc in h_GetHost_r\n")); + assert(0); + } + identP->valid = 0; + if (!pident) rx_SetSpecific(tcon, rxcon_ident_key, identP); - ViceLog(25, - ("Host %s:%d does not support WhoAreYou.\n", - afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); - code = 0; - } else if (code == 0) { - interfValid = 1; + ViceLog(25, + ("Host %s:%d does not support WhoAreYou.\n", + afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port))); + code = 0; + } else if (code == 0) { + if (!identP) identP = (struct Identity *)malloc(sizeof(struct Identity)); - if (!identP) { - ViceLog(0, ("Failed malloc in h_GetHost_r\n")); - assert(0); - } - identP->valid = 1; - identP->uuid = interf.uuid; - rx_SetSpecific(tcon, rxcon_ident_key, identP); - ViceLog(25, ("WhoAreYou success on %s:%d\n", - afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + else + pident = 1; + + if (!identP) { + ViceLog(0, ("Failed malloc in h_GetHost_r\n")); + assert(0); } + identP->valid = 1; + identP->uuid = interf.uuid; + if (!pident) + rx_SetSpecific(tcon, rxcon_ident_key, identP); + ViceLog(25, ("WhoAreYou success on %s:%d\n", + afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port))); } + interfValid=identP->valid; if (code == 0 && !identP->valid) { H_UNLOCK code = RXAFSCB_InitCallBackState(host->callback_rxcon); -- 1.9.4