From f1fa0535d79f31fdbaeb3dc12b1edc7928daa8b1 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Thu, 27 Feb 2014 11:53:22 -0500 Subject: [PATCH] Fix: dynamically fetch the session daemon port When connecting to the session daemon, fetch the port at each try. This moves the read port file functions to the TCP session daemon client where the connect happens. If the port file is not found, simply retry 3 seconds later. Also, this adds a timeout to the acquire semaphore of 3 seconds. Signed-off-by: Mathieu Desnoyers Signed-off-by: David Goulet --- .../org/lttng/ust/jul/LTTngAgent.java | 64 ++++----------- .../lttng/ust/jul/LTTngTCPSessiondClient.java | 81 +++++++++++++++++-- .../org/lttng/ust/jul/LTTngThread.java | 5 +- 3 files changed, 91 insertions(+), 59 deletions(-) diff --git a/liblttng-ust-jul/org/lttng/ust/jul/LTTngAgent.java b/liblttng-ust-jul/org/lttng/ust/jul/LTTngAgent.java index 72e60d23..2485be2d 100644 --- a/liblttng-ust-jul/org/lttng/ust/jul/LTTngAgent.java +++ b/liblttng-ust-jul/org/lttng/ust/jul/LTTngAgent.java @@ -18,11 +18,11 @@ package org.lttng.ust.jul; import java.io.IOException; -import java.io.FileNotFoundException; import java.io.InputStream; import java.io.BufferedReader; import java.io.FileReader; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.logging.FileHandler; import java.util.logging.Handler; import java.util.logging.Level; @@ -48,12 +48,13 @@ public class LTTngAgent { private static boolean initialized = false; private static Semaphore registerSem; + private final static int semTimeout = 3; /* Seconds */ + /* + * Default value to connect to session daemon. Port number is dynamically + * fetched from the port file that is created by a running session daemon. + */ private static final String sessiondAddr = "127.0.0.1"; - private static final int sessiondPort = 5345; - - private static final String rootPortFile = "/var/run/lttng/jul.port"; - private static final String userPortFile = "/.lttng/jul.port"; /* * Constructor is private. This is a singleton and a reference should be @@ -100,29 +101,6 @@ public class LTTngAgent { return uid; } - private String getHomePath() { - return System.getProperty("user.home"); - } - - private int getPortFromFile(String path) throws IOException { - int port; - BufferedReader br; - - try { - br = new BufferedReader(new FileReader(path)); - String line = br.readLine(); - port = Integer.parseInt(line, 10); - if (port < 0 || port > 65535) { - port = sessiondPort; - } - br.close(); - } catch (FileNotFoundException e) { - port = sessiondPort; - } - - return port; - } - /* * Public getter to acquire a reference to this singleton object. */ @@ -140,42 +118,32 @@ public class LTTngAgent { * returned by the logManager. */ private synchronized void init() throws SecurityException, IOException { - int user_port, root_port; int nr_acquires = 0; if (this.initialized) { return; } - root_port = getPortFromFile(rootPortFile); - if (getUID() == 0) { - user_port = root_port; - } else { - user_port = getPortFromFile(getHomePath() + userPortFile); - } - /* Handle user session daemon if any. */ - this.lttngThreadUser = new LTTngThread(this.sessiondAddr, user_port, + this.lttngThreadUser = new LTTngThread(this.sessiondAddr, this.lttngHandlerUser, this.registerSem); this.sessiondThUser = new Thread(lttngThreadUser); this.sessiondThUser.start(); /* Wait for registration done of per-user sessiond */ nr_acquires++; - /* Having two different ports, we have to try both. */ - if (root_port != user_port) { - /* Handle root session daemon. */ - this.lttngThreadRoot = new LTTngThread(this.sessiondAddr, - root_port, this.lttngHandlerRoot, this.registerSem); - this.sessiondThRoot = new Thread(lttngThreadRoot); - this.sessiondThRoot.start(); - /* Wait for registration done of system-wide sessiond */ - nr_acquires++; - } + /* Handle root session daemon. */ + this.lttngThreadRoot = new LTTngThread(this.sessiondAddr, + this.lttngHandlerRoot, this.registerSem); + this.sessiondThRoot = new Thread(lttngThreadRoot); + this.sessiondThRoot.start(); + /* Wait for registration done of system-wide sessiond */ + nr_acquires++; /* Wait for each registration to end. */ try { - this.registerSem.acquire(nr_acquires); + this.registerSem.tryAcquire(nr_acquires, semTimeout, + TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java b/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java index 21c228f0..594e735a 100644 --- a/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java +++ b/liblttng-ust-jul/org/lttng/ust/jul/LTTngTCPSessiondClient.java @@ -23,9 +23,12 @@ import java.nio.ByteOrder; import java.lang.Integer; import java.io.IOException; import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.DataInputStream; +import java.io.FileReader; +import java.io.FileNotFoundException; import java.net.*; import java.lang.management.ManagementFactory; import java.util.ArrayList; @@ -49,7 +52,6 @@ public class LTTngTCPSessiondClient { new LTTngSessiondCmd2_4.sessiond_hdr(); private final String sessiondHost; - private final int sessiondPort; private Socket sessiondSock; private boolean quit = false; @@ -71,9 +73,14 @@ public class LTTngTCPSessiondClient { private final static long timerDelay = 5 * 1000; private static boolean timerInitialized; - public LTTngTCPSessiondClient(String host, int port, Semaphore sem) { + private static final String rootPortFile = "/var/run/lttng/jul.port"; + private static final String userPortFile = "/.lttng/jul.port"; + + /* Indicate if we've already release the semaphore. */ + private boolean sem_posted = false; + + public LTTngTCPSessiondClient(String host, Semaphore sem) { this.sessiondHost = host; - this.sessiondPort = port; this.registerSem = sem; this.eventTimer = new Timer(); this.timerInitialized = false; @@ -168,6 +175,18 @@ public class LTTngTCPSessiondClient { this.timerInitialized = true; } + /* + * Try to release the registerSem if it's not already done. + */ + private void tryReleaseSem() + { + /* Release semaphore so we unblock the agent. */ + if (!this.sem_posted) { + this.registerSem.release(); + this.sem_posted = true; + } + } + public void init(LTTngLogHandler handler) throws InterruptedException { this.handler = handler; @@ -198,13 +217,13 @@ public class LTTngTCPSessiondClient { */ handleSessiondCmd(); } catch (UnknownHostException uhe) { - this.registerSem.release(); + tryReleaseSem(); System.out.println(uhe); } catch (IOException ioe) { - this.registerSem.release(); + tryReleaseSem(); Thread.sleep(3000); } catch (Exception e) { - this.registerSem.release(); + tryReleaseSem(); e.printStackTrace(); } } @@ -279,7 +298,7 @@ public class LTTngTCPSessiondClient { * Release semaphore so meaning registration is done and we * can proceed to continue tracing. */ - this.registerSem.release(); + tryReleaseSem(); /* * We don't send any reply to the registration done command. * This just marks the end of the initial session setup. @@ -346,8 +365,54 @@ public class LTTngTCPSessiondClient { } } + private String getHomePath() { + return System.getProperty("user.home"); + } + + /** + * Read port number from file created by the session daemon. + * + * @return port value if found else 0. + */ + private int getPortFromFile(String path) throws IOException { + int port; + BufferedReader br; + + try { + br = new BufferedReader(new FileReader(path)); + String line = br.readLine(); + port = Integer.parseInt(line, 10); + if (port < 0 || port > 65535) { + /* Invalid value. Ignore. */ + port = 0; + } + br.close(); + } catch (FileNotFoundException e) { + /* No port available. */ + port = 0; + } + + return port; + } + private void connectToSessiond() throws Exception { - this.sessiondSock = new Socket(this.sessiondHost, this.sessiondPort); + int port; + + if (this.handler.is_root == 1) { + port = getPortFromFile(rootPortFile); + if (port == 0) { + /* No session daemon available. Stop and retry later. */ + throw new IOException(); + } + } else { + port = getPortFromFile(getHomePath() + userPortFile); + if (port == 0) { + /* No session daemon available. Stop and retry later. */ + throw new IOException(); + } + } + + this.sessiondSock = new Socket(this.sessiondHost, port); this.inFromSessiond = new DataInputStream( sessiondSock.getInputStream()); this.outToSessiond = new DataOutputStream( diff --git a/liblttng-ust-jul/org/lttng/ust/jul/LTTngThread.java b/liblttng-ust-jul/org/lttng/ust/jul/LTTngThread.java index a64c6a9b..b3aa0e6e 100644 --- a/liblttng-ust-jul/org/lttng/ust/jul/LTTngThread.java +++ b/liblttng-ust-jul/org/lttng/ust/jul/LTTngThread.java @@ -23,11 +23,10 @@ public class LTTngThread implements Runnable { private LTTngLogHandler handler; private LTTngTCPSessiondClient sessiondClient; - public LTTngThread(String host, int port, LTTngLogHandler handler, + public LTTngThread(String host, LTTngLogHandler handler, Semaphore registerSem) { this.handler = handler; - this.sessiondClient = new LTTngTCPSessiondClient(host, port, - registerSem); + this.sessiondClient = new LTTngTCPSessiondClient(host, registerSem); } @Override -- 2.34.1