linxpsoft / delphi-iocp-framework

Automatically exported from code.google.com/p/delphi-iocp-framework
0 stars 0 forks source link

Resource Leak #13

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
At Iocp.TcpSocket.Pas, the TIocpTcpSocket.Listen function may cause resource 
leak, when WSASocket or bind or Iocp.Winsock2.listen or 
AssociateSocketWithCompletionPort return is failed.

May Change as:

function TIocpTcpSocket.Listen(const Host: string; Port: Word; InitAcceptNum: 
Integer): Boolean;
const
  IPV6_V6ONLY = 27;
var
  PHost: PWideChar;
  ListenSocket: TSocket;
  InAddrInfo: TAddrInfoW;
  POutAddrInfo, Ptr: PAddrInfoW;
  ListenCount: Integer;
  LastErr: Integer;
  SocketList:TList<TSocket>;
begin
  Result := False;
  if not Assigned(FAcceptThread) then Exit;  

  try
    // 如果传递了一个有效地址则监听该地址
    // 否则监听所有本地地址
    if (Host = '') then
      PHost := nil
    else
      PHost := PWideChar(Host);

    FillChar(InAddrInfo, SizeOf(TAddrInfoW), 0);
    InAddrInfo.ai_flags := AI_PASSIVE;
    InAddrInfo.ai_family := AF_UNSPEC;
    InAddrInfo.ai_socktype := SOCK_STREAM;
    InAddrInfo.ai_protocol := IPPROTO_TCP;
    if (getaddrinfo(PHost, PWideChar(IntToStr(Port)), @InAddrInfo, @POutAddrInfo) <> 0) then
    begin
      LastErr := WSAGetLastError;
      AppendLog('%s.Listen.getaddrinfo, ERROR %d=%s', [ClassName, LastErr, SysErrorMessage(LastErr)], ltWarning);
      Exit;
    end;

        SocketList:=TList<TSocket>.Create;
        try
        try
          {$region '检查监听个数是否已达上限'}
          Ptr := POutAddrInfo;
          ListenCount := FAcceptThread.ListenCount;
          while (Ptr <> nil) do
          begin
            Inc(ListenCount);
            Ptr := Ptr.ai_next;
          end;
          if (ListenCount > FAcceptThread.MAX_LISTEN_SOCKETS) then Exit;
          {$endregion}

            Ptr := POutAddrInfo;  
          while (Ptr <> nil) do
          begin
            ListenSocket := WSASocket(Ptr.ai_family, Ptr.ai_socktype, Ptr.ai_protocol, nil, 0, WSA_FLAG_OVERLAPPED);
            if (ListenSocket = INVALID_SOCKET) then Exit;

    //        no := 0;
    //        setsockopt(ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, PAnsiChar(@no), sizeof(no));

            if (bind(ListenSocket, Ptr.ai_addr, Ptr.ai_addrlen) = SOCKET_ERROR) then
            begin
              LastErr := WSAGetLastError;
              Iocp.Winsock2.closesocket(ListenSocket);
              AppendLog('%s.Listen.bind(Port=%d, Socket=%d), ERROR %d=%s', [ClassName, Port, ListenSocket, LastErr, SysErrorMessage(LastErr)], ltWarning);
              Exit;
            end;

            if (Iocp.Winsock2.listen(ListenSocket, SOMAXCONN) = SOCKET_ERROR) then
            begin
              LastErr := WSAGetLastError;
              Iocp.Winsock2.closesocket(ListenSocket);
              AppendLog('%s.Listen.listen(Port=%d, Socket=%d), ERROR %d=%s', [ClassName, Port, ListenSocket, LastErr, SysErrorMessage(LastErr)], ltWarning);
              Exit;
            end;

            if not AssociateSocketWithCompletionPort(ListenSocket, nil) then
            begin
              Iocp.Winsock2.closesocket(ListenSocket);
              AppendLog('%s.Listen.AssociateSocketWithCompletionPort(Port=%d, Socket=%d) failed', [ClassName, Port, ListenSocket], ltWarning);
              Exit;
            end;

            if not FAcceptThread.NewListen(ListenSocket, Ptr.ai_family, InitAcceptNum) then
            begin
              Iocp.Winsock2.closesocket(ListenSocket);
              Exit;
            end;
                    SocketList.Add(ListenSocket);
            Ptr := Ptr.ai_next;
          end;
        finally
          freeaddrinfo(POutAddrInfo);
        end;

        Result := True;
      except
        on e: Exception do
        begin
            for i:=0 to SocketList.Count-1 do
            begin
                FAcceptThread.StopListen(SocketList[i]);
            end; 
          AppendLog('%s.Listen ERROR %s=%s', [ClassName, e.ClassName, e.Message], ltException);
        end;
      end;
    finally
    SocketList.Free;
  end;
end;

Original issue reported on code.google.com by Hezihang...@gmail.com on 5 Jul 2013 at 4:45