|
private static final Map<String, UserGroupInformation> userGroupInformationMap = new HashMap<>(); |
|
|
|
private static final ScheduledExecutorService kerberosRenewalService = |
|
ThreadUtils.newSingleDaemonScheduledExecutorService("Hive-Kerberos-Renewal-Thread-"); |
|
|
|
static { |
|
kerberosRenewalService.scheduleWithFixedDelay(() -> { |
|
if (userGroupInformationMap.isEmpty()) { |
|
return; |
|
} |
|
userGroupInformationMap.forEach((key, ugi) -> { |
|
try { |
|
if (ugi.isFromKeytab()) { |
|
ugi.checkTGTAndReloginFromKeytab(); |
|
} |
|
log.info("Relogin from keytab success, user: {}", key); |
|
} catch (Exception e) { |
|
log.error("Relogin from keytab failed, user: {}", key, e); |
|
} |
|
}); |
|
}, 0, 5, TimeUnit.MINUTES); |
|
} |
|
|
|
public synchronized static UserGroupInformation login(String userName) { |
|
UserGroupInformation userGroupInformation = userGroupInformationMap.get(userName); |
|
if (userGroupInformation == null) { |
|
if (!openKerberos()) { |
|
userGroupInformation = createRemoteUser(userName); |
|
} else { |
|
userGroupInformation = createKerberosUser(); |
|
} |
|
userGroupInformationMap.put(userName, userGroupInformation); |
|
} |
|
currentLoginTimesMap.compute(userName, (k, v) -> v == null ? 1 : v + 1); |
|
return userGroupInformation; |
|
} |
|
|
|
public synchronized static void logout(String userName) { |
|
Integer currentLoginTimes = currentLoginTimesMap.get(userName); |
|
if (currentLoginTimes == null) { |
|
return; |
|
} |
|
if (currentLoginTimes <= 1) { |
|
currentLoginTimesMap.remove(userName); |
|
userGroupInformationMap.remove(userName); |
|
} else { |
|
currentLoginTimesMap.put(userName, currentLoginTimes - 1); |
|
} |
|
} |
Search before asking
What happened
dolphinscheduler/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hive/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hive/security/UserGroupInformationFactory.java
Lines 42 to 90 in c9e373e
In UserGroupInformationFactory, login() and logout() are synchronized, but the static initializer schedules a background Kerberos renewal task that reads the same HashMap without synchronization. This will cause ConcurrentModificationException
What you expected to happen
Kerberos renewal thread should safely iterate the map
How to reproduce
Occasional
Anything else
No response
Version
dev
Are you willing to submit PR?
Code of Conduct