0

UNIXソケットをポーリングするために単一のスレッドをディスパッチしようとすると、奇妙な動作に気づきます。osx 10.6.8でコードをテストすると、コードがクラッシュし、複数のスレッドがコードを実行しているのがわかります。奇妙なことに、osx 10.7.5では、クラッシュすると、1つのスレッドでしか実行されないことがわかります。

私のAppDelegateでは、次のようにスレッドをディスパッチします(1回):

[pp performSelectorInBackground:@selector(runloop) withObject:nil];

ppはMyIPCクラスのインスタンスです。

私のIPCクラスでは、runloopはいくつかのCコードのラッパーです。

@implementation IPC
-(void) runloop
{
  ipc_busy = 0;
  unixsocket_runloop();
}

runloopは、(ランタイムごとに)単一の接続を待機することを目的としています。次に、ハンドラーは、プログラムが終了するまでパケットを待機します。Cコードは次のようになります-

/**
 * Waits for a connection and dispatches the socket handler
 * No need to fork since we will only ever have a single connection per program launch
 */
int unixsocket_runloop()
{
  int connection_fd;
  socklen_t address_length;
  while((connection_fd = accept(socket_fd,
                                (struct sockaddr *) &address,
                                &address_length)) > -1)
  {
    return unixsocket_handler(connection_fd);
  }
  return 0; // for posterity
}

これは接続ハンドラーです-

/**
 * Handles the connection from the client
 * loops infinitely and reads from the socket when there is a message
 * Stores message into a ring buffer of buffers
 */
int unixsocket_handler(int connection_fd)
{
  size_t nbytes;
  char readbuffer[USBUFSIZE];
  bzero(readbuffer,USBUFSIZE);
  while((nbytes = read(connection_fd, readbuffer, USBUFSIZE)))
  {
    // store in buffer
    bufPut(readbuffer,nbytes);
    bzero(readbuffer,USBUFSIZE);
  }
  close(connection_fd);
  return 0;
}

スタックトレースでは、このunixsocket_runloopが2つのスレッドで発生していることがわかります。これがクラッシュの根本的な原因であるとは思いませんが、対処したい予期しない動作です。

私が独自のソケットクラスを使用した唯一の理由は、オープンソースコミュニティで見られるオプションの多くがTCPにハードワイヤードされていることでした。特に魅力的なcocoaAsyncSocketクラス。

4

0 に答える 0