Bug 323695 (MONO81010) - [PATCH] Socket.Connect/BeginConnect "Socket is already connected" exception on FreeBSD
Summary: [PATCH] Socket.Connect/BeginConnect "Socket is already connected" exception o...
Status: RESOLVED FIXED
Alias: MONO81010
Product: Mono: Runtime
Classification: Mono
Component: io-layer (show other bugs)
Version: 1.2
Hardware: Other Other
: P3 - Medium : Major
Target Milestone: ---
Assignee: Dick Porter
QA Contact: Mono Bugs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-02 23:30 UTC by Robert S Wojciechowski
Modified: 2007-09-15 21:24 UTC (History)
0 users

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
patch try #1 (254 bytes, patch)
2007-03-02 23:31 UTC, Thomas Wiest
Details | Diff
patch try #2 (2.14 KB, patch)
2007-03-02 23:31 UTC, Thomas Wiest
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wiest 2007-09-15 20:29:49 UTC


---- Reported by robertw@ssgx.com 2007-03-02 16:30:55 MST ----

Description of Problem:

I have been working on a problem in the last few days related to
threading and sockets on FreeBSD when I started noticing that a threaded
database application that uses Npgsql would throw the following
exception randomly (and not very frequently) when connecting to our
PostgreSQL database at localhost:5432:

  Unhandled Exception: Npgsql.NpgsqlException:
  Socket is already connected
    at Npgsql.NpgsqlClosedState.Open (Npgsql.NpgsqlConnector context)
[0x00000] 
    at Npgsql.NpgsqlConnector.Open () [0x00000] 
    at Npgsql.NpgsqlConnectorPool.GetPooledConnector
(Npgsql.NpgsqlConnection Connection) [0x00000] 
    ...snip...

Npgsql uses Socket.BeginConnect to establish a connection to PostgreSQL
(in the latest SVN), but why would I get an EISCONN from
Socket.BeginConnect? I tried reverting to a blocking Socket.Connect call
but it still happened once in a while. After researching further, things
started to point towards the Mono win32 compatibility layer and the
_wapi_connect method in io-layer/sockets.c, not my threaded application
or Npgsql.

It seems I'm getting the EISCONN errno back from connect() as it runs in
a do/while loop. The first call must not succeed for whatever reason
(EINTR from a signal?) and the second one gives EISCONN which mono
throws back up as an error because it doesn't know how to handle it.

The first patch attached checks the errno for EISCONN and treats it as a
success. That seemed to still throw exceptions throughout the day,
though. The second patch should be a little more robust -- it has been
adapted from the following page:

  http://www.madore.org/~david/computers/connect-intr.html

I'm testing that out right now on my server. It's hard to trace down
because I don't have a test case that causes this behavior... I just
have to wait for it to happen again until I can create one.

I also wonder if this problem is related to https://bugzilla.novell.com/show_bug.cgi?id=MONO80839, a problem with
Socket.BeginConnect on Solaris. Hmm!

Anyone have any ideas if I'm on the right path to fixing this problem?

Steps to reproduce the problem:
In a multi-threaded application, try to connect to sockets while doing
other work. 

Actual Results:
Exception in thrown for EISCONN.

Expected Results:
Connect without an exception.

How often does this happen? 
One out of every few executions.



---- Additional Comments From robertw@ssgx.com 2007-03-02 16:31:25 MST ----

Created an attachment (id=171584)
patch try #1




---- Additional Comments From robertw@ssgx.com 2007-03-02 16:31:30 MST ----

Created an attachment (id=171585)
patch try #2




---- Additional Comments From dick@ximian.com 2007-03-22 11:45:37 MST ----

I've committed a slight variant of the second patch as r74811.  Thanks.

Imported an attachment (id=171584)
Imported an attachment (id=171585)

Unknown bug field "cf_op_sys_details" encountered while moving bug
   <cf_op_sys_details>FreeBSD 6.2-STABLE amd64</cf_op_sys_details>
Unknown operating system other. Setting to default OS "Other".