• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:ジョブの切り離し)

ジョブの切り離し

hjoshuaの回答

  • ベストアンサー
  • hjoshua
  • ベストアンサー率66% (6/9)
回答No.1

全体の構造が詳しく分からないので、ひょっとすると見当違いかも知れませんが、私の経験から幾つかのアドバイスをしましょう。 まず、親プロセスでwaitを使わないときには、子プロセスからの終了シグナルを処理しない、と明言しておかないといけません。子プロセスは終了するときに、親プロセスがシグナルを受け取ったかどうかをチェックしていて、受け取るまでゾンビプロセスになって、残っていきます。もちろん親プロセスが終了してしまうと、このプロセスも消えますが.....。終了シグナルを処理しない、という名言は、Solaris では、sigignore(SIGCHLD) というのがあります。他のUNIX系でも似たようなシステムコールあるいは、シグナルが存在するでしょう。 ただ、上記の問題は直接はクライアント側のロックにはつながらないかも知れません。ただ、以下の理由と組み合わさると、ファイルディスクリプタがゾンビに残り続けるということも起こらないやもしれません。 もう一つ、fork, execをやる場合、ソケットなど、様々なファイルディスクリプタの情報が、子プロセスに受け継がれます。受け継がれたあと、親プロセスでソケットを閉じたとしても、子プロセスに残っているので、クライアントではソケットはつながりっぱなしです。子プロセスから孫プロセスへ受け継いでいけば、どんどんディスクリプタはコピーされるわけで、問題は波及していきます。これを解決するのは単純で、forkのあと、子プロセス側で、必要のないファイルディスクリプタは閉じます。そのあとexecするという処理が必要です。

lily02
質問者

お礼

ありがとうございます。 もともとこのソフトは、クライアント(MS-DOS)とサーバ(UNIX)で作られていたものを、できるだけサーバのソフトをそのまま生かす形でクライアントのソフトだけ作り変えています。サーバ側のソフトは私が作ったものではなく、UNIXシステムプログラミングに不慣れなこともあり、fork・exec・wait・signalのあたりを今勉強しているところです。 「fork, execをやる場合、ソケットなど、様々なファイルディスクリプタの情報が、子プロセスに受け継がれます。受け継がれたあと、親プロセスでソケットを閉じたとしても、子プロセスに残っているので、クライアントではソケットはつながりっぱなしです。」というのはまさにその通りですね。子プロセス・孫プロセスで次々とディスクリプタはコピーされるのですね。ここを見直してみます。 本当に詳しいアドバイスをしていただきありがとうございます。

lily02
質問者

補足

今日仕事先でアドバイスしていただいたことを試してみました。  1.sigignore(SIGCHLD) の記述  2.子プロセスでソケットディスクリプタを閉じてexitする サーバ側では、データの受信(子プロセス)のあとデータ解析と印刷は孫プロセスがやっています。データを受信してしまったらソケットを切断してもいいので、子プロセスの終了時にソケットディスクリプタを閉じました。結果は残念ながらこれまでと同じくデータ解析等処理の終了までクライアントに切断のイベントは発生しません。ファイルのopen・closeは各プロセス内でやっているので他に閉じるディスクリプタは見当たりませんし。 申し訳ありませんが、まだほかに思い当たることがありましたらお教えください。 よろしくお願いいたします。

関連するQ&A

  • Socket通信で、通信終了のイベントが発生しない

    クライアント(Windows)とサーバ(Unix)とSocket通信をするアプリを作っています。処理内容はクライアントのデータファイルをサーバに送信(アップデイト)し、サーバ側でデータを解析し、その結果を印刷するという手順です。 WinSockを使って、送信そのものはうまくいくのですが、サーバでデータを解析し結果を印刷するのに時間がかかり(10秒以上)、その間は送信終了のイベントが発生しません。これはサーバ側での処理を exec関数とwait関数で行っているので、正しい事態なのですが、データの送信が終わったら後はサーバ側で勝手にやって欲しいのです。サーバでの処理を system関数に置換えたり、バックグランド処理にしてもやはり処理が終わるまで送信終了のイベントが発生しません。何かいい方法をお教えください。

  • C#でソケット通信

    初歩的な質問ですみません。 クラアント側とサーバー側にそれぞれC#で作ったプログラムをインストールし、 クライアントからサーバーにデータを繰り返し送信したいとき、 そのプログラム内でソケット接続して送ることはできるでしょうか? できるとして、どのような手順でソケット接続し、データを送ればいいのでしょうか? まったくの初心者です。 よろしくお願いします。

  • サーバプロセスとクライアントプロセスの通信

    サーバプロセスとクライアントプロセスの通信がどのように行われているのか確認させてください。 現在、以下の認識でいます。 (1)TCPコネクション  サーバ側ポート番号【23】と、それぞれのクライアント側ポート番号【****】との間に確立する。   (2)通信処理  クライアント側のプロセスAは、サーバ側のプロセスA(子)  クライアント側のプロセスBは、サーバ側のプロセスB(子)  クライアント側のプロセスCは、サーバ側のプロセスC(子)  との間で通信を行う。 ※添付の図も参照ください。 認識に相違ないでしょうか。 サーバプロセスとクライアントプロセスの通信を行う際、プロセス間(ポート間?)の通信には、IPアドレスとポート番号を組み合わせたソケットを用いるため、サーバ側ではソケット【192.168.0.1:23】を1個作成し、クライアント側ではソケット【192.168.0.2:****】をプロセス分作成すると考えています。 このとき、クライアントプロセスAはサーバプロセスA(子)と通信を行いますが、サーバ側で作成されているソケットは1つであるため、どの子プロセスに対してデータをせばいいのか判別できないのではないかと考えています。 ※クライアントプロセス(A、B、C)はソケット(サーバ側)【192.168.0.1:23】に対して送信されるため。 上記について、何らかの仕組みがあるのでしょうか。 よろしくお願いします。

  • ソケットでのデータ送受信について教えてください

    はじめまして。 Perlでのソケット通信プログラムで質問があります。 現在ソケットで通信を行うテストプログラムを作っているのですが、 クライアントからサーバへの片方向送信は出来るのですが、 クライアントからデータ受信後、サーバからクライアントへ応答を 返す処理が上手くいきません。 私としては、クライアントとサーバの処理を逆にすればよいだけかな と思っているのですが認識違いでしょうか? 宜しくお願いします。 環境 OS:Linux 言語:Perl5.8 ■上手くいく場合(かなり省略します。ポイントだけ) サーバ側 $client=accept(C_SOCKET, P_SOCKET); while(<C_SOCKET>){ printf("%s",$_); #受信データ } クライアント側 socket (SOCKET, PF_INET, SOCK_STREAM, 0); connect(SOCKET, pack_sockaddr_in(9000,$ipaddr_bin)); print SOCKET "Test Data!!\n"; →サーバ側端末にTest Data!!と表示 ■送受信しようとしてダメなもの サーバ側 $client=accept(C_SOCKET, P_SOCKET); while(<C_SOCKET>){ printf("%s",$_); #受信データ } print C_SOCKET "Return Data!!\n"; クライアント側 socket (SOCKET, PF_INET, SOCK_STREAM, 0); connect(SOCKET, pack_sockaddr_in(9000,$ipaddr_bin)); print SOCKET "Test Data!!\n"; while(<SOCKET>){ printf("%s",$_); #応答データ } →サーバ側にはTest Data!!すら表示されない。  もちろんクライアント側にも。

    • ベストアンサー
    • Perl
  • SocketのSend関数でのCLOSEの検知 [Linux]

    Linux環境でSocket(dm:PF_INET,type:SOCK_STREAM)を使用しての、 Client&ServerプログラムをCで作成しているのですが、 そこでのSend関数の使い方についてご助力ください。 Client&Serverプログラムは下記のような動きをします。 [Client] ServerへConnectした後、複数のDataを数秒間隔でServerへ 送信(send関数使用)します。受信(recvやread関数等)は、 一切行いません。 [Server] ClientからのConnectを受け付けた後、Clientから受信(recv関数 使用)したDataを標準出力へ表示する。送信(sendやwrite関数 等)は、一切行いません。 さて、ここでもしClientプログラムがCloseを発行したり、マシン DOWN等の理由でConnectionが切断され、Server側のSocketが CLOSE_WAIT状態になった場合、Bufferに溜まっていたDataを すべて受けきった後、recv関数が0を返してくれるので 相手が終了したことがわかります。 ここからが質問のMainです。 では、もしServerプログラムがCloseを発行したり、マシン DOWN等の理由でConnectionが切断され、Client側のSocketが CLOSE_WAIT状態になっても、CLOSE_WAIT直後のsend関数が なぜか正常に処理されてしまいます。無論このDataは、 Server側は受け取りません。この次のsend関数実行時に EPIPEが返ってくるので、ここでようやくSocketが切断された ことが判ります。 これを何とかCLOSE_WAIT状態になった直後から、send関数で 切断を検知できるようにできないでしょうか。 よろしくお願いします。 以上

  • HTTPサーバプログラム

    C言語でHTTPサーバを作ろうとしています。 大方動くのですが、Java Applet(Jarファイル)を埋め込んだWebページをクライアント側のブラウザに表示させようとすると、エラー(ClassNotFoundError)が発生してしまいます。 ※GIFファイルなどの表示はうまく動いています。 パケットキャプチャソフトなどを活用して色々調べてみると、サーバ側からクライアント側へJarデータを送信する処理が上手く動いていないようです。 今のHTTPサーバの制約で、データ送信関数で一度に送信できるサイズが32KB程度になっています。 Jarファイルがこの最大サイズ(32KB)以下であれば問題なくクライアント側でJava Appletが起動するのですが、このサイズを超えるJarファイルの場合に先のエラーが発生してしまいます。 ※例えばJarファイルサイズが50KBの場合は、データ送信関数を2度呼び出す処理になります(1回目は32KB送信、2回目は残りの18KBを送信します)。 パケットキャプチャソフトでデータの流れを確認すると、50KBのJarファイル・データはクライアント側へちゃんと送信されているように見えるのですが、Jarファイル・データがクライアント側へ送信された後、(恐らく、クライアント側でJarファイルが正しく受信されなかったと認識されているため)クライアント側はClassファイルをサーバ側へリクエストしに行っています。 ※<applet archive="test.jar" code="test.class">としている場合は、"test.jar"ファイルのデータ送信後、クライアント側から"test.class"をサーバ側へリクエストしに行っています。 50KB程度のGIFファイルなどは、分割送信処理を用いてちゃんとクライアント側のブラウザで表示できているのですが…Jarファイルはなぜ上手くいかないのか分かりません。 Jarファイル・データ送信時には何か特別な制約があるのでしょうか? どなたか詳しい方がおられましたらお教えいただきたく存じます。

  • ソケット通信のシミュレータツールについて

    ソケット通信を使用したクライアント機能のテストを行うために、サーバ側を シミュレートするツールを探しています。 必要なツールの条件は、 『クライアント側から送信された電文をそのままの内容で自動で返す』 シミュレータです。 クライアントの送信データの中で動的にインクリメントしている番号があり、 サーバ側ではその番号をそのまま返す必要があるためです。 クライアントからの電文送信量も多いため、ツールの機能として、受信したデータに 対して折り返しのデータを事前に指定しておくというものではなく、 単純に同一データを自動で折り返すというものが望ましいのですが・・・。 どなたか良いツールをご存知ないでしょうか?

  • VC6.0ソケット通信プログラムについて

    お世話になります。 VC6.0でソケット通信の社内の既存のプログラムを改善しております。 クライアントより、サーバにソケットで大量に電文を送信した時に、サーバ側の処理が重くなってしまいます。 NETSTATコマンドで確認したところ、 サーバ側では、CLOSE_WAITが大量に出力されており クライアント側では、FIN_WAIT_2が大量に出力されます。 クライアント側のFIN_WAIT_2は、時間が経つと消えるのですが、サーバ側のCLOSE_WAITは残ってしまっております。 サーバ側のEXEを再起動すると、CLOSE_WAITは消えます。 サーバ側のソケットの受信後の処理に問題があるのではと考えておりますが、何処が問題なのかわからない状態です。 コードを以下に記述致します。 WINAPI K010cListener{ /*Winsock初期化*/ WSAStartup(wVersionRequested,&wsaData); /*SOCKET作成*/ fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP) /*ポートの設定*/ addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = AF_INET; addr.sin_port = htons(usPortNo); addrlen = sizeof(addr); /*BIND*/ bind(fd,(struct sockaddr*)&addr,addrlen) /*LISTEN*/ listen(fd,0) while(1){ /*ACCEPT*/ fd2 = accept(fd,(struct sockaddr*)&addr,&addrlen) //データ受信 waitReceiveThread(fd2, &rcv_msg); //DBオープン ConnectDB() //DB登録 AddTable(&rcv_msg) //DBクローズ CloseDB() } /*Winsock終了*/ WSACleanup(); } void waitReceiveThread(SOCKET fd, SockRcvMsg *rcv_msg) { while (1) { /*データ受信待ち*/ rcvSize = recv(fd,rcvBuf,sizeof(rcvBuf),0); if (rcvSize <= 0) { continue; } else { /* 返信電文の準備 */ memset(sndBuf,0x20,sizeof(sndBuf)); memcpy(sndBuf ,"RCMORDER00004800000000",22); /* 返信電文の送信 */ send(fd,(char*)sndBuf,sizeof(sndBuf),0); /* バッファの初期化 */ bufsize=0; memset(buf,'\0',sizeof(buf)); break; /*ループを抜ける*/ } } } 恐れ入りますが、ご教授いただければ幸いです。 宜しくお願い申し上げます。

  • VBからサーバ上のAccess mdbにアクセスする方式について

    クライアントのVBアプリからサーバ上のAccess mdbにアクセスしたいのですが、 データベースがAccessの場合、データを丸ごとクライアント側に持ってきて、クライアント処理になってしまうと聞きました。 サーバ上でデータセットを作成してクライアントに渡す方法があれば教えてください。 よろしくお願いします。

  • socketプログラミングについて

    C++でsocketの練習のためにソケットを開き、文字列の送信を行うだけのサーバクライアントプログラムを作成したのですが、どうも上手く動作してくれません。 クライアント→サーバへ文字列を送信する前に、 1.サーバがソケットを開き、9999ポートでアクセスを待つ 2.クライアントがソケットを作成し、サーバの9999ポートにアクセスする 3.クライアントが文字列をサーバへ送信し、サーバが文字列を表示 ということをしたいのですが、2の部分でつまずいています。 プログラムをネットワークに接続されているコンピュータ上で実行すると動作するのですが、(client 192.168.15.17 9999)単独でサーバ・クライアントを起動させ、localhost当てに接続(client localhost 9999)しようとしても「No route to host」と表示されて、接続すら出来ません。 ためしにサーバを起動させている状態で「telnet localhost 9999」とするとどうやらサーバに接続されているようです。 localhostでやる場合は特別なソケット操作が必要になるのでしょうか?