[jitsi-dev] Jitsi System Tray not initialized on Ubuntu 12.04


#1

Hello,

I've encountered an issue on Ubuntu 12.04 LTS that is Jitsi tray icon not
showing up. Message I get is "Systray not init" on normal log level.

The reason for that is the GUI service starting after the
OsDependentActivator was started. In SystrayServiceJdicImpl there's only
one ocassion to initialize system tray when calling the constructor.
Probably this shouldn't happen as osdependent.jar activator is started
on felix.auto.start.66, while GUI service is started on felix.auto.start.45
run level, but I'm not an expert on felix.

One solution could be to try to initialize Systray again in
checkInitialized() of SystrayServiceJdicImpl, but some thread
synchronization must be added as I've noticed few trays to get initialized
with trivial approach.

Below is the log fragment, but I'm attaching full log also. These upper
case messages are added by me to find out why this had happend.

09:20:26.238 INFO:
impl.osdependent.jdic.SystrayServiceJdicImpl.<init>().136 CREATE SYSTRAY
09:20:26.246 INFO:
impl.osdependent.jdic.SystrayServiceJdicImpl.<init>().138 CREATE SYSTRAY -
FINISHED
09:20:26.247 INFO:
impl.osdependent.jdic.SystrayServiceJdicImpl.<init>().147 INIT SYSTRAY
09:20:26.249 INFO:
impl.osdependent.jdic.SystrayServiceJdicImpl.initSystray().163 INIT SYSTRAY
CANCEL-GUI NULL
09:20:26.250 INFO: impl.osdependent.OsDependentActivator.start().76 Systray
Service...[ STARTED ]
09:20:26.253 INFO: impl.osdependent.OsDependentActivator.start().84 Systray
Service ...[REGISTERED]
09:20:26.265 INFO: impl.osdependent.OsDependentActivator.start().90 Desktop
Service...[ STARTED ]
09:20:26.267 INFO: impl.osdependent.OsDependentActivator.start().98 Desktop
Service ...[REGISTERED]
09:20:26.281 INFO: impl.gui.GuiActivator.start().127 GlobalStatus Service
...[REGISTERED]
09:20:26.414 WARNING: impl.protocol.sip.SipLogger.logWarning().174 Warning
from the JAIN-SIP stackusing default tls security policy
09:20:26.422 INFO: impl.protocol.sip.SipLogger.logInfo().185 Info from the
JAIN-SIP stack: the sip stack timer
gov.nist.javax.sip.stack.timers.DefaultSipTimer has been started
09:20:27.138 INFO: impl.gui.GuiActivator.start().138 UI Service...[
STARTED ]
09:20:27.139 WARNING:
impl.resources.ResourceManagementServiceImpl.getSettingsInt().754 Missing
resource for key: net.java.sip.communicator.SIP_PREFERRED_CLEAR_PORT
09:20:27.153 WARNING:
impl.resources.ResourceManagementServiceImpl.getSettingsInt().754 Missing
resource for key: net.java.sip.communicator.SIP_PREFERRED_SECURE_PORT
09:20:27.153 SEVERE:
impl.osdependent.jdic.SystrayServiceJdicImpl.checkInitialized().515 Systray
not init
09:20:27.177 INFO: impl.gui.GuiActivator.start().144 UI Service
...[REGISTERED]
09:20:27.180 SEVERE:
impl.osdependent.jdic.SystrayServiceJdicImpl.checkInitialized().515 Systray
not init

Regards,
Paweł Domas

jitsi0.log.0 (25.4 KB)


#2

Hello Paweł,

I've encountered an issue on Ubuntu 12.04 LTS that is Jitsi tray icon not showing up. Message I get is "Systray not init" on normal log level.

I've seen the missing Jitsi tray icon on Ubuntu 12.04 as well.

The reason for that is the GUI service starting after the OsDependentActivator was started. In SystrayServiceJdicImpl there's only one ocassion to initialize system tray when calling the constructor. Probably this shouldn't happen as osdependent.jar activator is started on felix.auto.start.66, while GUI service is started on felix.auto.start.45 run level, but I'm not an expert on felix.

The ui-service.jar bundle being started at felix.auto.start.45 is not the UIService implementation. The osdependent.jar bundle being started at felix.auto.start.66 and the SystrayServiceJdicImpl#initSystray() method want the swing-ui.jar bundle being started at felix.auto.start.66 as well.

I couldn't find documentation guaranteeing that the order of the bundles within the same level specified in felix.client.run.properties is guaranteed to be respected. For what it's worth, the OSGi specification seems to me to neither require a specific order not prohibit the use of multiple Threads (which Felix does not use anyway).

One solution could be to try to initialize Systray again in checkInitialized() of SystrayServiceJdicImpl, but some thread synchronization must be added as I've noticed few trays to get initialized with trivial approach.

What you propose could be possible. I just do not understand how you justify a second try at #initService() upon #checkInitialized().

Another approach could be separating swing-ui.jar and osdependent.jar at different levels. Which could turn out hard, however, given that each of their respective service implementations requires the other.

It should also be possible to modify SystrayServiceJdicImpl to delay the invocation of #initService() until the UIService implementation instance becomes available in the BundleContext. Of course, SystrayServiceJdicImpl might have to make sure that the SystrayService methods are capable of functioning prior to the call to #initService() as well (which could be tricky but does not seem insurmountable to me at a first glance).

Anyway, the above are just ideas so we could wait for the other developers to give them a chance to express their opinions.

Regards,
Lyubomir Marinov

···

On 19.07.2012, at 10:37, Paweł Domas wrote:


#3

Hey folks,

The reason for that is the GUI service starting after the
OsDependentActivator was started. In SystrayServiceJdicImpl there's
only one ocassion to initialize system tray when calling the
constructor. Probably this shouldn't happen as osdependent.jar
activator is started on felix.auto.start.66, while GUI service is
started on felix.auto.start.45 run level, but I'm not an expert on
felix.

The ui-service.jar bundle being started at felix.auto.start.45 is not
the UIService implementation. The osdependent.jar bundle being
started at felix.auto.start.66 and the
SystrayServiceJdicImpl#initSystray() method want the swing-ui.jar
bundle being started at felix.auto.start.66 as well.

I suppose that's a problem though, it's easily resolved. We only need to
make sure that the systray implementation would implement an OSGi
listener that would retry initialization once the UI service
implementation is registered. (Lyubo, I just saw you are proposing the
same below).

I couldn't find documentation guaranteeing that the order of the
bundles within the same level specified in
felix.client.run.properties is guaranteed to be respected.

It is not guaranteed indeed but that's what should happen given how we
use it in Jitsi. Of course we shouldn't count on it.

One solution could be to try to initialize Systray again in
checkInitialized() of SystrayServiceJdicImpl, but some thread
synchronization must be added as I've noticed few trays to get
initialized with trivial approach.

Before we move to the solutions, Pawel, could you please state exactly
what the problem is? Where does the whole thing fail? Is there a null
reference somwhere? Where does the code fail exactly?

Emil

···

On 19.07.12 11:01, Lyubomir Marinov wrote:


#4

Before we move to the solutions, Pawel, could you please state exactly
what the problem is? Where does the whole thing fail? Is there a null
reference somwhere? Where does the code fail exactly?

It's in initSystray() method of class SystrayServiceJdicImpl. There's a
check at the beginning of the method:

if(OsDependentActivator.getUIService() == null)
        {
            return;
        }

If it would stay that way there should be at least some log info about that.

Regards, Paweł Domas


#5

Hello,

I'm sending a patch which solves this issue. At the moment when tray tries
to initialize and there's no UIService available it registers a listener
which waits for it. When it's available that listener initializes the tray
and unregisters from service listeners once had finished his job.

Regards, Pawel Domas

systrayIssuePatch.patch (2.23 KB)


#6

Hello,

···

2012/7/19 Paweł Domas <paweldomas@gmail.com>

Hello,

I'm sending a patch which solves this issue. At the moment when tray tries
to initialize and there's no UIService available it registers a listener
which waits for it. When it's available that listener initializes the tray
and unregisters from service listeners once had finished his job.

Any feedback about that ? Is this ok ?

Regards, Paweł Domas


#7

Paweł, thank you very much for the contribution! We committed it in r9754 and acknowledged it at https://jitsi.org/index.php/Development/TeamAndContributors.

···

On Jul 19, 2012, at 9:03 PM, Paweł Domas wrote:

I'm sending a patch which solves this issue. At the moment when tray tries to initialize and there's no UIService available it registers a listener which waits for it. When it's available that listener initializes the tray and unregisters from service listeners once had finished his job.


#8

Hello Paweł,

Thank you very much for the patch! It looks promising and we will eventually integrate it in trunk.

We'd like to ask you though for a bit of clarification on the following code:

    public SystrayServiceJdicImpl()
    {
        try
        {
            systray = SystemTray.getDefaultSystemTray();
        } catch (Throwable e)
        {
            if(!GraphicsEnvironment.isHeadless())
                logger.error("Failed to create a systray!", e);
        }

        if (systray != null)
        {
            this.initSystray();

            UIService ui = OsDependentActivator.getUIService();
            if (ui != null)
                ui.setExitOnMainWindowClose(false);
        }
    }

In your patch, the #initSystray() will be re-run itself when the UIService implementation becomes available. However, in the SystrayServiceJdicImpl contractor seen above, there is yet another check with respect to the availability of the UIService implementation and UIService#setExitOnMainWindowClose(boolean) is called. Shouldn't we re-run that code as well when the UIService implementation becomes available?

Regards,
Lyubomir Marinov

···

On 20.07.2012, at 11:37, Paweł Domas wrote:

I'm sending a patch which solves this issue. At the moment when tray tries to initialize and there's no UIService available it registers a listener which waits for it. When it's available that listener initializes the tray and unregisters from service listeners once had finished his job.

Any feedback about that ? Is this ok ?


#9

Hi,

Thanks for response ! :slight_smile:

···

2012/7/20 Lyubomir Marinov <lubo@jitsi.org>

We'd like to ask you though for a bit of clarification on the following
code:

    public SystrayServiceJdicImpl()
    {
        try
        {
            systray = SystemTray.getDefaultSystemTray();
        } catch (Throwable e)
        {
            if(!GraphicsEnvironment.isHeadless())
                logger.error("Failed to create a systray!", e);
        }

        if (systray != null)
        {
            this.initSystray();

            UIService ui = OsDependentActivator.getUIService();
            if (ui != null)
                ui.setExitOnMainWindowClose(false);
        }
    }

In your patch, the #initSystray() will be re-run itself when the UIService
implementation becomes available. However, in the SystrayServiceJdicImpl
contractor seen above, there is yet another check with respect to the
availability of the UIService implementation and
UIService#setExitOnMainWindowClose(boolean) is called. Shouldn't we re-run
that code as well when the UIService implementation becomes available?

Yes, I didn't noticed that. As I understand this disables jitsi shutdown
when main window is closed(it is minimized then). So it is logically linked
to situation when we have the tray initialized. Will it be ok if I put this
code at the end of initSystray() method ?

Regards, Paweł Domas