From e524fb113703d2d25f18daddcef7888dfb89574b Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Wed, 2 Apr 2003 01:23:58 +0000 Subject: [PATCH] STABLE12-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 (cherry picked from commit 5967b22698c8aeb51131a62c56a2f7fbf1f8e79e) --- src/viced/host.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/viced/host.c b/src/viced/host.c index 9310d2678..6f2985082 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -968,8 +968,8 @@ struct host *h_GetHost_r(tcon) hport = rxr_PortOf(tcon); retry: 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 @@ -1078,28 +1078,37 @@ retry: host = h_Alloc_r(tcon); h_gethostcps_r(host,FT_ApproxTime()); if (!(host->Console&1)) { - if (!identP || !interfValid) { - H_UNLOCK - code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf); - H_LOCK - if ( code == RXGEN_OPCODE ) { - identP = (struct Identity *)malloc(sizeof(struct Identity)); - identP->valid = 0; + int pident = 0; + H_UNLOCK + code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf); + H_LOCK + if ( code == RXGEN_OPCODE ) { + if (!identP) + identP = (struct Identity *)malloc(sizeof(struct Identity)); + else + pident = 1; + 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)); - identP->valid = 1; - identP->uuid = interf.uuid; + else + pident = 1; + 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))); - } + 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); -- 2.39.5