none
handler event leak RRS feed

  • General discussion

  • Saluer!

    I write the program on mixed CLR. The library Is connected native. I transfer in it from exe an unmanaged class.

     

    class SameClass
    {
    public:
    ....
    virtual void OnConnect(char* HostAddress, int ServerPort);
    virtual void OnDisconnect(int socerr);
    ....
    }
    

    The library calls methods of the given class. By the first call in native what thread or method SameClass, it is not clear from what form events. Who creates not clearly. At a similar situation but if exe it is written in native a mode of problems does not arise. Why so occurs? How to disable creation not known events? Because, after destruction of threads and a class, events remain - we receive leak of handlers.

    • Changed type nobugzModerator Wednesday, April 22, 2009 4:00 PM incomprehensible
    Thursday, April 16, 2009 1:07 PM

All replies

  • Hello,

    I don't quite understand your question. Can you please post a small working example to demonstrate which thread leaks which handle? How is your SameClass used exactly?

    -Karel
    Thursday, April 16, 2009 5:23 PM
    Moderator
  • Exe module /clr:

    extern "C" __declspec(dllimport) NT870* GetNT870Connection (NTConnectionEvents* ConnectionEvents1);

    ....
    NTChannel* NT870Con::ConnectionEventsCl::OnConnectListenPort(char* IP, unsigned short ServerPort) { Chan* temp = Sectors->OnConnectLisenPort(gcnew String(IP), ServerPort); NTChannel* NTChannelOut = temp; return NTChannelOut; } .... { NT870Obj1 = GetNT870Connection((NTConnectionEvents*)TempConnectionEventsCl); ..... }
    NTChannel::OnReceive_M_SP_NA_1(.....)
    {
    //free body. not code

    }
    NTChannel::OnDisconnect(int i)
    {
    //free body. not code
    }

    ________________________________________________________________________________________

    //Dll Module (native, not /clr):

    {
             //ServerThread
    	NTChannel * temp = ListenPortEvent1->OnConnectListenPort(ServerIP, PortNum);///!!!Create 5 events!!!
    	Channel_Stru* NTChannelClass = new Channel_Stru(ServerIP, PortNum, (Chan*)temp, sClient);
    	NTChannelClass->ListenSockInfo = lSockInfo;
    	if (NTChannelClass->Channel == -1) return -1;
    	NTChannel::SendCh* i1 = (NTChannel::SendCh*)NTChannelClass;
    	temp->SendCh1 = i1;
    	temp->OnConnect(ServerIP, PortNum); //Non create 5 events
    	return NTChannelClass->Channel;
    }
    ...
    {
    .....
    //ClientThread
    if(shutdown(sSock, 0) == SOCKET_ERROR)
    	sEndSucces = false;
    if(closesocket(sSock) == SOCKET_ERROR)
    	sEndSucces = false;
    if(!socerr || !sEndSucces)
    	socerr = (SOCKET_ERRORNO);
    connected = false;
    ReceiveDataObject->OnDisconnect(socerr);//!!!Create 5 events!!!
    }
    ....
    {
    .....
    //ReceiveThread
    ReceiveDataObject->OnReceive_M_SP_NA_1(commonAddr, cause, infonum, StructReceive);//!!!Create 5 events!!!
    .....
    }
    NTChannel is SameClass

    if exe module not /clr then he not creates events
    • Edited by hooky-mars Friday, April 17, 2009 7:18 AM
    Friday, April 17, 2009 3:25 AM
  • Who creates events? How it to disable?
    Friday, April 17, 2009 3:32 AM
  • Where and how is your event declared? Where and how many times do you connect your event handler method to the event?
    Note that if you connect the same method to the event multiple times, it will be called multiple times when the event is raised.
    Here's a simple example in managed C++ (compile: cl.exe /clr Test.cpp)
    #include <stdio.h>
    #include <windows.h>
    #using <system.dll>
    ref class ServerConnection;
    delegate void ServerConnectedEventHandler(ServerConnection ^ connection);
    
    ref class ServerConnection {
    public:
        char * serverName;
        ServerConnection(char * serverName) { this->serverName = serverName; }
        void Connect() {
            // Make connection to server ...
            
            // Raise event (will call all registered event handlers)
            connectedEvent(this);
        }
        event ServerConnectedEventHandler ^ connectedEvent;
    };
    ref class Test {
    public:
        static void Run() {
            ServerConnection ^ hConnection = gcnew ServerConnection("www.microsoft.com");
            // Register/connect event handler (ServerConnected) to the event 3 times
            hConnection->connectedEvent += gcnew ServerConnectedEventHandler(ServerConnected);
            hConnection->connectedEvent += gcnew ServerConnectedEventHandler(ServerConnected);
            hConnection->connectedEvent += gcnew ServerConnectedEventHandler(ServerConnected);
            
            // Do more stuff ...
            
            // Connects to the server and raises connectedEvent
            // Will call ServerConnected 3 times, because it was registered/connected 3x above
            hConnection->Connect();
            
            printf("\nUnregister/disconnect 1 event handler:\n");
            
            hConnection->connectedEvent -= gcnew ServerConnectedEventHandler(ServerConnected);
            // Connects to the server and raises connectedEvent
            hConnection->Connect();
        }
        
        // Event handler
        static void ServerConnected(ServerConnection ^ connection) {
            printf("Connection to server %s established\n", connection->serverName);
        }
    };
    int wmain(int argc, WCHAR * argv[]) {
        Test::Run();
        return 0;
    }
    


    This example will print this:
        Connection to server www.microsoft.com established
        Connection to server www.microsoft.com established
        Connection to server www.microsoft.com established

        Unregister/disconnect 1 event handler:
        Connection to server www.microsoft.com established
        Connection to server www.microsoft.com established

    You can disable/unregister/disconnect an event handler using -=
        hConnection->connectedEvent -= gcnew ServerConnectedEventHandler(ServerConnected);

    Let me know if I misunderstood your question (in that case please post a small working example as I did above).
    -Karel
    Friday, April 17, 2009 5:56 PM
    Moderator
  • Matter is not in it.

    Has found in MSDN: http://msdn.microsoft.com/en-us/library/74169f59.aspx
    When an unmanaged thread enters the runtime through, for example, a COM callable wrapper, the system checks the thread-local store of that thread to look for an internal managed Thread object. If one is found, the runtime is already aware of this thread. If it cannot find one, however, the runtime builds a new Thread object and installs it in the thread-local store of that thread.

    How to disable automatic creation Thread?

     

    Tuesday, April 21, 2009 6:17 AM
  • If each thread registers a handler (via thread-static member), then it might be it.
    I don't think it's possible to disable automatic creation of Threads. I think that CLR needs them to function properly. However I am not expert on threading and I might be wrong ...

    If you believe that threading is the problem, try not to register the handler for each thread and register the handler only once per process ...

    Tuesday, April 21, 2009 6:39 AM
    Moderator
  • Why CLR does not delete managed Thread if unmanaged thread has been deleted?

    Tuesday, April 21, 2009 6:55 AM
  • The Thread object is truly deleted/released after its finalization from finalization thread.
    How is this related to your original question?

    Tuesday, April 21, 2009 9:17 PM
    Moderator