Skip to content

Commit

Permalink
Fix #26 by closing the dbus connection on auto-close
Browse files Browse the repository at this point in the history
  • Loading branch information
swiesend committed Apr 16, 2021
1 parent 60f032c commit c386feb
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 20 deletions.
66 changes: 51 additions & 15 deletions src/main/java/org/freedesktop/secret/simple/SimpleCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static org.freedesktop.secret.Static.DBus.DEFAULT_DELAY_MILLIS;
import static org.freedesktop.secret.Static.DEFAULT_PROMPT_TIMEOUT;

public final class SimpleCollection extends org.freedesktop.secret.simple.interfaces.SimpleCollection {

private static final Logger log = LoggerFactory.getLogger(SimpleCollection.class);
private static boolean testing = false;
private static Lock disconnectLock = new ReentrantLock();
private static DBusConnection connection = getConnection();
private TransportEncryption transport = null;
private Service service = null;
Expand Down Expand Up @@ -144,7 +148,7 @@ private static final DBusConnection getConnection() {
log.warn("Could not communicate properly with the D-Bus: " + e.getMessage() + " (" + e.getClass().getSimpleName() + ")");
}
} finally {
disconnect();
disconnect(false);
}
return null;
}
Expand Down Expand Up @@ -187,24 +191,55 @@ public static boolean isAvailable() {
}
}

static private void disconnect() {
if (connection != null && connection.isConnected()) {
Thread daemonThread = new Thread(() -> {
try {
if (connection != null && connection.isConnected()) {
connection.close();
}
log.debug("Disconnected properly from the D-Bus.");
} catch (IOException | RejectedExecutionException e) {
log.error("Could not disconnect properly from the D-Bus.", e);
/**
* Acquire a lock and close and close the D-Bus connection.
* Waits until the connection is closed.
*/
static private void disconnectSynchronized() {
disconnectLock.lock();
try {
if (connection != null && connection.isConnected()) {
connection.close();
while (connection.isConnected()) {
Thread.sleep(DEFAULT_DELAY_MILLIS);
}
});
daemonThread.setName("secret-service:disconnect");
daemonThread.setDaemon(true);
Runtime.getRuntime().addShutdownHook(daemonThread);
connection = null;
log.debug("Disconnected properly from the D-Bus.");
}
} catch (IOException | RejectedExecutionException | InterruptedException e) {
log.error("Could not disconnect properly from the D-Bus.", e);
} finally {
disconnectLock.unlock();
}
}

/**
* Close the global D-Bus connection.
*
* @param now Either close the connection immediately or set up a shutdown hook.
*/
static private void disconnect(boolean now) {
if (connection != null && connection.isConnected()) {
if (now && !testing) {
disconnectSynchronized();
} else {
Thread daemonThread = new Thread(() -> disconnectSynchronized());
daemonThread.setName("secret-service:disconnect-shutdown");
daemonThread.setDaemon(true);
Runtime.getRuntime().addShutdownHook(daemonThread);
}
}
}

/**
* This is an ugly helper method in order to easily test some private static scope.
*
* @param testing if true then the D-Bus connection will be closed with a shutdown hook otherwise auto-close will close the connection immediately.
*/
public static void setTesting(boolean testing) {
SimpleCollection.testing = testing;
}

private void init() throws IOException {
if (!isAvailable()) throw new IOException("The secret service is not available.");
try {
Expand Down Expand Up @@ -358,6 +393,7 @@ public void close() {
session.close();
log.debug("Closed session properly.");
}
disconnect(true);
}

/**
Expand Down
14 changes: 11 additions & 3 deletions src/test/java/org/freedesktop/secret/simple/Example.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package org.freedesktop.secret.simple;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.*;

import java.io.IOException;
import java.security.AccessControlException;
Expand All @@ -14,6 +12,16 @@

public class Example {

@BeforeAll
public static void startTesting() {
SimpleCollection.setTesting(true);
}

@AfterAll
public static void endTesting() {
SimpleCollection.setTesting(false);
}

@Test
@Disabled
@DisplayName("Create a password in the user's default collection ('/org/freedesktop/secrets/aliases/default').")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.freedesktop.secret.simple;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -16,6 +15,16 @@ public class SimpleCollectionTest {

private static final Logger log = LoggerFactory.getLogger(SimpleCollectionTest.class);

@BeforeAll
public static void startTesting() {
SimpleCollection.setTesting(true);
}

@AfterAll
public static void endTesting() {
SimpleCollection.setTesting(false);
}

@Test
@Disabled("Danger Zone! Be aware that this can lead to the loss of passwords.")
public void deleteDefaultCollection() throws IOException {
Expand Down Expand Up @@ -247,9 +256,12 @@ public void setTimeout() throws IOException {
}

@Test
@Disabled
public void close() throws IOException {
SimpleCollection.setTesting(false);
SimpleCollection collection = new SimpleCollection();
collection.close();
SimpleCollection.setTesting(true);
}

}

0 comments on commit c386feb

Please sign in to comment.