1

I have an app that communicates through USB with an external device. It works in the background and periodically checks if the device is connected to USB and starts reading data from it. When the device is connected, the app in addition shows a window to the user. The app is installed per user and launches when the user logs in. The app is written in C++ using QT and works on Windows and Mac OS X.

The problem is that if 2 users have the app installed and are logged in in the same time (by the "switch user" feature for example), there are 2 instances of the app running and both of them will start communicating with the device, which causes data corruption.

I'd like to implement a check that prevents the app from starting the communication if the owner of the process isn't currently active. Then only the instance started by the active user will be communicating with the device (this assumes only one user can be active, but it's fine for personal computers). Ideally, I'd be very happy to see a QT based solution that works on both Windows and OS X, but platform specific solution will also be fine.

I was wondering if a solution that activates the app's window and the checks if the window is active after that will work.

Best regards, Michal

Michał Fronczyk
  • 1,859
  • 4
  • 24
  • 29
  • You may think of separating the GUI and the device-communicating aspects into separate processes, the latter being a system service. You may look into the [qtservice](https://qt.gitorious.org/qt-solutions/qt-solutions/source/fd22bee22274975c56f1c10d87ee9fd2c0818f83:qtservice) solution. – Kuba hasn't forgotten Monica May 21 '14 at 13:45

2 Answers2

0

you can use QSystemSemaphore to synchronize access to the USB device.

Otherwise you can combine this with QSharedMemory to coordinate access more precisely.

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • QSharedMemory seems not to work across different user accounts - http://www.qtcentre.org/threads/19205-QSharedMemory-in-processes-from-different-accounts and https://bugreports.qt-project.org/browse/QTBUG-9446 – Michał Fronczyk May 21 '14 at 12:11
  • @MichałFronczyk for the IOS issue you can use a native key that resolves to the proper shared memory – ratchet freak May 21 '14 at 12:18
  • OK, I'll check that if there won't be any other solutions. This will prevent the apps from communicating with the device at the same time, but still both apps will process the data and show the window, and I'd like only one of them to do that ideally. – Michał Fronczyk May 21 '14 at 12:25
0

Although there exists a function QGuiApplication::sessionId(), on OSX, it returns an empty string.

There's a guide in the OSX docs about how to handle Multiuser sessions.

What you need is the current session id. When the user logs in and your application starts, retrieve the current session ID and store it in the app. Here's how you can get that session id: -

#include <security/AuthSession.h>

unsigned int GetSessionId() const
{
    OSStatus error;
    SecuritySessionId mySession;
    SessionAttributeBits sessionInfo;

    error = SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);

    if(error != errSessionSuccess)
    {
        qDebug() << "Error retrieving session info");
        return 0;
    }

    return mySession;
}

You will need to include the Security Framework in your project file (.pro): -

LIBS += -framework Security

So, when the app needs to communicate with the USB device, retrieve the stored session Id and compare it with the current one, once again calling GetSessionId. If they are not equal, then the app is not running from the current logged-in session and you can skip the read, allowing the other app instance to continue.

Assuming QGuiApplication::sessionId() works as expected in Windows, you may be able to use that.

TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85