silverp / jabber-net

Automatically exported from code.google.com/p/jabber-net
Other
0 stars 0 forks source link

Problems when using several jabberclients #69

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Create the clients

            foreach (JPSettings.ChatUser u in 
JPSettings.Instance.ChatUsers)
            {
                JabberClient client = new JabberClient();
                client.User = u.username;
                client.Password = u.password;
                client.Server = JPSettings.Instance.JabberServerHostname;
                client.Port = JPSettings.Instance.JabberServerPort;
                client.AutoLogin = true;
                client.AutoReconnect = 1;
                client.AutoPresence = false;
                client.Resource = client.User;
                client.KeepAlive = 10;
                client.PlaintextAuth = true;

                client.OnInvalidCertificate += new

System.Net.Security.RemoteCertificateValidationCallback(
                    client_OnInvalidCertificate);
                client.OnMessage += new MessageHandler(client_OnMessage);
                client.OnPresence += new 
PresenceHandler(client_OnPresence);

                client.OnError += new 
bedrock.ExceptionHandler(client_OnError);
                client.OnStreamError += new 
jabber.protocol.ProtocolHandler(
                    client_OnStreamError);
                client.OnAuthError += new jabber.protocol.ProtocolHandler(
                    client_OnAuthError);
                clients.Add(client);
            }

2. Connect them

        public override void OnChatUserLogin(ChatUser user)
        {
            user.PresenceChanged += new EventHandler(user_PresenceChanged);
            JabberClient client = FindJabberClient(user.Username);
            if (client == null) return;
            client.Connect();

            try
            {
                SetUserPresence(user);
            }
            catch (Exception e)
            {
                throw new Exception("Failed to set user presence for user " 
+
                    user.Username, e);
            }
        }

3. OnChatUserLogin is called in a loop for every users. SetUserPresence 
calls JabberClient.Presence().

4. My server is OpenFire 3.6.2

What is the expected output? What do you see instead?

I expect the chat users (I have two) to be logged in.

Sometimes they are.
Sometimes only one of them is.
Sometimes one of them got disconnected after exchanging some messages.
Sometimes I get the OnError event fired with Object reference not set to an 
object.
Sometimes I get the OnAuthError event fired.
Sometimes they say that xml tags are not matching.
Sometimes I get an Assertion error (see attached file).

What version of the product are you using? On what operating system?

I have this problem both with the current release And the revision 760.

Please provide any additional information below.

Both the server and my app are on my local machine.
I strongly suspect a parallel programming issue.

Original issue reported on code.google.com by michel.y...@vtxmail.ch on 1 May 2009 at 7:53

Attachments:

GoogleCodeExporter commented 9 years ago
Oh and this is visual studio 2005 and windows xp pro sp 3

Original comment by michel.y...@vtxmail.ch on 1 May 2009 at 8:02

GoogleCodeExporter commented 9 years ago
When OnError, the first exception is thrown in 
SocketStanzaStream:ISocketEventListener.OnRead(BaseSocket, byte[], int, int)

by m_element.Push(buf, offset, length);

Exception text: Unexpected exception. InnerException text: object reference not 
set 
to an instance of an object.

The exception stack trace is:

   at jabber.protocol.AsynchElementStream.Push(Byte[] buf, Int32 offset, Int32 
length)
   at 
jabber.connection.SocketStanzaStream.bedrock.net.ISocketEventListener.OnRead(Bas
eSock
et sock, Byte[] buf, Int32 offset, Int32 length)

The OnError call stack is
    JabberPort.dll!JabberPort.JabberPort.client_OnError(object sender = 
{jabber.client.JabberClient}, System.Exception ex = {"Unexpected exception"}) 
Line 
213 C#
    jabber-
net.dll!jabber.connection.XmppStream.jabber.connection.IStanzaEventListener.Erro
red(S
ystem.Exception ex = {"Unexpected exception"}) Line 1670 + 0x16 bytes   C#
    jabber-
net.dll!jabber.connection.SocketStanzaStream.bedrock.net.ISocketEventListener.On
Error
(bedrock.net.BaseSocket sock = {AsyncSocket 
172.24.1.74:1956->172.24.1.74:5222}, 
System.Exception ex = {"Unexpected exception"}) Line 414 + 0xc bytes    C#
>   jabber-
net.dll!jabber.connection.SocketStanzaStream.bedrock.net.ISocketEventListener.On
Read(
bedrock.net.BaseSocket sock = {AsyncSocket 172.24.1.74:1956->172.24.1.74:5222}, 
byte[] buf = {Dimensions:[4096]}, int offset = 0, int length = 319) Line 430 + 
0xf 
bytes   C#
    jabber-net.dll!bedrock.net.AsyncSocket.GotData(System.IAsyncResult ar = 
{System.Net.BufferAsyncResult}) Line 957 + 0x1c bytes   C#
    [External Code] 

Original comment by michel.y...@vtxmail.ch on 1 May 2009 at 11:34

GoogleCodeExporter commented 9 years ago
I found out that jabber.protocol.EnumParser::GetValHash (and GetStringHash) are 
not 
threadsafe. However I could observe two threads running simultaneously in this 
method.

Static member variable s_strings and s_vals must use a synchronization scheme.

From MSDN:

"A Dictionary<TKey, TValue> can support multiple readers concurrently, as long 
as the 
collection is not modified. Even so, enumerating through a collection is 
intrinsically not a thread-safe procedure. In the rare case where an 
enumeration 
contends with write accesses, the collection must be locked during the entire 
enumeration. To allow the collection to be accessed by multiple threads for 
reading 
and writing, you must implement your own synchronization."

A synchronization scheme that allows concurrent read access and exclusive write 
access would be more efficient than RW-exclusive since write's occur rarely. 
Therefore I suggest to not use the "lock" statement.

Original comment by michel.y...@vtxmail.ch on 5 May 2009 at 1:57

GoogleCodeExporter commented 9 years ago
has this issue been fixed?
cause in my architecture i use multiple clients from one machine and this seems 
to give random errors/disconnects.

Original comment by wgtm.pet...@gmail.com on 16 Nov 2010 at 9:11

GoogleCodeExporter commented 9 years ago
To fix this at home yourself do the following in EnumParser.cs:

Add a synchronization object:
private static readonly g_sync = null;

Add a synchronization block to GetValHash() and GetStringHash() (top of method 
should look like this):

Dictionary<string, object> map = null;
if (!s_vals.TryGetValue(t, out map))
{
    lock (g_sync)
    {
        if (s_vals.ContainsKey(t)) 
             return s_vals[t];

        s_vals[t] = map = new Dictionary<string, object>();
        // Everything else is the same here
        // etc
     } // End of lock(g_sync)
}

return map;

You'll do something similar in GetStringHash.

Original comment by crwe...@gmail.com on 17 May 2011 at 1:09

GoogleCodeExporter commented 9 years ago
Ahh, I guess I could have just attached the file...

Original comment by crwe...@gmail.com on 17 May 2011 at 1:11

Attachments: