ホームページ バックエンド開発 PHPチュートリアル [グッドプラクティス記事] PHP デッドロック問題の分析

[グッドプラクティス記事] PHP デッドロック問題の分析

Jun 20, 2016 pm 12:25 PM

背景: デッドロックの問題というと、テスト環境であればアクセスの遅さやホワイトページ現象を思い浮かべる方が多いと思います(実際に私もテスト環境でこの記事で述べたのと同じ問題に遭遇しました)。 ) PHP php-fpm プロセスを再起動すると、再び正常であることがわかりますが、しばらくすると同様の問題が再び発生します。「最大実行タイムアウト」というログが多数あることがわかります。 60 秒を超えました。これは、一部の php デーモン プロセスが原因である可能性があることがわかります。テスト環境の問題を解決するには、より多くの php-fpm プロセスを開いた方がよいと考えます。そのため、オープンします。この問題の原因は、会社がインストールした PHP は運用保守によってインストールされており、デバッグ版の PHP をインストールする方法と時間がないためです。この問題は運用保守担当者に確認してもらう必要があるとのことですが、発見できると思いますか?それで、この問題は何度も延期されましたが、解決されていませんでした。しかし、ある日、du を使用してディスク全体を確認すると、ディスクがいっぱいであることがわかりました。ディレクトリを 1 つずつ見てみると、それほど多くは占有されていないことがわかります。私は、PHP のデッドロックによってディスク領域が過剰に占有されるのではないかと考えていました。実際に上記の状況に遭遇しました。その後、オペレーティング システムを再起動すると、ディスクが回復しました。そのため、この記事は、PHP 拡張機能のコード品質を厳密に管理する必要があることを説明したいと考えたので、この記事に転送しました。そして、PHP 自体のロックの側面を弱める必要があります (Cookie/セッションとキャッシュのロックを除き、必要でなければ他のものを使用できます)。ロックの使用はできるだけ少なくする必要があります。これはブロガーのちょっとした意見です。本題に入りましょう。

はじめに:

今回は、クラウド ディスク サーバー チームの技術専門家である Xu Tiecheng 氏をお招きし、長らく隠されていた PHP のデッドロックの問題が明らかになりました。この楽しい体験をお届けします、皆さん、このテクノロジーの旅への準備はできていますか?

---------------

問題が見つかりました

最近、多くのオンライン マシンにディスク容量アラームが発生していることがわかりました。ログ ファイルはクリーンアップされましたが、ディスク領域は解放されませんでした。 ps aux | grep php-cgi を通じて、多くのプロセスが数日から数週間、場合によっては数か月前に開始されたことがわかりました。弊社のオンライン php-cgi には最大実行数があります。通常、1 日以内に 1 回再起動されます。暫定的な結論は、これらの CGI プロセスに問題があるということです。

lsof -p [pid] により、長時間起動された CGI プロセスで一部のログ ファイル ハンドルが開かれ、閉じられていないことが判明しました。これらのログ ファイルはファイル システムから削除されました。ただし、ハンドルが閉じられていないため、ディスク領域が解放されません。この時点で、異常なディスク容量の問題は基本的に特定されます。これは、CGI がファイル ハンドルを閉じていないことが原因です。

プロセスをさらに分析し、strace -p [pid] を実行すると、すべての異常なプロセスが fmutex 状態でブロックされていることを確認します。つまり、異常な CGI プロセスがデッドロック状態になります。プロセスのデッドロックにより、開いているファイル ハンドルが閉じられなくなり、ディスク領域の異常が発生します。

CGI プロセスがデッドロックするのはなぜですか?

デッドロックとは

オペレーティング システムを勉強したことのある人なら誰でも、マルチスレッドの概念を知っています。複数のスレッドでパブリック リソースにアクセスするには、リソースをロックする必要があります。アクセスが完了したらロックを解除してください。ロックが解放されないと、次のスレッドがリソースを取得するときにリソース ロックを取得できなくなり、スレッドはデッドロックになります。では、CGI はマルチスレッドのパブリック リソース アクセスによって引き起こされるデッドロックなのでしょうか? 答えは「ノー」です。

1. CGI はシングルスレッドプロセスであり、ps を通じて見ることができます。 (プロセスステータスS1はマルチスレッドプロセスである)。

2. マルチスレッドであっても、デッドロックは PHP のシャットダウン処理中に glibc の time 関数が呼び出されたときに発生します。これは PHP モジュールが原因ではありません。 glibc の時間関連関数はスレッドセーフであり、デッドロックを引き起こしません。

デッドロックの原因は何ですか?

Linux におけるデッドロックのメカニズムを解析した結果、マルチスレッドによるデッドロック以外に、信号処理関数によってもデッドロックが発生する可能性があることがわかりました。では、CGI のデッドロックはシグナル処理が原因なのでしょうか?その前に、一つ考えを紹介します。

関数の再入性とシグナルの安全性

関数の再入性とは、関数が何度入力されても、関数が正常に実行され、結果を返すことができることを意味します。では、スレッドセーフ関数はリエントラントなのでしょうか?答えは「ノー」です。 スレッドセーフ関数は、パブリック リソースに初めてアクセスするときにグローバル ロックを取得します。関数が実行されておらず、ロックも解除されていない場合、処理は中断されます。その後、割り込み処理関数で再度アクセスするとデッドロックが発生します。では、割り込み処理関数ではどのような関数にアクセスできるのでしょうか。 グローバル ロックを使用しない関数に加えて、使用できるシグナル セーフ システム コールもいくつかあります。他の非シグナルセーフ関数を呼び出すと、予期しない結果 (デッドロックなど) が発生します。 詳細については、マンシグナルを参照してください。デッドロックの原因を分析する前に、まずはCGIの実行プロセスを見て、デッドロックの可能性があるか分析してみましょう。

PHP-CGI 実行プロセス

Glibc の time 関数は、関数のスレッド安全性を確保するためにグローバル ロックを使用しますが、信号の安全性は保証されません。以前の分析の後、私たちは当初、デッドロックの原因は PHP-CGI プロセスがシグナルを受信し、シグナル ハンドルで非シグナル セーフ関数を実行したことが原因であると疑っていました。メインプロセスが中断される前に、glibc の time 関数が実行されます。関数で取得したロックが解除される前に割り込み処理に移行します。割り込み処理中に、glibc の time 関数がアクセスされます。これによりデッドロックが発生しました。

PHP-CGI の実行フローは次の図に示すとおりです。

さらなる分析により、デッドロックされたすべての CGI プロセスの sapi_global にエラー メッセージが記録されていることが判明しました。

「最大実行タイムアウト 60 秒を超えました。」

60 秒は、php-cgi で設定された実行タイムアウトです。そこで、cig が実行中にタイムアウト例外を生成し、longjmp によりシャットダウン プロセスに入ったことを確認しました。 glibc の時間関数はシャットダウン プロセス中にアクセスされます。デッドロックを引き起こした。

void zend_set_timeout(長い秒数)

{

TSRMLS_FETCH();

EG(timeout_秒) = 秒;

if( !秒) {

return;

}

……

setitimer(ITIMER_PROF, &t_r, NULL);

signal( SIGPROF, zend_timeout); // ここで zend 例外処理関数が呼び出されます

sigemptyset(&sigset);

sigaddset(&sigset, SIGPROF);

……

}

gdb デバッグにより、すべての PHP-CGI が zend_request_shutdown でブロックされていることがわかりました。 zend_request_shutdown は、ユーザー定義の PHP スクリプトに実装されたシャットダウン関数を呼び出します。 CGI がスーパーマーケットを実行すると、タイマーは SIGPROF 信号を生成して実行プロセスを中断します。この時点でたまたまスクリプトが time 関数を呼び出している状態で、ロック リソースがまだ解放されていない場合。次に、実行プロセスはタイムアウト関数に入り、引き続き zend_request_shutdown にジャンプします。このとき、カスタムシャットダウン関数で時刻関数にアクセスした場合。デッドロックが発生します。

register_shutdown_function ('SimpleWebSvc:: shutdown');

PHP コードでは qalarm システムを使用しており、qalarm システムは CGI の後に終了 (シャットダウン) します。このとき、CGI の実行が正常かどうかを解析するためのフック関数が挿入されます。正常に実行されていない場合は、アラーム メッセージが送信されます。たまたま、qalarm のアラーム処理関数で time 関数がアクセスされています。したがって、一定の確率でデッドロックが発生します。

結論

上記の分析により、CGI デッドロックの原因がわかりました。シグナル ハンドラー内でシグナル セーフではない関数が使用されており、デッドロックが発生していることがわかりました。

解決策

qalarm がシャットダウン時に登録するフック関数を削除または簡略化します。安全でない関数呼び出しを避けてください。

出典: http://www.v2gg.com/lady/shishangzixun/20140924/57266.html

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 Apr 03, 2025 am 12:04 AM

PHP開発における固体原理の適用には、次のものが含まれます。1。単一責任原則(SRP):各クラスは1つの機能のみを担当します。 2。オープンおよびクローズ原理(OCP):変更は、変更ではなく拡張によって達成されます。 3。Lischの代替原則(LSP):サブクラスは、プログラムの精度に影響を与えることなく、基本クラスを置き換えることができます。 4。インターフェイス分離原理(ISP):依存関係や未使用の方法を避けるために、細粒インターフェイスを使用します。 5。依存関係の反転原理(DIP):高レベルのモジュールと低レベルのモジュールは抽象化に依存し、依存関係噴射を通じて実装されます。

システムの再起動後にUnixSocketの権限を自動的に設定する方法は? システムの再起動後にUnixSocketの権限を自動的に設定する方法は? Mar 31, 2025 pm 11:54 PM

システムが再起動した後、UnixSocketの権限を自動的に設定する方法。システムが再起動するたびに、UnixSocketの許可を変更するために次のコマンドを実行する必要があります:sudo ...

PHPにおける後期静的結合の概念を説明します。 PHPにおける後期静的結合の概念を説明します。 Mar 21, 2025 pm 01:33 PM

記事では、PHP 5.3で導入されたPHPの後期静的結合(LSB)について説明し、より柔軟な継承を求める静的メソッドコールのランタイム解像度を可能にします。 LSBの実用的なアプリケーションと潜在的なパフォーマ

phpstormでCLIモードをデバッグする方法は? phpstormでCLIモードをデバッグする方法は? Apr 01, 2025 pm 02:57 PM

phpstormでCLIモードをデバッグする方法は? PHPStormで開発するときは、PHPをコマンドラインインターフェイス(CLI)モードでデバッグする必要がある場合があります。

PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? Apr 01, 2025 pm 03:12 PM

PHP開発でPHPのCurlライブラリを使用してJSONデータを送信すると、外部APIと対話する必要があることがよくあります。一般的な方法の1つは、Curlライブラリを使用して投稿を送信することです。

フレームワークセキュリティ機能:脆弱性から保護します。 フレームワークセキュリティ機能:脆弱性から保護します。 Mar 28, 2025 pm 05:11 PM

記事では、入力検証、認証、定期的な更新など、脆弱性から保護するためのフレームワークの重要なセキュリティ機能について説明します。

See all articles