8f427b2 by axis at 2009-04-24 1
/****************************************************************************
2
**
89c08c0 by Jason McDonald at 2012-01-11 3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
04e3b30 by Jason McDonald at 2009-09-09 4
** All rights reserved.
858c70f by Jason McDonald at 2009-06-16 5
** Contact: Nokia Corporation (qt-info@nokia.com)
8f427b2 by axis at 2009-04-24 6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
1eea52e by Jyri Tahtela at 2011-05-13 11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
8f427b2 by axis at 2009-04-24 17
**
04e3b30 by Jason McDonald at 2009-09-09 18
** In addition, as a special exception, Nokia gives you certain additional
1eea52e by Jyri Tahtela at 2011-05-13 19
** rights. These rights are described in the Nokia Qt LGPL Exception
04e3b30 by Jason McDonald at 2009-09-09 20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
8f427b2 by axis at 2009-04-24 21
**
1eea52e by Jyri Tahtela at 2011-05-13 22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
309db73 by Jason McDonald at 2009-08-31 33
**
34
**
35
**
36
**
8f427b2 by axis at 2009-04-24 37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include "qsharedmemory.h"
43
#include "qsharedmemory_p.h"
44
#include "qsystemsemaphore.h"
45
#include <qdir.h>
46
#include <qcryptographichash.h>
47
#ifdef Q_OS_SYMBIAN
48
#include <e32const.h>
49
#endif
50
#include <qdebug.h>
51
52
QT_BEGIN_NAMESPACE
53
54
#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
55
/*!
56
    \internal
57
58
    Generate a string from the key which can be any unicode string into
59
    the subset that the win/unix kernel allows.
60
61
    On Unix this will be a file name
62
    On Symbian key will be truncated to 80 characters
63
  */
64
QString
65
QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
66
					  const QString &prefix)
67
{
68
    if (key.isEmpty())
69
        return QString();
70
71
    QString result = prefix;
72
73
    QString part1 = key;
74
    part1.replace(QRegExp(QLatin1String("[^A-Za-z]")), QString());
75
    result.append(part1);
76
77
    QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
78
    result.append(QLatin1String(hex));
79
#ifdef Q_OS_WIN
80
    return result;
6c08eef by mread at 2010-10-22 81
#elif defined(Q_OS_SYMBIAN)
82
    return result.left(KMaxKernelName);
d869e1a by Ritt Konstantin at 2011-06-21 83
#elif defined(QT_POSIX_IPC)
84
    return QLatin1Char('/') + result;
8f427b2 by axis at 2009-04-24 85
#else
86
    return QDir::tempPath() + QLatin1Char('/') + result;
87
#endif
88
}
89
#endif // QT_NO_SHAREDMEMORY && QT_NO_SHAREDMEMORY
90
91
#ifndef QT_NO_SHAREDMEMORY
92
93
/*!
94
  \class QSharedMemory
95
  \since 4.4
96
97
  \brief The QSharedMemory class provides access to a shared memory segment.
98
99
  QSharedMemory provides access to a shared memory segment by multiple
100
  threads and processes. It also provides a way for a single thread or
101
  process to lock the memory for exclusive access.
102
103
  When using this class, be aware of the following platform
104
  differences:
105
106
  \list
107
108
  \o Windows: QSharedMemory does not "own" the shared memory segment.
109
  When all threads or processes that have an instance of QSharedMemory
110
  attached to a particular shared memory segment have either destroyed
111
  their instance of QSharedMemory or exited, the Windows kernel
112
  releases the shared memory segment automatically.
113
114
  \o Unix: QSharedMemory "owns" the shared memory segment. When the
115
  last thread or process that has an instance of QSharedMemory
116
  attached to a particular shared memory segment detaches from the
117
  segment by destroying its instance of QSharedMemory, the Unix kernel
118
  release the shared memory segment. But if that last thread or
119
  process crashes without running the QSharedMemory destructor, the
120
  shared memory segment survives the crash.
121
d869e1a by Ritt Konstantin at 2011-06-21 122
  \o QNX: Due to possible race conditions in the POSIX IPC implementation, create()
123
  should be called prior to any attach() calls (even across multiple threads).
124
8f427b2 by axis at 2009-04-24 125
  \o HP-UX: Only one attach to a shared memory segment is allowed per
126
  process. This means that QSharedMemory should not be used across
127
  multiple threads in the same process in HP-UX.
128
129
  \o Symbian: QSharedMemory does not "own" the shared memory segment.
130
  When all threads or processes that have an instance of QSharedMemory
131
  attached to a particular shared memory segment have either destroyed
132
  their instance of QSharedMemory or exited, the Symbian kernel
133
  releases the shared memory segment automatically.
134
  Also, access to a shared memory segment cannot be limited to read-only
135
  in Symbian.
136
137
  \endlist
138
139
  Remember to lock the shared memory with lock() before reading from
140
  or writing to the shared memory, and remember to release the lock
141
  with unlock() after you are done.
142
143
  Unlike QtSharedMemory, QSharedMemory automatically destroys the
144
  shared memory segment when the last instance of QSharedMemory is
145
  detached from the segment, and no references to the segment
146
  remain. Do not mix using QtSharedMemory and QSharedMemory. Port
147
  everything to QSharedMemory.
9824e4a by Markus Goetz at 2009-05-18 148
97a092b by Mirko Damiani at 2010-05-26 149
  \warning QSharedMemory changes the key in a Qt-specific way, unless otherwise
150
  specified. Interoperation with non-Qt applications is achieved by first creating
151
  a default shared memory with QSharedMemory() and then setting a native key with
152
  setNativeKey(). When using native keys, shared memory is not protected against
153
  multiple accesses on it (e.g. unable to lock()) and a user-defined mechanism
154
  should be used to achieve a such protection.
8f427b2 by axis at 2009-04-24 155
 */
156
157
/*!
158
  \overload QSharedMemory()
159
160
  Constructs a shared memory object with the given \a parent.  The
161
  shared memory object's key is not set by the constructor, so the
162
  shared memory object does not have an underlying shared memory
97a092b by Mirko Damiani at 2010-05-26 163
  segment attached. The key must be set with setKey() or setNativeKey()
164
  before create() or attach() can be used.
8f427b2 by axis at 2009-04-24 165
166
  \sa setKey()
167
 */
168
QSharedMemory::QSharedMemory(QObject *parent)
169
  : QObject(*new QSharedMemoryPrivate, parent)
170
{
171
}
172
173
/*!
174
  Constructs a shared memory object with the given \a parent and with
175
  its key set to \a key. Because its key is set, its create() and
176
  attach() functions can be called.
177
178
  \sa setKey(), create(), attach()
179
 */
180
QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
181
    : QObject(*new QSharedMemoryPrivate, parent)
182
{
183
    setKey(key);
184
}
185
186
/*!
187
  The destructor clears the key, which forces the shared memory object
188
  to \l {detach()} {detach} from its underlying shared memory
189
  segment. If this shared memory object is the last one connected to
190
  the shared memory segment, the detach() operation destroys the
191
  shared memory segment.
192
193
  \sa detach() isAttached()
194
 */
195
QSharedMemory::~QSharedMemory()
196
{
197
    setKey(QString());
198
}
199
200
/*!
8d267e8 by Andreas Aardal Hanssen at 2010-05-26 201
  Sets the platform independent \a key for this shared memory object. If \a key
202
  is the same as the current key, the function returns without doing anything.
203
204
  You can call key() to retrieve the platform independent key. Internally,
205
  QSharedMemory converts this key into a platform specific key. If you instead
206
  call nativeKey(), you will get the platform specific, converted key.
207
208
  If the shared memory object is attached to an underlying shared memory
209
  segment, it will \l {detach()} {detach} from it before setting the new key.
97a092b by Mirko Damiani at 2010-05-26 210
  This function does not do an attach().
211
212
  \sa key() nativeKey() isAttached()
213
*/
8f427b2 by axis at 2009-04-24 214
void QSharedMemory::setKey(const QString &key)
215
{
216
    Q_D(QSharedMemory);
97a092b by Mirko Damiani at 2010-05-26 217
    if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey)
8f427b2 by axis at 2009-04-24 218
        return;
219
220
    if (isAttached())
221
        detach();
222
    d->cleanHandle();
223
    d->key = key;
97a092b by Mirko Damiani at 2010-05-26 224
    d->nativeKey = d->makePlatformSafeKey(key);
225
}
226
227
/*!
8d267e8 by Andreas Aardal Hanssen at 2010-05-26 228
  \since 4.8
229
230
  Sets the native, platform specific, \a key for this shared memory object. If
231
  \a key is the same as the current native key, the function returns without
232
  doing anything. If all you want is to assign a key to a segment, you should
233
  call setKey() instead.
234
235
  You can call nativeKey() to retrieve the native key. If a native key has been
236
  assigned, calling key() will return a null string.
237
238
  If the shared memory object is attached to an underlying shared memory
97a092b by Mirko Damiani at 2010-05-26 239
  segment, it will \l {detach()} {detach} from it before setting the new key.
240
  This function does not do an attach().
241
8d267e8 by Andreas Aardal Hanssen at 2010-05-26 242
  The application will not be portable if you set a native key.
243
97a092b by Mirko Damiani at 2010-05-26 244
  \sa nativeKey() key() isAttached()
245
*/
246
void QSharedMemory::setNativeKey(const QString &key)
247
{
248
    Q_D(QSharedMemory);
249
    if (key == d->nativeKey && d->key.isNull())
250
        return;
251
252
    if (isAttached())
253
        detach();
254
    d->cleanHandle();
11bacd3 by Ritt Konstantin at 2011-06-06 255
    d->key.clear();
97a092b by Mirko Damiani at 2010-05-26 256
    d->nativeKey = key;
8f427b2 by axis at 2009-04-24 257
}
258
259
bool QSharedMemoryPrivate::initKey()
260
{
8eaf39f by Ritt Konstantin at 2011-06-06 261
    cleanHandle();
262
8f427b2 by axis at 2009-04-24 263
#ifndef QT_NO_SYSTEMSEMAPHORE
264
    systemSemaphore.setKey(QString(), 1);
265
    systemSemaphore.setKey(key, 1);
266
    if (systemSemaphore.error() != QSystemSemaphore::NoError) {
267
        QString function = QLatin1String("QSharedMemoryPrivate::initKey");
268
        errorString = QSharedMemory::tr("%1: unable to set key on lock").arg(function);
269
        switch(systemSemaphore.error()) {
270
        case QSystemSemaphore::PermissionDenied:
271
            error = QSharedMemory::PermissionDenied;
272
            break;
273
        case QSystemSemaphore::KeyError:
274
            error = QSharedMemory::KeyError;
275
            break;
276
        case QSystemSemaphore::AlreadyExists:
277
            error = QSharedMemory::AlreadyExists;
278
            break;
279
        case QSystemSemaphore::NotFound:
280
            error = QSharedMemory::NotFound;
281
            break;
282
        case QSystemSemaphore::OutOfResources:
283
            error = QSharedMemory::OutOfResources;
284
            break;
285
        case QSystemSemaphore::UnknownError:
286
        default:
287
            error = QSharedMemory::UnknownError;
288
            break;
289
        }
290
        return false;
291
    }
292
#endif
11bacd3 by Ritt Konstantin at 2011-06-06 293
    errorString.clear();
8f427b2 by axis at 2009-04-24 294
    error = QSharedMemory::NoError;
295
    return true;
296
}
297
298
/*!
8d267e8 by Andreas Aardal Hanssen at 2010-05-26 299
  Returns the key assigned with setKey() to this shared memory, or a null key
300
  if no key has been assigned, or if the segment is using a nativeKey(). The
301
  key is the identifier used by Qt applications to identify the shared memory
302
  segment.
303
304
  You can find the native, platform specific, key used by the operating system
305
  by calling nativeKey().
97a092b by Mirko Damiani at 2010-05-26 306
307
  \sa setKey() setNativeKey()
8f427b2 by axis at 2009-04-24 308
 */
309
QString QSharedMemory::key() const
310
{
311
    Q_D(const QSharedMemory);
312
    return d->key;
313
}
314
315
/*!
8d267e8 by Andreas Aardal Hanssen at 2010-05-26 316
  \since 4.8
317
318
  Returns the native, platform specific, key for this shared memory object. The
319
  native key is the identifier used by the operating system to identify the
320
  shared memory segment.
321
322
  You can use the native key to access shared memory segments that have not
323
  been created by Qt, or to grant shared memory access to non-Qt applications.
97a092b by Mirko Damiani at 2010-05-26 324
325
  \sa setKey() setNativeKey()
326
*/
327
QString QSharedMemory::nativeKey() const
328
{
329
    Q_D(const QSharedMemory);
330
    return d->nativeKey;
331
}
332
333
/*!
334
  Creates a shared memory segment of \a size bytes with the key passed to the
335
  constructor, set with setKey() or set with setNativeKey(), then attaches to
336
  the new shared memory segment with the given access \a mode and returns
337
  \tt true. If a shared memory segment identified by the key already exists,
338
  the attach operation is not performed and \tt false is returned. When the
339
  return value is \tt false, call error() to determine which error occurred.
8f427b2 by axis at 2009-04-24 340
341
  \sa error()
342
 */
343
bool QSharedMemory::create(int size, AccessMode mode)
344
{
345
    Q_D(QSharedMemory);
346
347
    if (!d->initKey())
348
        return false;
349
11bacd3 by Ritt Konstantin at 2011-06-06 350
    if (size <= 0) {
351
        d->error = QSharedMemory::InvalidSize;
352
        d->errorString = QSharedMemory::tr("%1: create size is less then 0").arg(QLatin1String("QSharedMemory::create"));
353
        return false;
354
    }
355
8f427b2 by axis at 2009-04-24 356
#ifndef QT_NO_SYSTEMSEMAPHORE
357
#ifndef Q_OS_WIN
358
    // Take ownership and force set initialValue because the semaphore
359
    // might have already existed from a previous crash.
360
    d->systemSemaphore.setKey(d->key, 1, QSystemSemaphore::Create);
361
#endif
362
363
    QSharedMemoryLocker lock(this);
11bacd3 by Ritt Konstantin at 2011-06-06 364
    if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::create")))
8f427b2 by axis at 2009-04-24 365
        return false;
366
#endif
367
368
    if (!d->create(size))
369
        return false;
370
371
    return d->attach(mode);
372
}
373
374
/*!
375
  Returns the size of the attached shared memory segment. If no shared
376
  memory segment is attached, 0 is returned.
377
378
  \sa create() attach()
379
 */
380
int QSharedMemory::size() const
381
{
382
    Q_D(const QSharedMemory);
383
    return d->size;
384
}
385
386
/*!
387
  \enum QSharedMemory::AccessMode
388
389
  \value ReadOnly The shared memory segment is read-only. Writing to
390
  the shared memory segment is not allowed. An attempt to write to a
391
  shared memory segment created with ReadOnly causes the program to
392
  abort.
393
394
  \value ReadWrite Reading and writing the shared memory segment are
395
  both allowed.
396
*/
397
398
/*!
399
  Attempts to attach the process to the shared memory segment
400
  identified by the key that was passed to the constructor or to a
97a092b by Mirko Damiani at 2010-05-26 401
  call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::}
8f427b2 by axis at 2009-04-24 402
  {ReadWrite} by default. It can also be \l {QSharedMemory::}
403
  {ReadOnly}. Returns true if the attach operation is successful. If
404
  false is returned, call error() to determine which error occurred.
405
  After attaching the shared memory segment, a pointer to the shared
406
  memory can be obtained by calling data().
407
408
  \sa isAttached(), detach(), create()
409
 */
410
bool QSharedMemory::attach(AccessMode mode)
411
{
412
    Q_D(QSharedMemory);
413
414
    if (isAttached() || !d->initKey())
415
        return false;
416
#ifndef QT_NO_SYSTEMSEMAPHORE
417
    QSharedMemoryLocker lock(this);
97a092b by Mirko Damiani at 2010-05-26 418
    if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach")))
8f427b2 by axis at 2009-04-24 419
        return false;
420
#endif
421
422
    if (isAttached() || !d->handle())
423
        return false;
424
425
    return d->attach(mode);
426
}
427
428
/*!
429
  Returns true if this process is attached to the shared memory
430
  segment.
431
432
  \sa attach(), detach()
433
 */
434
bool QSharedMemory::isAttached() const
435
{
436
    Q_D(const QSharedMemory);
437
    return (0 != d->memory);
438
}
439
440
/*!
441
  Detaches the process from the shared memory segment. If this was the
442
  last process attached to the shared memory segment, then the shared
443
  memory segment is released by the system, i.e., the contents are
444
  destroyed. The function returns true if it detaches the shared
445
  memory segment. If it returns false, it usually means the segment
446
  either isn't attached, or it is locked by another process.
447
448
  \sa attach(), isAttached()
449
 */
450
bool QSharedMemory::detach()
451
{
452
    Q_D(QSharedMemory);
453
    if (!isAttached())
454
        return false;
455
456
#ifndef QT_NO_SYSTEMSEMAPHORE
457
    QSharedMemoryLocker lock(this);
97a092b by Mirko Damiani at 2010-05-26 458
    if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach")))
8f427b2 by axis at 2009-04-24 459
        return false;
460
#endif
461
c17e49e by Ritt Konstantin at 2011-01-21 462
    return d->detach();
8f427b2 by axis at 2009-04-24 463
}
464
465
/*!
466
  Returns a pointer to the contents of the shared memory segment, if
467
  one is attached. Otherwise it returns null. Remember to lock the
468
  shared memory with lock() before reading from or writing to the
469
  shared memory, and remember to release the lock with unlock() after
470
  you are done.
471
472
  \sa attach()
473
 */
474
void *QSharedMemory::data()
475
{
476
    Q_D(QSharedMemory);
477
    return d->memory;
478
}
479
480
/*!
481
  Returns a const pointer to the contents of the shared memory
482
  segment, if one is attached. Otherwise it returns null. Remember to
483
  lock the shared memory with lock() before reading from or writing to
484
  the shared memory, and remember to release the lock with unlock()
485
  after you are done.
486
487
  \sa attach() create()
488
 */
489
const void* QSharedMemory::constData() const
490
{
491
    Q_D(const QSharedMemory);
492
    return d->memory;
493
}
494
495
/*!
496
  \overload data()
497
 */
498
const void *QSharedMemory::data() const
499
{
500
    Q_D(const QSharedMemory);
501
    return d->memory;
502
}
503
504
#ifndef QT_NO_SYSTEMSEMAPHORE
505
/*!
506
  This is a semaphore that locks the shared memory segment for access
507
  by this process and returns true. If another process has locked the
508
  segment, this function blocks until the lock is released. Then it
509
  acquires the lock and returns true. If this function returns false,
97a092b by Mirko Damiani at 2010-05-26 510
  it means that you have ignored a false return from create() or attach(),
511
  that you have set the key with setNativeKey() or that
512
  QSystemSemaphore::acquire() failed due to an unknown system error.
8f427b2 by axis at 2009-04-24 513
514
  \sa unlock(), data(), QSystemSemaphore::acquire()
515
 */
516
bool QSharedMemory::lock()
517
{
518
    Q_D(QSharedMemory);
519
    if (d->lockedByMe) {
520
        qWarning("QSharedMemory::lock: already locked");
521
        return true;
522
    }
523
    if (d->systemSemaphore.acquire()) {
524
        d->lockedByMe = true;
525
        return true;
526
    }
527
    QString function = QLatin1String("QSharedMemory::lock");
528
    d->errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
529
    d->error = QSharedMemory::LockError;
530
    return false;
531
}
532
533
/*!
534
  Releases the lock on the shared memory segment and returns true, if
535
  the lock is currently held by this process. If the segment is not
536
  locked, or if the lock is held by another process, nothing happens
537
  and false is returned.
538
539
  \sa lock()
540
 */
541
bool QSharedMemory::unlock()
542
{
543
    Q_D(QSharedMemory);
544
    if (!d->lockedByMe)
545
        return false;
546
    d->lockedByMe = false;
547
    if (d->systemSemaphore.release())
548
        return true;
549
    QString function = QLatin1String("QSharedMemory::unlock");
550
    d->errorString = QSharedMemory::tr("%1: unable to unlock").arg(function);
551
    d->error = QSharedMemory::LockError;
552
    return false;
553
}
554
#endif // QT_NO_SYSTEMSEMAPHORE
555
556
/*!
557
  \enum QSharedMemory::SharedMemoryError
558
559
  \value NoError No error occurred.
560
561
  \value PermissionDenied The operation failed because the caller
562
  didn't have the required permissions.
563
564
  \value InvalidSize A create operation failed because the requested
565
  size was invalid.
566
567
  \value KeyError The operation failed because of an invalid key.
568
569
  \value AlreadyExists A create() operation failed because a shared
570
  memory segment with the specified key already existed.
571
572
  \value NotFound An attach() failed because a shared memory segment
573
  with the specified key could not be found.
574
575
  \value LockError The attempt to lock() the shared memory segment
576
  failed because create() or attach() failed and returned false, or
577
  because a system error occurred in QSystemSemaphore::acquire().
578
579
  \value OutOfResources A create() operation failed because there was
580
  not enough memory available to fill the request.
581
582
  \value UnknownError Something else happened and it was bad.
583
*/
584
585
/*!
586
  Returns a value indicating whether an error occurred, and, if so,
587
  which error it was.
588
589
  \sa errorString()
590
 */
591
QSharedMemory::SharedMemoryError QSharedMemory::error() const
592
{
593
    Q_D(const QSharedMemory);
594
    return d->error;
595
}
596
597
/*!
598
  Returns a text description of the last error that occurred. If
599
  error() returns an \l {QSharedMemory::SharedMemoryError} {error
600
  value}, call this function to get a text string that describes the
601
  error.
602
603
  \sa error()
604
 */
605
QString QSharedMemory::errorString() const
606
{
607
    Q_D(const QSharedMemory);
608
    return d->errorString;
609
}
610
611
#endif // QT_NO_SHAREDMEMORY
612
613
QT_END_NAMESPACE