2012.01.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

MHI 5.0

この「にっき」には暴力シーンやグロテスクな表現が含まれています。

(2012.01.29)

$ [NYAOS] ×で閉じた時に signal でキャッチできたらいいんだけど

@nocd5
※これは決して要望ではありません。 nyaosで諦めてる事 -- ・^zからのbg ・ckw+nyaosで×で閉じた時のsavehis←ckwをゴニョゴニョしたらいけるかも

(要望ではないことを承知で) やり方が分かれば、実現させるんだけどなー。 特に×で閉じた時に signal とかでキャッチできたらいいんだけど

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>

void dying_message(int foo)
{
    FILE *fp=fopen("dying_message.txt","w");
    if( fp != NULL ){
        fputs("signaled!\n",fp);
        fclose(fp);
    }
}
void dying_message2(void)
{
    dying_message(0);
}

int main()
{
    signal( SIGINT , dying_message );
    signal( SIGBREAK , dying_message );
    signal( SIGABRT , dying_message );
    signal( SIGTERM , dying_message );
    atexit(dying_message2);
    Sleep(100000);
}

これを動かして、コマンドプロンプトを閉じても、 ファイル「dying_message.txt」は作成されていない。

つーか、tasklist コマンドで見ると、 コマンドは別に止まっておらず、普通に動いているので、 「taskkill /f /pid PID」で停止させなきゃいけない。

どうすればいいんでしょうねぇ。うーむ。

$ [NYAOS] 試してみたけれど、何故かエラーになる

@lpproj
@zetamatta 一応それらしいAPI(SetConsoleCtrlHandler)はあるっぽいですが、試したことはないです… msdn.microsoft.com/ja-jp/library/…

試してみました。

[c:hayama]
$ type foo.c
#include <stdio.h>
#include <windows.h>

BOOL WINAPI HandleRoutine( DWORD dwCtrlType )
{
    FILE *fp;
    switch( dwCtrlType ){
    case CTRL_CLOSE_EVENT:
    case CTRL_LOGOFF_EVENT:
    case CTRL_SHUTDOWN_EVENT:
        fp=fopen("dying_message.txt","w");
        if( fp != NULL ){
            fputs("犯人はヤス\n",fp);
            fclose(fp);
        }
        break;
    default:
        break;
    }
    return TRUE;
}

int main()
{
    BOOL rc=SetConsoleCtrlHandler( HandleRoutine , TRUE );
    printf( "SetConsoleCtrlHandler=[%d]\n" , rc );
    if( rc == 0 ){
        Sleep( 100000 );
    }else{
        printf("GetLastError=[%d]\n",GetLastError());
    }
    return 0;
}
[c:hayama]
$ a
SetConsoleCtrlHandler=[1]
GetLastError=[126]

何故かエラーになりました(SetConsoleCtrlHandler が 1 で返ってきた)。 なんでだろう。初期化か、何か、いるのかなぁ…

$ [NYAOS] うまくいったお

通りすがりの齊藤さん
関数が成功すると、0 以外の値が返ります。 なので 1 がかえってきてるのは成功です。 rc!=0 に変更してみたところ、私の環境ではハンドラが呼ばれるのですが…。

うっかりしてました。仕様書 を読んでみたところ、確かに「関数が成功すると、0 以外の値が返ります」とありました。 これを元に修正してみたところ、確かにうまくいきました。

ハンドラが呼ばれなかったのは、ターミナルが ckw のためだったようです。 コマンドプロンプトから実行してみると、 「このプログラムは応答がありません」的なダイアログがちゃんと出ました。 そこでハンドラの中で ExitProcess 関数を呼び出してみると、 スムーズに終了し、ちゃんとダイイングメッセージが呼ばれました。

これが ckw の場合、ダイアログもでず、ウインドウが閉じるのですが、 裏でしっかりプロセスが稼働したままになっています。 ここは ckw の側での対応が必要のようです。だれかー!

通りすがりの齊藤さん SetConsoleCtrlHandler でどうですかね。 (2012/01/29 21:05:34)

はやま ありがとうございます。やってみましたが、何故かエラーになりました。エラーを無視して実行しても、ハンドル関数がよばれていないようです。いったい何が悪いのやら… (2012/01/29 21:55:00)

通りすがりの齊藤さん 関数が成功すると、0 以外の値が返ります。 なので 1 がかえってきてるのは成功です。 rc!=0 に変更してみたところ、私の環境ではハンドラが呼ばれるのですが…。 (2012/01/29 22:47:52)

はやま あ、ほんとですね。仕様書を読み間違えていました。ありがとうございます! (2012/01/29 22:55:54)

通りすがりの齊藤さん 親プロセスの終了イベントを監視すれば大丈夫だと思うのですが、コンソールアプリでイベントを受け取るには専用のスレッドを作らざるを得ないので、それだけのためにスレッドを作るのもなぁという気はしますね。 CTRL+C の監視も内部的にはスレッドが作られているらしいですけど。 (2012/01/30 12:50:59)

(2012.01.28) | (2012.01.30)

.net(3) C++(3) Cygwin(12) GAME(3) Groovy(1) Linux(2) Lua(39) Mercurial(13) NYAOS(92) OS/2(7) Oracle(3) Perl(4) Python(22) SKK(4) Windows8(1) album(68) ckw(10) coLinux(1) vim(6) wifky(27) 書評(21) (9)

zetamattaのたいじゅー