digital matter

‘Windows’ タグのついている投稿

Windows版のPHP5.3がc0000005で強制終了する

Symfony 1.4.16をWindowsのPHP 5.3.9で実行したときに、特定の条件で強制終了する現象に悩まされていました。
主にSymfonyタスクでdoctrine:data-dumpなどを実行するときに落ちていました。

色々調べた結果、Symfonyに問題があるわけではなく、/lib/vendor/symfony/lib/config/sfDefineEnvironmentConfigHandler.class.phpがきっちり4096バイトだったということが原因でした。

つまり、PHP5.3.9では、4096バイトのファイルをrequireもしくはincludeするとc0000005(Access Violation)で強制終了します。CLIに限らず、Apache経由でも同じです。

試しに4096バイトの一切コードが書かれていないテキストファイルを作ってrequireしてみると、再現しました。

強制終了時のウィンドウと、内容は以下のとおり。

image

ちなみにモジュール名はnts(Non Thread Safe)版ならphp5.dll、ts(Thread Safe)版ならphp5ts.dllです。
どちらも確認しましたが、どちらも同じ現象です。モジュールは入っていても入っていなくても同じです。

問題の署名:
  問題イベント名:    APPCRASH
  アプリケーション名:    php.exe
  アプリケーションのバージョン:    5.3.9.0
  アプリケーションのタイムスタンプ:    4f0c5cd0
  障害モジュールの名前:    php5.dll
  障害モジュールのバージョン:    5.3.9.0
  障害モジュールのタイムスタンプ:    4f0c5dfb
  例外コード:    c0000005
  例外オフセット:    00090f5b
  OS バージョン:    6.1.7601.2.1.0.256.48
  ロケール ID:    1041
  追加情報 1:    0a9e
  追加情報 2:    0a9e372d3b4ad19135b953a78882e789
  追加情報 3:    0a9e
  追加情報 4:    0a9e372d3b4ad19135b953a78882e789

多分現象はこのバグ報告と同じだと思います。
PHP :: Bug #60758 :: require() crashes Apache

5.4.0RC5でも解決してないみたいですね。報告とほぼ同じですが、これで再現できます。

<?php
file_put_contents('test.txt', str_pad('', 4096));
include('./test.txt');

とりあえず対処法としては改行1文字でも増やしておけばいいってことですか…

関連する投稿

nginxのWindows版バイナリをビルドする

nginxのWindows版バイナリは公式で配布されていますが、nginxに追加のモジュールを入れたい場合、どうしても自分でビルドする必要がでてきます。

ビルド方法は公式のドキュメントに書かれています。

How to build nginx on the Win32 Platform with Visual C

が、色々ハマるのでメモしておきます。ビルド環境はWindows7 Professional x64です。

必要なのは以下。

  • Microsoft Visual C++ Compiler
  • Microsoft Windows SDK
  • MinGW/MSYS
  • ActivePerl
  • PCRE
  • zlib
  • OpenSSL

まず、VCコンパイラが必要なので、Microsoft Visual C++ Expressをインストールします。

Microsoft Visual Studio Express

上記ページのVisual C++ 2010 ExpressのWebインストールをクリックすればvc_web.exeがダウンロードできるので、それを実行してあとは言われるままにインストールすればOKです。

続いてMicrosoft Windows SDK(旧Platform SDK)をインストールします。

Windows SDK: Download the Windows SDK for Windows 7 and More | MSDN

「Install Now」を押せばインストールできます。こちらもそのままインストールすればOK。

OpenSSLのコンパイルにPerlが必要なので、ActivePerlをインストールします。32bit版と64bit版がありますが、僕は64bit版をインストールしました。

ActivePerl Downloads – Perl Binaries for Windows, Linux and Mac | ActiveState

続けてMinGW/MSYSのインストールをします。

MinGW – Minimalist GNU for Windows – Browse Files at SourceForge.net

「Looking for the latest version?」と書かれている隣のファイルをダウンロードします。

インストールが終わったら環境変数の設定をします。

MinGW Shellを起動して、パスを設定します。

$ export LIB="C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\lib;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib"
$ export INCLUDE="C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include"
$ export PATH="$PATH:/c/Perl64/bin:/c/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin:/c/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE:/c/Program Files/Microsoft SDKs/Windows/v7.1/Bin"

nginxのソースコードをダウンロードしましょう。tarボールで提供されているものには、Windows用のConfigureが入っていないらしいので、svnから取得します。

svnコマンドが使えるのであれば、
svn co svn://svn.nginx.org/tags/release-(バージョン番号)
でチェックアウトできます。僕はrelease-1.0.10を使いました。

なぜかTortoiseSVNではtags/release-1.0.10が表示できませんでした。

ダウンロードしたソースコードはMSYSのHOMEディレクトリに置きます。

C:\MinGW\msys\1.0\home\(ユーザー名)\nginx
としました。

PCRE、zlib、OpenSSLをダウンロードします。

PCRE – Browse /pcre at SourceForge.net

zlib Home Site

OpenSSL: Source, Tarballs

pcre-8.20.zip、zlib-1.2.5.tar.gz、openssl-1.0.0e.tar.gzをダウンロードしました。

nginxディレクトリの下にobjs/libディレクトリを作成します。ここに、先ほどダウンロードした3ファイルを解凍したものを設置します。

これで準備はできたので、ビルドします。

公式のビルド方法に載っているConfigureを実行します。が、PCREのバージョンは8.20になっていたので、–with-pcreの引数は変更します。あとは適宜合わせてください。

$ auto/configure –with-cc=cl –builddir=objs –prefix= \
–conf-path=conf/nginx.conf –pid-path=logs/nginx.pid \
–http-log-path=logs/access.log –error-log-path=logs/error.log \
–sbin-path=nginx.exe –http-client-body-temp-path=temp/client_body_temp \
–http-proxy-temp-path=temp/proxy_temp \
–http-fastcgi-temp-path=temp/fastcgi_temp \
–with-cc-opt=-DFD_SETSIZE=1024 –with-pcre=objs/lib/pcre-8.20 \
–with-zlib=objs/lib/zlib-1.2.5 –with-openssl=objs/lib/openssl-1.0.0e \
–with-select_module –with-http_ssl_module –with-ipv6

Configureが成功したら、nmakeでビルドします。

$ nmake -f objs/Makefile

これで、何も問題がなければnginx/objsディレクトリにnginx.exeファイルが出来上がっているはずです。

このnginx.exeファイルを、ひとつ上のディレクトリ(nginx)に設置して、

$ mkdir logs
$ mkdir temp

として、

$ start nginx.exe

で起動できます。

これでやっと追加モジュールをインストールできるというもの。

関連する投稿

今日の微妙エラー

コントロールはひとつの case ラベル (‘default:’) から別のラベルへ流れ落ちることはできません。

switch (message)
{
    case "hoge":
        funcA();
        break;
    default:
        funcB();
        break; // これがないとエラー
}

他の言語のクセでbreak書かなかったら起きた。

「フォールスルー」ってことなんですね。

ちなみにcaseのあとのブロックにコードを書かなければフォールスルーはできるという話。

関連する投稿

Pythonのwin32comからSilverlightを使おうと試みる

最終的にはPythonで書かれたWindowsアプリケーションで、Silverlightのコンテンツをロードしたいという目的なのですが、とりあえずSilverlightのActiveXコントロールを読み込んで動作を確認してみたいので色々実験。

まず、インストールされているSilverlightのバージョンを調べてみる。

Javascriptで書かれたコードがいくつか見つかったのでそれを書き直す。

以下はJS版。

var control = new ActiveXObject('AgControl.AgControl');
alert(control.IsVersionSupported('3.0'));

これをPythonで書いてみる。

import win32com.client
control = win32com.client.Dispatch("AgControl.AgControl")
print control.IsVersionSupported('3.0')

Silverlight 3がインストールされていればTrueが表示されます。

他にどんなメソッドが定義されているのかを調べるために、Visual StudioからAgControlを参照して、オブジェクトブラウザで調査。

というか、Silverlightのプラグインのリファレンスがあった。

Silverlight プラグインのオブジェクト リファレンス

が…Sourceを指定してもIsLoadedプロパティがTrueにならない…うーん…もう少し調べてみる。

関連する投稿

PythonでMIDI出力をしてみる

既存のPythonで作ったWindowsアプリケーションにMIDI出力を組み込む用事があったので、実験してみました。

参考サイトはこちら。

sulume blog» ブログアーカイブ » python で MIDI を使う

MIDIIO.dllというのはおーぷんMIDIぷろじぇくとで公開されているMIDIメッセージ入出力用ライブラリです。

これもダウンロードして、pyファイルと同じ場所に置いておきます。

で、ソースコードはこちら。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

c_mess = ctypes.create_string_buffer(3)
c_mess.value = '\x90\x3C\x64'

midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)

time.sleep(3)

midiiolib.MIDIOut_Close(midiout)

説明することもあまりないですが、8行目のMIDIOut_GetDeviceNameで、MIDI出力の先頭のデバイスの名前を先に取得します。

で、その名前を使ってMIDIOut_Openで出力デバイスを開きます。

11~12行目ではノートを作成します。とりあえずドの音でも鳴らしておきます。この辺もMIDIIO.dllに入っていたドキュメントのサンプルと同じ。

あとはMIDIOut_PutMIDIMessageで出力するだけです。

ちゃんと閉じておかないと、次回音が鳴らなかったりする(オープンに失敗します)ので、MIDIOut_Closeで閉じておきましょう。

実験として、ちょっと長いデータを指定してみる。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

notes = ['\x90\x3C\x64',
         '\x90\x3E\x64',
         '\x90\x40\x64',
         '\x90\x41\x64',
         '\x90\x43\x64',
         '\x90\x45\x64',
         '\x90\x47\x64',
         '\x90\x48\x64']

c_mess = ctypes.create_string_buffer(3)

for note in notes:
    c_mess.value = note

    midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)
    time.sleep(0.5)

time.sleep(1.0)

midiiolib.MIDIOut_Close(midiout)

和音を鳴らしてみるテスト。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

notes = ['\x90\x3C\x64',
         '\x90\x40\x64',
         '\x90\x43\x64']

c_mess = ctypes.create_string_buffer(3)

for note in notes:
    c_mess.value = note

    midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)

time.sleep(3.0)

midiiolib.MIDIOut_Close(midiout)

とりあえずこれだけできれば満足なので終了。

関連する投稿

ネットワークドライブからデータを全部バックアップする

TeraStationのHDDが1台故障したので、交換を前に中身を全部バックアップする必要がありました。

ちなみに以前同じような症状でRAID崩壊させたことがあるので今回は慎重に…

共有フォルダのルートがたくさんあるので、それをいかに簡単にコピーするかがキモ。

共有フォルダ自体はコピーしようとドラッグアンドドロップすると、ショートカットが作られてしまう。

やりたいことは、PCを使ってLAN内のNASからデータを全部コピーして、ローカルに接続してあるUSB HDDにバックアップすること。

で、robocopyコマンドというのが便利っぽいので使ってみた。使ったOSはWindows Vista。標準コマンド?

まずは対象のフォルダ名一覧の取得から。

C:\> net view \\NAS

みたいにすると、フォルダ一覧が文字情報として取れます。

で、robocopy。

robocopyでフォルダをバックアップ/同期させる - @IT

どうやらrsyncみたいに使えるよう。

C:\> robocopy /mir \\NAS\dir1 C:\Backup\dir1

という感じで書けば対象ディレクトリの中身をミラーリングコピーしてくれます。

ちなみに受け側ディレクトリは作っておかなくても勝手に作ってくれます。

というわけで、先ほどのnet viewの結果を流し込んだコマンドリストを作ってbatファイルに保存して、実行。

全部きれいにバックアップできました。

今xcopyって推奨されてないんですね。知らなかった。

関連する投稿

NSISから使える、起動中のプロセスを削除するプラグイン

常駐アプリケーションを作ったはいいが、アンインストールしようとしたときにプロセスが起動していると、削除できなくて困る。

というわけで、プロセスを殺す目的のプラグインDLLを作成。コンパイル済みファイルはエントリの最後に。

taskkillコマンド使えという話ですが、Windows XP Home Editionにはtaskkillコマンドが含まれていないので。

今回もさっくりC#で。C#.NETで作ってしまうと、そのままではNSISで使えないのだけど、.NETで作ったDLLをNSISのプラグインとして使う方法は以下のエントリを参照。

NSISで、C#で書かれた自作のDLLを使う : blog.loadlimit – digital matter -

ソースは以下。C#でクラスライブラリとしてプロジェクトを作成。プロセス名を指定すると、マッチしたプロセスを全部終了してくれます。

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TaskKill
{
    public class TaskKill
    {
        [DllImport("Psapi.dll", SetLastError = true)]
        static extern bool EnumProcesses(
           [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] UInt32[] processIds,
             UInt32 arraySizeBytes,
             [MarshalAs(UnmanagedType.U4)] out UInt32 bytesCopied
          );

        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
           uint dwProcessId);

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);

        [StructLayout(LayoutKind.Sequential)]
        public struct StringBuffer
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string text;
        }

        [DllImport("psapi.dll")]
        private static extern bool EnumProcessModules(IntPtr hProcess, out IntPtr lphModule, int cb, out int lpcbNeeded);
        [DllImport("psapi.dll")]
        private static extern int GetModuleBaseName(IntPtr hProcess, IntPtr hModule, out StringBuffer lpBaseName, int nSize);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool TerminateProcess(IntPtr hProcess, int uExitCode);

        public static void KillByName(string pname)
        {

            UInt32 arraySize = 1024;
            UInt32 arrayBytesSize = arraySize * sizeof(UInt32);
            UInt32[] processIds = new UInt32[arraySize];
            UInt32 bytesCopied;

            bool success = EnumProcesses(processIds, arrayBytesSize, out bytesCopied);

            if (!success)
            {
                return;
            }
            if (0 == bytesCopied)
            {
                return;
            }

            UInt32 numIdsCopied = bytesCopied >> 2;

            if (0 != (bytesCopied & 3))
            {
                UInt32 partialDwordBytes = bytesCopied & 3;

                return;
            }

            for (UInt32 index = 0; index < numIdsCopied; index++)
            {
                IntPtr hProcess = OpenProcess(
                    ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead | ProcessAccessFlags.Terminate,
                    false,processIds[index]);
                if (hProcess.ToInt32() != 0)
                {
                    IntPtr hMod = IntPtr.Zero;
                    int cbNeeded;
                    StringBuffer szProcessName;
                    szProcessName.text = "<unknown>";

                    if (EnumProcessModules(hProcess, out hMod, Marshal.SizeOf(hMod), out cbNeeded))
                    {
                        GetModuleBaseName(hProcess, hMod, out szProcessName, Marshal.SizeOf(szProcessName));
                    }

                    if (szProcessName.text == pname)
                    {
                        TerminateProcess(hProcess, -1);
                    }

                    CloseHandle(hProcess);
                }
            }

        }

    }
}

で、これをNSISの配布ファイルに含めておいて、

; アンインストーラ
Section "Uninstall"
  ; アンインストールで使用するプラグインの準備
  InitPluginsDir
  SetOutPath $PLUGINSDIR
  File "TaskKill.dll"

  ; hogehoge.exeが起動していたら、それを落とす
  CLR::Call /NOUNLOAD "TaskKill.dll" "TaskKill.TaskKill" "KillByName" 1 "hogehoge.exe"

  ; インストールしたファイル群削除
  Delete $INSTDIR\*.*

  CLR::Destroy
SectionEnd

という感じでnsiファイルを記述。

ファイルは下記リンクからダウンロードしてお使いください。

download TaskKill.dll

関連する投稿

スクリーンキーボード

Vistaでソフトウェアキーボードというか、スクリーンキーボードを作ろうとしてハマったのでメモ。ただし、結局解決には至っていません。アプローチ変えてしまったので。

スクリーンキーボードを作るにあたって検索すると、imm32関連の関数を使ったサンプルが諸々出てくるのだけど、どうやらこの関数がWindows XPまでのもので、Vista以降はTSF(Text Services Framework)というものに置き換わっているらしい。

これに気づかず、

IntPtr hIMC = ImmGetContext(AHwnd);
IntPtr hKL = GetKeyboardLayout(0);
int dwSize = ImmGetConversionList(hKL, hIMC, AText, IntPtr.Zero, 0, GCL_CONVERSION);

とかやっていたのだけど、ImmGetConversionListの結果が必ず0になってしまう。

imm32 を使ったプログラムの互換性について

試してないけど、TSFのドキュメントは以下。

Text Services Framework Reference (Windows)

で、ここまでわかったところで、結局Linuxでやることになりました。

関連する投稿

マウスを動かしただけでCPU使用率が100%に行く現象

Windowsを使っていると、だんだんと重くなってきて、マウスもガクガク飛ぶようになった。うーん?以前はこんなことなかったけどなぁと思って原因究明に乗り出すことに。

使用OSはWindows Vista Ultimate 32bit。半日使ってると重くなってきて、1日経つとまともにブラウザも扱えない。

Core2Quadでメモリ4GBな上、ブラウザしか起動していなくても遅いので、マシンスペック云々ではないことを先に断っておきます。

まぁ、結論から言うとDisplayLink製のUSBモニタが問題でした。というか、それに付随するアプリケーションとサービスか。当該のプロセスは以下の3つ。

  • DisplayLinkUI.exe
  • DisplayLinkService.exe
  • DisplayLinkManager.exe

ServiceとManagerは全ユーザのプロセスを表示で、管理権限にならないと削除できないので注意。

3つ落としてやったら途端に快適な環境が復活しました。これ単体ではさほどCPU食ったりしないので、意外と気づきにくいかも?ちなみに使ってるUSBモニタはSAMSUNGのSyncMaster U70。

OS起動時に2回に1回ブルースクリーンになったり、色々あやしさは感じていたのだけど、ドライバの出来が良くないなぁ…USBサブモニタ流行ってるから、同じような現象が大量発生しているんじゃないかと不安だわ。

調べてみたら、バージョンは4.6.17952.0。付属のCDから一度バージョンアップしてます。

今見たら新しいメジャーバージョン(5.1)出てたので試してみます。この分野は可能性感じるし、U70自体は結構気に入ってるので、早々に安定してくれることを期待。

ダウンロードはこちらから。

DisplayLink: DisplayLink: Windows Drivers

ウィルスバスター2009とか疑ってすまんかった。同じような現象に悩まされている人の一助になれば幸いです。

追記

5.1にしたら遅くなる現象は直った模様。USBモニタ上でのマウスポインタの動作が遅くなったけど、別にクリティカルじゃないのでOK。

関連する投稿

Photoshopの強制終了と対応

Photoshop CS3を起動しようとしたら、起動スプラッシュ表示中に突然強制終了する現象に見舞われた。

同じPCに入っているCS2もダメ。

スプラッシュの文字を追っていくと、どうやら「TWAIN メニュー項目を作成」というところで止まっているようだ。

うーん、最近何か入れた覚えはないけどなぁ…

とりあえず検索すると

TWAIN プラグインの読み込み中にアプリケーションが終了する(Photoshop Elements 4.0/5.0/Photoshop CS2/CS3)

これらしい。

原因となるドライバが不明なので、TWAINプラグイン自体外すことにした。説明の通りにプラグインのファイル名の先頭に「~(チルダ)」をつけるだけでOK。

会社で使ってるPCだからTWAIN経由ではスキャンしないしね。

で、思ったのは、AdobeのTechNoteに大抵の問題は情報があるらしいということ。

Photoshop他Adobe製品で起動しないとかの対応方法を探すには、ちゃんと正確にどこで止まったかを調べないといけないってことですな。基本だけど。「Photoshop 強制終了」とかで探すとハマるよ!

関連する投稿