QLockFile Class
QLockFile クラスは、ファイルを用いてプロセス間のロック機能を提供します。詳細...
| ヘッダー: | #include <QLockFile> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
- 継承されたメンバーを含む、すべてのメンバーの一覧
- QLockFileは、入出力およびネットワーク機能の一部です。
パブリック型
| enum | LockError { NoError, LockFailedError, PermissionError, UnknownError } |
パブリック関数
| QLockFile(const QString &fileName) | |
| ~QLockFile() | |
| QLockFile::LockError | error() const |
| QString | fileName() const |
| bool | getLockInfo(qint64 *pid, QString *hostname, QString *appname) const |
| bool | isLocked() const |
| bool | lock() |
| bool | removeStaleLockFile() |
| void | setStaleLockTime(int staleLockTime) |
(since 6.2) void | setStaleLockTime(std::chrono::milliseconds staleLockTime) |
| int | staleLockTime() const |
(since 6.2) std::chrono::milliseconds | staleLockTimeAsDuration() const |
| bool | tryLock(int timeout) |
(since 6.2) bool | tryLock(std::chrono::milliseconds timeout = std::chrono::milliseconds::zero()) |
| void | unlock() |
詳細な説明
ロックファイルを使用すると、複数のプロセスが同じリソースに同時にアクセスすることを防ぐことができます。たとえば、ディスク上の設定ファイル、ソケット、ポート、共有メモリの領域などです...
シリアライゼーションが保証されるのは、共有リソースにアクセスするすべてのプロセスが、同じファイルパスで QLockFile を使用している場合のみです。
QLockFile は、2 つのユースケースをサポートしています。1 つは、短期間の操作(たとえば、新しい設定を保存する前に設定ファイルが変更されたかどうかを確認する場合など)のためにリソースを保護する場合、もう 1 つは、不確定な期間にわたってリソース(たとえば、エディタでユーザーが開いたドキュメントなど)を長期的に保護する場合です。
短期的な操作のためにリソースを保護する場合、lock() を呼び出し、実行中の操作がすべて終了するまで待機しても問題ありません。しかし、リソースを長期間にわたって保護する場合は、リソースがロックされていることをユーザーに警告するため、アプリケーションは常にsetStaleLockTime(0ms) を呼び出し、その後、短いタイムアウトを設定してtryLock() を呼び出す必要があります。
ロックを保持しているプロセスがクラッシュした場合、ロックファイルはディスク上に残ったままとなり、他のプロセスが共有リソースにアクセスできなくなる可能性があります。このため、QLockFile は、ファイルに書き込まれたプロセス ID に基づいて、このような「古くなった」ロックファイルを検出しようとします。 その間にプロセスIDが再利用されてしまった場合に対応するため、現在のプロセス名と、ロックファイル内のプロセスIDに対応するプロセスの名前とを比較します。プロセス名が異なる場合、そのロックファイルは古くなったものとみなされます。 さらに、ロックファイルの最終更新時刻(短時間の操作を想定したユースケースではデフォルトで30秒)も考慮されます。ロックファイルが古いと判断された場合、そのファイルは削除されます。
したがって、リソースを長期間保護するユースケースでは、setStaleLockTime(0) を呼び出し、tryLock() がLockFailedError を返した場合は、getLockInfo() などを使用して詳細情報を提供しつつ、ドキュメントがロックされていることをユーザーに通知する必要があります。
制限事項
QLockFile の実装は、ほとんどの環境やファイルシステムにおいて通常は安全です。ただし、実際には古くないロックファイルを誤って古いと判定したり、古くなったファイルを検出できなかったり、ロック時に競合が発生したりする状況がいくつか存在します。このセクションでは、それらの問題について説明します。
主な回避策は 2 つあります。適切な 0 以外の `staleLockTime()` を選択すること、およびロックファイルを保存するために通常のローカルファイルシステム(Unix システムで root として実行している場合は `/var/lock `、または `runtime location` など)を選択することです。 ただし、QLockFileの特定のユースケースでは、これが不可能な場合があります。例えば、QLockFileを使用して、ユーザーから指定されたファイルパスが編集中であることを示す場合などが挙げられます。
非永続的なマシン ID
QLockFile は、マシン固有の ID を使用して、現在のマシンによるロックと、別のホスト上で実行されているプロセスによるロックを区別します。 マシン ID が時間の経過とともに変化する場合(たとえば、一時的なストレージを使用するシステムで、起動のたびに新しい ID を生成しなければならない場合など)、QLockFile は再起動後にロックファイルが古くなっていることを検出できなくなります。
逆に、2 台の異なるマシンでマシン ID が重複している場合(たとえば、システムイメージのクローンやバックアップからの復元など)、QLockFile にネットワークパスが指定されていると、実際にはロックが古くなっていないにもかかわらず、このクラスはロックが古くなったと判定してしまう可能性があります。
ネイティブロックの欠如
QLockFile は、staleLockTime() の設定を超えても、ロックが有効(古くなっていない)であることを他のプロセスやスレッドに示すために、OS 固有の呼び出しを使用します。 この機能は、一部のネットワークファイルシステムや仮想ファイルシステム(Linux や macOS の FUSE など)上のファイルでは利用できない場合があります。また、同じファイルに異なるファイルシステムを使用してアクセスする際、ネイティブロックが引き継がれない場合や、必要なシステムコールをブロックする特定の環境においても利用できない可能性があります。
ネイティブなロック機能がサポートされていない場合、QLockFileはロックファイル自体の存在、最終更新日時、および内容のみに依存します。この場合、現在リソースをロックしているプロセスがstaleLockTime()の期限を過ぎてもロックを維持し続けていると、QLockFileはそのロックを奪取します。
ネットワークファイルシステム
ネットワーク環境においてネイティブのファイルロックがサポートされるかどうかは未定義です。実装によっては、ファイルシステムにアクセスするすべてのクライアントでサポートされる場合もあれば、ローカルシステムが自身のプロセスに対してロックをサポートしていてもネットワーク経由でロックを共有しない場合、さらには1つのホスト内ですらネイティブロックが存在しない場合もあります。 さらに、同じファイルに対して、ネットワークロックに参加するクライアントと参加しないクライアントが混在する可能性もあります。ネットワークを介したロックがサポートされていない場合、QLockFile は、ネイティブロックが存在しない場合に説明した制限に従います。
さらに、ロックファイルに別のホストの識別子が含まれている場合、QLockFileはロックを保持しているプロセスがまだ実行中であるかを確認できず、staleLockTime() が不正常終了から回復するのを待つ必要があります。
同じパスを通じて異なる実際のファイルにアクセスする場合
2つのプロセスがファイルシステムに対して異なるビューを持っている可能性があり、その結果、同一のファイルパスがファイルシステム上では異なるファイルとなる場合があります。この場合、2つのQLockFileオブジェクトはロックの作成に成功する可能性がありますが、相互排他性はありません。ロックファイルが保護しているリソースが依然として両プロセス間で共有されている場合、競合が発生する可能性があります。
この状況はコンテナ(後述)で最も頻繁に発生しますが、コンテナに限ったことではありません。
コンテナと共有されるファイル
一部のコンテナ実装では、特定のプロセスの存在を隠蔽することが可能です(例えば、Linuxの「PIDネームスペース」機能など)。 あるプロセスがそのようなコンテナ内で実行されているものの、ホストシステムや別のコンテナとマシンIDを共有している場合、異なるコンテナ(またはホスト)内の2つのプロセスは、ロックを掛けているプロセスがまだ実行中であるかどうかについて誤った判断を下してしまいます。 さらに、一部のコンテナコントローラは、コンテナ内のブート ID を置き換えることがあるため、起動されたプロセスは、タイムスタンプがどれほど新しいかに関係なく、ロックファイルが常に古いと判断してしまいます。
他の実装によっては、コンテナが一時的なストレージを持つ場合や、衝突を避けるために意図的に新しいマシン ID を作成する場合があります。この場合、アプリケーションは、非永続的なマシン ID に関して前述の問題に直面することになります。
ただし、ネイティブのファイルロックは通常正常に機能するため(前述のファイルシステムや環境の制限はありますが)、たとえ QLockFile がそのファイルが明らかに古いと判断したとしても、ネイティブにロックされているロックファイルを奪うことはありません。
同じプロトコルを使用しないアクセス
QLockFile は、このクラスが実装するプロトコル外で行われたロックファイルへの変更とは相互運用できません。これには、tmpwatch などのツールによるロックファイルの削除だけでなく、一部のウイルススキャンツールや類似のツールによる操作も含まれます。
クロックのずれ
QLockFileは、ロックファイルのタイムスタンプが正確であることを前提としています。時計が前進した場合、QLockFileは実際には古くなっていないロックファイルを古くなったと判断してしまう可能性があり、逆に時計が後退した場合も同様の現象が発生します。
このため、すべてのシステムでネットワーク同期された時刻を維持し、起動プロセスの早い段階でこの同期を行うことが推奨されます。これは、ネットワークファイルシステムにおいて特に重要です。
メンバ型のドキュメント
enum QLockFile::LockError
この列挙型は、lock() またはtryLock() の最後の呼び出しの結果を表します。
| 定数 | 定数名 | 説明 |
|---|---|---|
QLockFile::NoError | 0 | ロックの取得に成功しました。 |
QLockFile::LockFailedError | 1 | 別のプロセスがロックを保持しているため、ロックを取得できませんでした。 |
QLockFile::PermissionError | 2 | 親ディレクトリに権限がないため、ロックファイルを作成できませんでした。 |
QLockFile::UnknownError | 3 | その他のエラーが発生しました。たとえば、パーティションが満杯だったためにロックファイルの書き込みができなかったなどです。 |
メンバ関数のドキュメント
[explicit] QLockFile::QLockFile(const QString &fileName)
新しいロックファイルオブジェクトを作成します。このオブジェクトはロックされていない状態で作成されます。lock() またはtryLock() を呼び出す際、fileName という名前のロックファイルがまだ存在しない場合は、そのファイルが作成されます。
[noexcept] QLockFile::~QLockFile()
ロックファイルオブジェクトを破棄します。ロックが取得されていた場合、この操作によりロックファイルが削除され、ロックが解放されます。
QLockFile::LockError QLockFile::error() const
ロックファイルのエラーステータスを返します。
tryLock() が `false` を返した場合、この関数を呼び出すことで、ロックに失敗した原因を特定できます。
QString QLockFile::fileName() const
ロックファイルのファイル名を返します
bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const
ロックファイルの現在の所有者に関する情報を取得します。
tryLock() が `false` を返し、error() が `LockFailedError` を返す場合、この関数を呼び出すことで、既存のロックファイルに関する詳細情報を取得できます。
- アプリケーションのPID(pid で返される)
- 実行されているhostname (ネットワークファイルシステムの場合に有用)
- そのロックファイルを作成したアプリケーションの名前(appname で返されます)、
なお、tryLock() は、この PID を持つ実行中のアプリケーションが存在しない場合、ファイルを自動的に削除するため、LockFailedError が呼び出されるのは、この PID を持つアプリケーションが存在する場合に限られます(ただし、そのアプリケーションとは無関係である可能性もあります)。
これを利用して、ユーザーにロックファイルの存在を通知し、削除するかどうかを選択させることができます。removeStaleLockFile() を使用してファイルを削除した後、アプリケーションは再度tryLock() を呼び出すことができます。
この関数は、情報を正常に取得できた場合はtrue を返し、ロックファイルが存在しないか、期待されるデータが含まれていない場合はfalseを返します。これは、tryLock()が失敗してからこの関数が呼び出されるまでの間にロックファイルが削除された場合に発生する可能性があります。その場合は、単にtryLock()を再度呼び出してください。
bool QLockFile::isLocked() const
このQLockFile インスタンスによってロックが取得されていた場合はtrue を返し、そうでない場合はfalse を返します。
lock()、unlock()、およびtryLock()も参照してください 。
bool QLockFile::lock()
ロックファイルを作成します。
別のプロセス(またはスレッド)がすでにロックファイルを作成している場合、この関数は、そのプロセス(またはスレッド)がロックを解放するまでブロックされます。
最初にロックを解除せずに、同じスレッドから同じロックに対してこの関数を複数回呼び出すことは許可されません。ファイルが再帰的にロックされている場合、この関数はデッドロックを起こします。
ロックが取得できた場合は `true ` を返し、親ディレクトリへのアクセス権がないなど、回復不可能なエラーによりロックを取得できなかった場合は `false` を返します。
unlock() およびtryLock()も参照してください 。
bool QLockFile::removeStaleLockFile()
既存のロックファイルを強制的に削除しようとしています。
短期間の操作を保護する場合、この関数を呼び出すことは推奨されません。QLockFile は、ロックファイルがstaleLockTime()よりも古い場合、自動的に削除を行うためです。
このメソッドは、リソースを長期間保護する場合、つまりstaleLockTime(0) を使用する場合にのみ呼び出すべきであり、かつtryLock() がLockFailedError を返した後、ユーザーがロックファイルの削除に同意した場合に限ります。
成功した場合はtrue を返し、ロックファイルを削除できなかった場合はfalseを返します。これは、Windowsにおいて、ロックを保持しているアプリケーションがまだ実行中の場合に発生します。
void QLockFile::setStaleLockTime(int staleLockTime)
staleLockTime を、ロックファイルが古くなったとみなされるまでの時間をミリ秒単位で設定します。デフォルト値は 30000、つまり 30 秒です。 アプリケーションで通常、ファイルを 30 秒以上ロックし続ける場合(たとえば、数メガバイトのデータを 2 分間保存する場合など)、setStaleLockTime() を使用してより大きな値を設定する必要があります。
staleLockTime の値は、lock() およびtryLock() によって、既存のロックファイルがいつ「古くなった」、つまりクラッシュしたプロセスによって残されたものとみなされるかを判断するために使用されます。これは、その間に PID が再利用されてしまった場合に有用であり、ロックファイルが長時間存在し続けているという事実によって、そのファイルが古くなったものであることを検出する方法の一つとなります。
これはオーバーロードされた関数であり、以下の呼び出しと同等です:
setStaleLockTime(std::chrono::milliseconds{staleLockTime});staleLockTime()も参照してください 。
[since 6.2] void QLockFile::setStaleLockTime(std::chrono::milliseconds staleLockTime)
ロックファイルが古くなったとみなされるまでの間隔をstaleLockTime に設定します。デフォルト値は30秒です。
アプリケーションで通常、ファイルを30秒以上ロックし続ける場合(たとえば、数メガバイトのデータを2分間保存する場合など)、setStaleLockTime() を使用してより大きな値を設定する必要があります。
staleLockTime() の値は、lock() およびtryLock() によって、既存のロックファイルがいつ「古くなった」、つまりクラッシュしたプロセスによって残されたものとみなされるかを判断するために使用されます。これは、その間に PID が再利用された場合に有用であり、ロックファイルが長時間存在しているという事実に基づいて、古くなったロックファイルを検出する方法の一つとなります。
この値を 0 または負の値に設定すると、ロックファイルのタイムスタンプの検証が無効になります。QLockFile は、その内容からロックを行っているプロセスがもはや実行されていないことが判明した場合、引き続き古いロックファイルを検出します。
この関数は Qt 6.2 で導入されました。
staleLockTime()も参照してください 。
int QLockFile::staleLockTime() const
ロックファイルが古くなったとみなされるまでの時間をミリ秒単位で返します。
setStaleLockTime()も参照してください 。
[since 6.2] std::chrono::milliseconds QLockFile::staleLockTimeAsDuration() const
ロックファイルが古くなったとみなされるまでの時間を表す std::chrono::milliseconds オブジェクトを返します。
この関数は Qt 6.2 で導入されました。
setStaleLockTime()も参照してください 。
bool QLockFile::tryLock(int timeout)
ロックファイルの作成を試みます。この関数は、ロックを取得できた場合にtrue を返し、そうでない場合はfalse を返します。別のプロセス(または別のスレッド)がすでにロックファイルを作成している場合、この関数はロックファイルが利用可能になるまで、最大timeout ミリ秒待機します。
注:timeout として負の数を渡すことは、lock() を呼び出すことと同じです。つまり、timeout が負の場合、この関数はロックファイルがロック可能になるまで無限に待機します。
ロックが取得された場合、別のプロセス(またはスレッド)が正常にロックを行うには、unlock() を使用してロックを解除する必要があります。
同じスレッドから、最初にロックを解除せずに同じロックに対してこの関数を複数回呼び出すことは許可されていません。ファイルを再帰的にロックしようとすると、この関数は常にfalse を返します。
[since 6.2] bool QLockFile::tryLock(std::chrono::milliseconds timeout = std::chrono::milliseconds::zero())
ロックファイルの作成を試みます。この関数は、ロックを取得できた場合はtrue を返し、そうでない場合はfalse を返します。別のプロセス(またはスレッド)がすでにロックファイルを作成している場合、この関数はロックファイルが利用可能になるまで、最大timeout の間待機します。
ロックが取得された場合、別のプロセス(またはスレッド)が正常にロックを行うには、unlock() を使用してロックを解除する必要があります。
同じスレッドから、最初にロックを解除せずに同じロックに対してこの関数を複数回呼び出すことは許可されていません。ファイルを再帰的にロックしようとすると、この関数は常にfalse を返します。
これはオーバーロードされた関数です。
この関数は Qt 6.2 で導入されました。
void QLockFile::unlock()
ロックファイルを削除して、ロックを解除します。
事前にファイルをロックせずに unlock() を呼び出しても、何もしません。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.