Results 1 to 12 of 12

Thread: QSharedMemory locking-Question

  1. #1
    Join Date
    Jan 2011
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QSharedMemory locking-Question

    Hello guys,

    the locking with the QSharedMemory class behaves very strange with me.

    Let me demonstrate:
    Qt Code:
    1. // T1
    2. #include <QSharedMemory>
    3.  
    4. int main() {
    5. QSharedMemory qs("TEST");
    6. qs.create(10);
    7. qs.attach();
    8.  
    9. qs.lock();
    10. while (1);
    11. }
    12. // T1
    To copy to clipboard, switch view to plain text mode 
    and
    Qt Code:
    1. // T2
    2. #include <QSharedMemory>
    3. #include <iostream>
    4.  
    5. int main() {
    6. QSharedMemory qs("TEST");
    7. qs.create(10);
    8. qs.attach();
    9.  
    10. qs.lock();
    11. std::cout << "Here?\n";
    12. }
    13. // T2
    To copy to clipboard, switch view to plain text mode 

    Now I run T1 first:
    Qt Code:
    1. $ ./t1
    To copy to clipboard, switch view to plain text mode 
    and some seconds later I run T2 and I get:
    Qt Code:
    1. $ ./t2
    2. Here?
    3. QSharedMemory::lock: already locked
    To copy to clipboard, switch view to plain text mode 

    Huh? Here should never be reached, if I read the documentation correctly. How is this possible? I don't understand this behavior and it makes the whole locking function pointless, doesn't it?

    Can anybody help me out?

    Best regards!

  2. #2
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedMemory locking-Question

    Those functions return a bool saying whether or not they were successfull, you might want to check that and call error() if one of them returns false.

    Also, create does an attach for you, and you can't create from two processes with the same key.

  3. #3
    Join Date
    Jun 2007
    Posts
    5
    Thanks
    2

    Default Re: QSharedMemory locking-Question

    Hi all,

    sorry squidge, but your comment or hint saying that "create does an attach for you, and you can't create from two processes with the same key." is not correct.
    A create operation do an attach only if the creation was successful. If not the creation process fails. One reason upon other cases can be that the shared variable already exist.
    In that case you can try to attach to them. So even if the example below is not complete it seems to use the Qt interface as specified by the documentation.
    I have same problem on Linux. Same code works fine in a Windows environment.

    I found a QTBug-1036 https://bugreports.qt.io/browse/QTBUG-10364 but it seems not being handled by Digia.

    So my question here is ... what can I do to work around this issue on a Linux platform?

    Please help.

    Bye
    Kai

  4. #4
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: QSharedMemory locking-Question

    You are still ignoring the return values from QSharedMemory::create and QSharedMemory::attach.

    What are the return values from those calls?

  5. #5
    Join Date
    Jun 2007
    Posts
    5
    Thanks
    2

    Default Re: QSharedMemory locking-Question

    Hi,

    I did a lot of testing today. I can now reproduce the error case in a Linux system.
    Even if I do not undertstand the reason the fix is - as documented in the thread -
    to invert the function calls create and attach.

    Please use the attached code to reproduce both cases
    Usage:
    - Error case undef or comment #define REVERSE
    - working case define or uncomment #define REVERSE
    After compilation launch multiple instances of it and try different scenarios.
    Hope this help!

    Bye
    Kai

    Qt Code:
    1. #include <QSharedMemory>
    2. #include <QDebug>
    3.  
    4.  
    5.  
    6. bool shmCreate( QSharedMemory & qs )
    7. {
    8. qDebug( ) << "About to create shared memory. Press key to execute.";
    9. getchar( );
    10.  
    11. qDebug( ) << "\nShared memory creation in progress...\n";
    12. if( qs.create( 10 ) )
    13. {
    14. qDebug( ) << "Shared memory successfully created.\n";
    15. return true;
    16. }
    17. else
    18. {
    19. qDebug( ) << "Shared memory creation failed.\n";
    20. qDebug( ) << qs.errorString( ) << "\n";
    21. return false;
    22. }
    23. }
    24.  
    25.  
    26.  
    27. bool shmAttach( QSharedMemory & qs )
    28. {
    29. qDebug( ) << "About to attach to shared memory. Press key to execute.";
    30. getchar( );
    31.  
    32. qDebug( ) << "\nAttaching to shared memory...\n";
    33. if( qs.attach( ) )
    34. {
    35. qDebug( ) << "Shared memory successfully attached.\n";
    36. return true;
    37. }
    38. else
    39. {
    40. qDebug( ) << "Attaching to shared memory failed.\n";
    41. qDebug( ) << qs.errorString( ) << "\n";
    42. return false;
    43. }
    44. }
    45.  
    46.  
    47.  
    48. void shmLock( QSharedMemory & qs )
    49. {
    50. qDebug( ) << "About to lock shared memory. Press key to execute.\n";
    51. getchar( );
    52.  
    53. qDebug( ) << "\nLocking shared memory...\n";
    54. if( qs.lock( ) )
    55. {
    56. qDebug( ) << "Shared memory successfully locked.\n";
    57. }
    58. else
    59. {
    60. qDebug( ) << "Locking shared memory failed.\n";
    61. qDebug( ) << qs.errorString( ) << "\n";
    62. }
    63. }
    64.  
    65.  
    66.  
    67. void shmUnlock( QSharedMemory & qs )
    68. {
    69. qDebug( ) << "About to unlock shared memory. Press key to execute.";
    70. getchar( );
    71.  
    72. qDebug( ) << "\nUnocking shared memory...\n";
    73. if( qs.unlock( ) )
    74. {
    75. qDebug( ) << "Shared memory successfully unlocked.\n";
    76. }
    77. else
    78. {
    79. qDebug( ) << "\nUnlocking shared memory failed.\n";
    80. qDebug( ) << qs.errorString( ) << "\n";
    81. }
    82. }
    83.  
    84.  
    85.  
    86. void shmDetach( QSharedMemory & qs )
    87. {
    88. qDebug( ) << "About to detach from shared memory. Press key to execute.";
    89. getchar( );
    90.  
    91. qDebug( ) << "\nDetaching from shared memory...\n";
    92. if( qs.detach( ) )
    93. {
    94. qDebug( ) << "Successfully detached from shared memory.\n";
    95.  
    96. }
    97. else
    98. {
    99. qDebug( ) << "\nDetaching from shared memory failed.\n";
    100. qDebug( ) << qs.errorString( ) << "\n";
    101. }
    102. }
    103.  
    104.  
    105. #define REVERSE REVERSE
    106.  
    107.  
    108. int main(int argc, char *argv[])
    109. {
    110. QSharedMemory qs( "TEST" );
    111.  
    112. while( true )
    113. {
    114. #ifdef REVERSE
    115. // Attach, then create.
    116. if( shmAttach( qs ) ) break;
    117. if( shmCreate( qs ) ) break;
    118. #else
    119. // Create, then attach.
    120. if( shmCreate( qs ) ) break;
    121. if( shmAttach( qs ) ) break;
    122. #endif
    123. if(qs.error() == QSharedMemory::AlreadyExists || qs.error() == QSharedMemory::NotFound)
    124. qDebug( ) << "\nRetry again ...";
    125. else{
    126. qDebug( ) << "\nError occurred. Cannot continue. Terminate application.\n";
    127. return 0;
    128. }
    129. }
    130.  
    131. shmLock ( qs );
    132. qDebug( ) << "\nDo critical stuff...\n";
    133. shmUnlock( qs );
    134. shmDetach( qs );
    135.  
    136. return 0;
    137. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: QSharedMemory locking-Question

    Quote Originally Posted by kaiben View Post
    Even if I do not undertstand the reason the fix is - as documented in the thread -
    to invert the function calls create and attach.
    Seems to make sense to me. When performed in the "reverse" order as you refer to it, you attempt to attach to the shared memory segment. If that is not successful, then you attempt to create it, all the while ignoring why the attach failed because you did not check the error after attach returned false.

    If the attach failed because it does not exist, then you will successfully create (and implicitly attach) to the share memory segment by calling create.

    To handle properly IMHO, you should try to attach to the shared memory segment. If attach returns false and the error return value is QSharedMemory::NotFound, then and only then would I attempt to create the shared memory segment.

    This approach works if it's the first instance of your program, the 2nd, 3rd, 4th, etc.

    In your very first attempt, you called create, attach, lock in that order. Worked great for the 1st instance, but 2nd and subsequent instances, create would fail because it already exits, then you would attempt to attach and lock. Reading the doc for QSharedMemory::lock(), it specifically says:

    This is a semaphore that locks the shared memory segment for access by this process and returns true. If another process has locked the segment, this function blocks until the lock is released. Then it acquires the lock and returns true. If this function returns false, it means that you have ignored a false return from create() or attach(), that you have set the key with setNativeKey() or that QSystemSemaphore::acquire() failed due to an unknown system error.
    Says right there that you attempted to lock after ignoring a false return from either lock or attach and your 2nd instance and beyond would *always* receive a false return code from the create attempt. Based on that I'm not surprised it doesn't work, so I'm more surprised that it works on Windows than you are surprised it doesn't work on Linux...

    Develop good programming habits and learn to not ignore return values from functions. You will save yourself hours and hours of frustration not understanding why something isn't working. Especially as something as simple as using the error information provided by the function, it's trying to tell you what the problem is!

    Good luck
    Last edited by jefftee; 5th February 2015 at 07:27.

  7. #7
    Join Date
    Jun 2007
    Posts
    5
    Thanks
    2

    Default Re: QSharedMemory locking-Question

    Hi jthomps,

    Ok maybe the following testcases will convince you that something is wrong with the Qt implementation.

    Please take a look at the attached picture where two interaction flows between process A and B are
    described. I did the test with the source code previously send to this thread.

    BrokeCase.png

    Please tell me what do you thing about the second case? No errors are returned from the interface, so
    it is impossible to handle this case at all.
    Again it is strange to me that the reverse order (attach then create) seeems to work in all cases.
    Maybe I did not catch all cases during my testing. But it should not be my task to do that....

    Its up to you to decide what to do next...
    For me it is important to have a hopefully errorfree workaround on all platforms.
    And if doing first an "attach" and then a "create" let the software works as expected.... I can live with it.
    Furthermore it is important to me to complete this thread with all information I have, so that other people do not fall in this trap.

    Thank you for your fast help to find a solution.

    Bye
    Kai
    Attached Images Attached Images

  8. #8
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: QSharedMemory locking-Question

    I did explain why I thought the reverse order works and I do agree that the create/attach/lock approach does indeed appear to allow both processes to lock the shared memory at the same time. I believe the documentation could be improved to state which order (if relevant) the create or attach should be performed. This could be by design or a bug in QSharedMemory code.

    I don't agree that it's not your task to catch all cases in your testing though. As a developer, you have to code defensively and anticipate errors and properly handle errors or else the impact on your application will be unpredictable. The first example you posted in this thread had zero error checking.

    I'm also not sure what you meant by "its [sic] up to me to decide what to do next". I am not working on anything that uses or requires QSharedMemory, so how you handle this is up to you, not me. I was only trying to help and if you don't believe I have or can help, I'm happy to stop trying...

    That said, here's what I would do if I were you:


    • Write/test the code in the "reverse" order because so far in your testing, I believe you agree that this works on at least the two platforms you have tested (Windows and Linux). I have confirmed this approach also works on the Mac platform.

    • If you believe you have found a bug in QSharedMemory, I'd suggest that you submit a bug report.


    Edit: found this bug that may be relevant to what you are seeing.

    Good luck
    Last edited by jefftee; 6th February 2015 at 22:48. Reason: found bug that may be relevant

  9. The following user says thank you to jefftee for this useful post:

    kaiben (9th February 2015)

  10. #9
    Join Date
    Jun 2007
    Posts
    5
    Thanks
    2

    Default Re: QSharedMemory locking-Question

    Hi jthomps,

    Thank you for your answer again and I'm sorry. I supposed that you are involved in the development of the Qt Framework.
    With "you" I mean the digia company.

    I completely agree with you regarding development of software.
    With "testing all cases" I mean... consider all possible interaction/interference between the processes running concurrently when using the QSharedmemory interface.

    And finally I'm not the creator of this thread. Engelhardt did this some years ago and he posted the simple code to indicate the issue.


    Bye
    Kai

  11. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedMemory locking-Question

    In my opinion both these approaches are incorrect Regardless of the order of calls both of them may fail. The create-attach order is wrong as if create fails (the key exists) and you call attach, the block may be destroyed and your attach is going to fail leaving you with nothing. If you reverse the order and call attach first and then create, a create call from another process might fit between your calls and create will fail as well. The only solution I can see other than using a semaphore for synchronizing creation of the segment is to use a while loop in which you will be calling create and attach. And I think in this case the order of calls will not matter. Correct me if I'm wrong.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #11
    Join Date
    Jun 2007
    Posts
    5
    Thanks
    2

    Default Re: QSharedMemory locking-Question

    Hi wysota,

    If you look at the code I posted in this thread, then the create/attach, attach/create functions are within a while loop.
    http://www.qtcentre.org/threads/4186...341#post272341

    Bye
    Kai

  13. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedMemory locking-Question

    Quote Originally Posted by kaiben View Post
    If you look at the code I posted in this thread, then the create/attach, attach/create functions are within a while loop.
    Yeah, and that's ok, if you ask me. And the order of calls doesn't matter. If both processes can enter the critical section at this point then there is simply a bug in the lock implementation. You can work around this by using your own semaphore.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. The following user says thank you to wysota for this useful post:

    kaiben (9th February 2015)

Similar Threads

  1. GUI locking problem
    By Benjamin in forum Qt Programming
    Replies: 6
    Last Post: 30th July 2012, 04:48
  2. QtConcurrent locking
    By MTK358 in forum Qt Programming
    Replies: 9
    Last Post: 3rd October 2010, 12:35
  3. Mutex unlock without locking it
    By ^NyAw^ in forum Qt Programming
    Replies: 1
    Last Post: 23rd September 2010, 17:17
  4. (noob question) write qint64 into qsharedmemory
    By daemonna in forum Qt Programming
    Replies: 1
    Last Post: 28th June 2010, 11:28
  5. locking the combobox
    By jayw710 in forum Qt Programming
    Replies: 5
    Last Post: 10th May 2006, 16:12

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.