public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* Re: RPC clnt_create() adress already in use
@ 2017-12-19 16:13 PAULUS, Raimund, TI-ABN
  2017-12-28  0:03 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2017-12-19 16:13 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

Hello Mark,

in my earlier tests the lib and header files for tirpc was still there from the Cygwin-installation. I think, this could influence the results of the tests.
Therefore i removed these files. From now on i used only the downloaded files from sourceforge (https://sourceforge.net/projects/libtirpc/files/libtirpc/). I tested libtirpc-0.3.2, libtirpc-1.0.1 and libtirpc-1.0.2. The results for all releases are the same. 

I needed the following sources:

auth_none.c, auth_unix.c, authunix_prot.c, bindresvport.c, clnt_bcast.c, clnt_dg.c, clnt_generic.c, clnt_perror.c, clnt_vc.c, debug.c, getnetconfig.c, getnetpath.c, mt_misc.c, rpc_callmsg.c, rpc_commondata.c, rpc_generic.c, rpc_prot.c, rpcb_clnt.c, rpcb_prot.c, xdr.c, xdr_array.c, xdr_float.c, xdr_reference.c,   xdr_rec.c, xdr_mem.c

I had to change the following (already mentioned earlier):

clnt_bcast.c 
(because POLLRDNORM, POLLRDBAND are already defined in /usr/include/sys/poll.h) :

--> #ifndef POLLRDNORM
# define POLLRDNORM     0x040           /* Normal data may be read.  */
# define POLLRDBAND     0x080           /* Priority data may be read.  */
--> #endif

xdr.h (typedefs where missed):

#include <rpc/types.h>

--> typedef __uint64_t      u_quad_t;
--> typedef __int64_t       quad_t;


My compile-flags: -D_GNU_SOURCE -D__GLIBC__ -D__linux__

If i build my test program with the sources above, the behavior is the same as with the Cygwin-libtirpc: the first RPC-connection is ok, the next call to clnt_create() delivers the error EADDRINUSE.

The test program on a Linux-box works perfectly. With "netstat -n" you can see each connection from the client to the server creates a new pair of ports. On the server-side the pair is always the same (ports 111, 907). On the client-side however the ports differ from one connection to the other. When the connections are closed the ports remain in state TIME_WAIT. After a while they disappear.

If the RPC-client (Cygwin) is running on a Windows-box, "netstat -n" shows the pair of ports for the first connection. The next connection attempt (clnt_create()) delivers: EADDRINUSE.
 
In the sources you can see the following:

clnt_create() calls the function bindresvport_sa() (in bindresvport.c). Here the port for the connection is determined:

if (port == 0) {
                port = (getpid() % NPORTS) + STARTPORT;
}

and the socket is bound to the port:

res = bind(sd, sa, salen);

If this part is executed multiple times (loop) the port is always the same. The function bind() doesn't deliver an error (res = 0, maybe bind() doesn't work correctly?). Therefore the error is not detected until the call of  connect() in function clnt_vc_create() (in clnt_vc.c). But here you can not correct the port. 

I tried the following:

The call of setsockopt(., SO_REUSEADDR, .) before bind() doesn't change anything. The error still occurs.

I found 2 approaches to avoid the error:

1. Before the call to bind() set the port to 0 (port = 0). The following bind() searches an unused port.

2. Set the port to 0 (port = 0). Do not call bind(). Later the call to connect() searches an unused port.

I tested the two methods and the behavior was the same as the Linux-client. It obviously works correctly.  But i'm not a network specialist and i don't know, if it's the best solution for the problem. 


Subsequently I downloaded the Cygwin-sources for libtirpc-0.3.2 and libtirpc-1.0.1. And here again, with the changes mentioned in the two approaches the RPC-connection works perfectly. The only difference her is: a connection does not create a pair of ports but only a single port (netstat -n).


Greetings

Raimund 

-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Mittwoch, 22. November 2017 22:55
An: cygwin@cygwin.com
Betreff: Re: WG: RPC clnt_create() adress already in use

(3rd attempt at sending this)

PAULUS, Raimund, TI-ABN wrote:
> Hello Mark,
>
> is there any news with respect to libtirpc? Very important: I need it in Cygwin 2.5.1.

I neglected to report what I found; sorry for that.  The difference(s) between the vanilla libtirpc 1.0.1 that you downloaded and the one supplied by Cygwin are due to the patches applied as part of the Cygwin build.  If you have the Cygwin package's source downloaded and unpacked with 'cygport prep' you can find these patches in /usr/src/libtirpc-1.0.1-1.src.

I noticed one of the patches is a security fix.  I suspect one or more of these patches are causing the difficulty you're having but I don't know enough about RPC in general to set up a test environment and can't devote time to digging further.  This is as far as I can go.  Apologies again for not stating this.
Regards,

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2017-12-19 16:13 RPC clnt_create() adress already in use PAULUS, Raimund, TI-ABN
@ 2017-12-28  0:03 ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2017-12-28  0:03 UTC (permalink / raw)
  To: cygwin

Hi Raimund,
Comments embedded below...

PAULUS, Raimund, TI-ABN wrote:
> Hello Mark,
>
> in my earlier tests the lib and header files for tirpc was still there from the Cygwin-installation. I think, this could influence the results of the tests.
> Therefore i removed these files. From now on i used only the downloaded files from sourceforge (https://sourceforge.net/projects/libtirpc/files/libtirpc/). I tested libtirpc-0.3.2, libtirpc-1.0.1 and libtirpc-1.0.2. The results for all releases are the same.
>
> I needed the following sources:
>
> auth_none.c, auth_unix.c, authunix_prot.c, bindresvport.c, clnt_bcast.c, clnt_dg.c, clnt_generic.c, clnt_perror.c, clnt_vc.c, debug.c, getnetconfig.c, getnetpath.c, mt_misc.c, rpc_callmsg.c, rpc_commondata.c, rpc_generic.c, rpc_prot.c, rpcb_clnt.c, rpcb_prot.c, xdr.c, xdr_array.c, xdr_float.c, xdr_reference.c,   xdr_rec.c, xdr_mem.c
>
> I had to change the following (already mentioned earlier):
>
> clnt_bcast.c
> (because POLLRDNORM, POLLRDBAND are already defined in /usr/include/sys/poll.h) :
>
> --> #ifndef POLLRDNORM
> # define POLLRDNORM     0x040           /* Normal data may be read.  */
> # define POLLRDBAND     0x080           /* Priority data may be read.  */
> --> #endif

Not only does /usr/include/sys/poll.h already define them, they're defined with 
different values.  Could be a red flag or a red herring; don't know yet.

> xdr.h (typedefs where missed):
>
> #include <rpc/types.h>
>
> --> typedef __uint64_t      u_quad_t;
> --> typedef __int64_t       quad_t;
>
>
> My compile-flags: -D_GNU_SOURCE -D__GLIBC__ -D__linux__

Just so I understand more fully: you are compiling with those options on Cygwin?

> If i build my test program with the sources above, the behavior is the same as with the Cygwin-libtirpc: the first RPC-connection is ok, the next call to clnt_create() delivers the error EADDRINUSE.
>
> The test program on a Linux-box works perfectly. With "netstat -n" you can see each connection from the client to the server creates a new pair of ports. On the server-side the pair is always the same (ports 111, 907). On the client-side however the ports differ from one connection to the other. When the connections are closed the ports remain in state TIME_WAIT. After a while they disappear.
>
> If the RPC-client (Cygwin) is running on a Windows-box, "netstat -n" shows the pair of ports for the first connection. The next connection attempt (clnt_create()) delivers: EADDRINUSE.
>
> In the sources you can see the following:
>
> clnt_create() calls the function bindresvport_sa() (in bindresvport.c). Here the port for the connection is determined:
>
> if (port == 0) {
>                 port = (getpid() % NPORTS) + STARTPORT;
> }

The idea there is to use a different port on each run of the program.  If you're 
looping around and reaching that code again with port==0, then yes you'll get 
the same port number each time because getpid() is not changing.

>
> and the socket is bound to the port:
>
> res = bind(sd, sa, salen);
>
> If this part is executed multiple times (loop) the port is always the same. The function bind() doesn't deliver an error (res = 0, maybe bind() doesn't work correctly?). Therefore the error is not detected until the call of  connect() in function clnt_vc_create() (in clnt_vc.c). But here you can not correct the port.
>
> I tried the following:
>
> The call of setsockopt(., SO_REUSEADDR, .) before bind() doesn't change anything. The error still occurs.
>
> I found 2 approaches to avoid the error:
>
> 1. Before the call to bind() set the port to 0 (port = 0). The following bind() searches an unused port.
>
> 2. Set the port to 0 (port = 0). Do not call bind(). Later the call to connect() searches an unused port.
>
> I tested the two methods and the behavior was the same as the Linux-client. It obviously works correctly.  But i'm not a network specialist and i don't know, if it's the best solution for the problem.
>
>
> Subsequently I downloaded the Cygwin-sources for libtirpc-0.3.2 and libtirpc-1.0.1. And here again, with the changes mentioned in the two approaches the RPC-connection works perfectly. The only difference her is: a connection does not create a pair of ports but only a single port (netstat -n).

I must compliment you; you are being very specific and detailed about what 
you're doing on the client end of the RPC connection.  But as I said in my last 
email, I don't know specifics about RPC implementation; I sort of know generally 
what RPC can do.

I don't know enough to set up an RPC test bed to try your client program 
locally.  *Unless* it's sufficient to run your client program and aim at the 
local machine even though it has no RPC server listening.  If that would 
demonstrate your issue, let me know and I'll have another look.  Otherwise, I 
would need to set up an RPC server on my Cygwin machine.  If you've done that on 
your Cygwin machine, what are the steps?  I think I can follow Unix-style 
instructions but will have to allow for Windows Firewall so if you've done this 
already on Cygwin your procedure would help a lot.
Thanks,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-03-08 11:44 PAULUS, Raimund, TI-ABN
  2018-03-08 15:24 ` Corinna Vinschen
@ 2018-03-08 23:00 ` Mark Geisert
  1 sibling, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2018-03-08 23:00 UTC (permalink / raw)
  To: cygwin

PAULUS, Raimund, TI-ABN wrote:
[...]

Apologies for butting in, but there is one place you might look. It is not 
supported on the Cygwin lists; the few devs here already have overfull plates 
supporting current Windows OSs and Cygwin packages.

It's the Cygwin Time Machine.  Find it at
http://www.crouchingtigerhiddenfruitbat.org/cygwin/timemachine.html

HTH,

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-03-08 11:44 PAULUS, Raimund, TI-ABN
@ 2018-03-08 15:24 ` Corinna Vinschen
  2018-03-08 23:00 ` Mark Geisert
  1 sibling, 0 replies; 34+ messages in thread
From: Corinna Vinschen @ 2018-03-08 15:24 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 462 bytes --]

On Mar  8 06:55, PAULUS, Raimund, TI-ABN wrote:
> 
> Hello Corinna,
> 
> is there still an earlier snapshot of the cygwin1.dll, that works
> under Windows XP? I'd like to try to make the adjustments myself (in
> net.cc).

XP is deprecated since August 2016.  No later snapshot supports XP.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: RPC clnt_create() adress already in use
@ 2018-03-08 11:44 PAULUS, Raimund, TI-ABN
  2018-03-08 15:24 ` Corinna Vinschen
  2018-03-08 23:00 ` Mark Geisert
  0 siblings, 2 replies; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-03-08 11:44 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1342 bytes --]


Hello Corinna,

is there still an earlier snapshot of the cygwin1.dll, that works under Windows XP? I'd like to try to make the adjustments myself (in net.cc).

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Corinna Vinschen
Gesendet: Dienstag, 27. Februar 2018 11:37
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

On Feb 27 09:54, PAULUS, Raimund, TI-ABN wrote:
> High Corinna,
> 
> is it possible to get the patched cygwin1.dll for Cygwin 2.5.1? I have to support several older Win XP SP3 boxes.

Sorry, we only support the current Cygwin build and keep the next older version as fallback.  It's just not feasible to support version branches like the Linux kernel does, given the low number of active participants in this project.

Nothing keeps you from building your own, though.  The patches should apply mostly clean.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
\0ТÒÐÐ¥\a&ö&ÆVÒ\a&W\x06÷'G3¢\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒ÷\a&ö&ÆV×2æ‡FÖÀФd\x15\x13¢\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöf\x17\x12ðФFö7VÖVçF\x17F–öã¢\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöFö72æ‡FÖÀÐ¥Vç7V'67&–&R\x06–æfó¢\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöÖÂò7Vç7V'67&–&R×6–×\x06ÆPРÐ

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-03-02 10:39 PAULUS, Raimund, TI-ABN
  0 siblings, 0 replies; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-03-02 10:39 UTC (permalink / raw)
  To: cygwin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1888 bytes --]

High Mark,

i did it already. Building cygwin1.dll in Cygwin 2.5.1 is ok, but using it delivers the message: 

"The procedure entry point CancelSynchronousIo could not be located in the dynamic link library KERNEL32.dll".

It seems, i have to continue in using the old Cygwin 1.5.8 release  for my Win XP SP3 boxes.

Raimund

-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Mittwoch, 28. Februar 2018 07:00
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

Corinna Vinschen wrote:
> On Feb 27 09:54, PAULUS, Raimund, TI-ABN wrote:
>> High Corinna,
>>
>> is it possible to get the patched cygwin1.dll for Cygwin 2.5.1? I have to support several older Win XP SP3 boxes.
>
> Sorry, we only support the current Cygwin build and keep the next 
> older version as fallback.  It's just not feasible to support version 
> branches like the Linux kernel does, given the low number of active 
> participants in this project.
>
> Nothing keeps you from building your own, though.  The patches should 
> apply mostly clean.
>
>
> Corinna

...And there's a FAQ that tells how to build the Cygwin DLL.  Provided you have installed all the necessary tools listed there, it is straightforward to do.

https://cygwin.com/faq.html#faq.programming.building-cygwin

Something to consider,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

\0ТÒÐÐ¥\a&ö&ÆVÒ\a&W\x06÷'G3¢\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒ÷\a&ö&ÆV×2æ‡FÖÀФd\x15\x13¢\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöf\x17\x12ðФFö7VÖVçF\x17F–öã¢\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöFö72æ‡FÖÀÐ¥Vç7V'67&–&R\x06–æfó¢\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöÖÂò7Vç7V'67&–&R×6–×\x06ÆPРÐ

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-27 10:37 ` Corinna Vinschen
@ 2018-02-28  6:00   ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2018-02-28  6:00 UTC (permalink / raw)
  To: cygwin

Corinna Vinschen wrote:
> On Feb 27 09:54, PAULUS, Raimund, TI-ABN wrote:
>> High Corinna,
>>
>> is it possible to get the patched cygwin1.dll for Cygwin 2.5.1? I have to support several older Win XP SP3 boxes.
>
> Sorry, we only support the current Cygwin build and keep the next older
> version as fallback.  It's just not feasible to support version branches
> like the Linux kernel does, given the low number of active participants
> in this project.
>
> Nothing keeps you from building your own, though.  The patches should
> apply mostly clean.
>
>
> Corinna

...And there's a FAQ that tells how to build the Cygwin DLL.  Provided you have 
installed all the necessary tools listed there, it is straightforward to do.

https://cygwin.com/faq.html#faq.programming.building-cygwin

Something to consider,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-27  9:54 PAULUS, Raimund, TI-ABN
@ 2018-02-27 10:37 ` Corinna Vinschen
  2018-02-28  6:00   ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: Corinna Vinschen @ 2018-02-27 10:37 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 684 bytes --]

On Feb 27 09:54, PAULUS, Raimund, TI-ABN wrote:
> High Corinna,
> 
> is it possible to get the patched cygwin1.dll for Cygwin 2.5.1? I have to support several older Win XP SP3 boxes.

Sorry, we only support the current Cygwin build and keep the next older
version as fallback.  It's just not feasible to support version branches
like the Linux kernel does, given the low number of active participants
in this project.

Nothing keeps you from building your own, though.  The patches should
apply mostly clean.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-02-27  9:54 PAULUS, Raimund, TI-ABN
  2018-02-27 10:37 ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-02-27  9:54 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2512 bytes --]

High Corinna,

is it possible to get the patched cygwin1.dll for Cygwin 2.5.1? I have to support several older Win XP SP3 boxes.

Raimund

-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Corinna Vinschen
Gesendet: Dienstag, 6. Februar 2018 15:20
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

On Feb  6 11:29, PAULUS, Raimund, TI-ABN wrote:
> On Feb  5 15:06, Corinna Vinschen wrote:
> > On Feb  5 14:34, Corinna Vinschen wrote:
> > > On Feb  5 12:26, Corinna Vinschen wrote:
> > > > [...]
> > > > What potential solutions to this problem do we have?
> > > > 
> > > > - bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
> > > >   sure bind fails.
> > > 
> > > Nope, no way.  Even enforcing SO_EXCLUSIVEADDRUSE results in the 
> > > second bind succeeding and the subsequent connect failing.  The 
> > > entire SO_REUSEADDR/SO_EXCLUSIVEADDRUSE semantics only works as 
> > > desired on the server side apparently
> > > 
> > > > - bindresvport could check every local address for being free prior
> > > >   to calling bind.  However, there's a potential race here.
> > > > 
> > > > - DisconnectEx?  Never tried this Winsock extension but it might be
> > > >   worth a shot.
> > 
> > I think I have a very simple solution for the scenario which calls 
> > bindresvport with port number.  Still looking for a solution for the 
> > second problem...
> 
> I've pushed a few patches and uploaded new developer snapshots to 
> https://cygwin.com/snapshots.  Please give them a try.
> 
> with the snapshot of cygwin1.dll and using bindresvport() from Cygwin 
> for libtirpc (instead of the original bindresvport() from libtirpc) 
> all my testcases work without error.
> 
> Many thanks
> Raimund

Thanks for testing.  Please note that this should work most of the time, but is still not 100% foolproof.  There's a systematic race between checking existing connections and calling bind which can't be easily worked around by Cygwin.  Still, should be better than before :}


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
\0ТÒÐÐ¥\a&ö&ÆVÒ\a&W\x06÷'G3¢\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒ÷\a&ö&ÆV×2æ‡FÖÀФd\x15\x13¢\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöf\x17\x12ðФFö7VÖVçF\x17F–öã¢\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöFö72æ‡FÖÀÐ¥Vç7V'67&–&R\x06–æfó¢\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöÖÂò7Vç7V'67&–&R×6–×\x06ÆPРÐ

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-06 14:20 ` Corinna Vinschen
@ 2018-02-07  6:54   ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2018-02-07  6:54 UTC (permalink / raw)
  To: cygwin

Corinna Vinschen wrote:
> On Feb  6 11:29, PAULUS, Raimund, TI-ABN wrote:
>> On Feb  5 15:06, Corinna Vinschen wrote:
[...]
>> I've pushed a few patches and uploaded new developer snapshots to
>> https://cygwin.com/snapshots.  Please give them a try.
>>
>> with the snapshot of cygwin1.dll and using bindresvport() from Cygwin
>> for libtirpc (instead of the original bindresvport() from libtirpc)
>> all my testcases work without error.
>>
>> Many thanks
>> Raimund
>
> Thanks for testing.  Please note that this should work most of the time,
> but is still not 100% foolproof.  There's a systematic race between
> checking existing connections and calling bind which can't be easily
> worked around by Cygwin.  Still, should be better than before :}

Great to read this latest status.  I'll shortly submit a libtirpc patch to stub 
out its own version of bindresvport() in favor of Cygwin's version.
Thanks all,

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-06 11:29 PAULUS, Raimund, TI-ABN
@ 2018-02-06 14:20 ` Corinna Vinschen
  2018-02-07  6:54   ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: Corinna Vinschen @ 2018-02-06 14:20 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 1886 bytes --]

On Feb  6 11:29, PAULUS, Raimund, TI-ABN wrote:
> On Feb  5 15:06, Corinna Vinschen wrote:
> > On Feb  5 14:34, Corinna Vinschen wrote:
> > > On Feb  5 12:26, Corinna Vinschen wrote:
> > > > [...]
> > > > What potential solutions to this problem do we have?
> > > > 
> > > > - bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
> > > >   sure bind fails.
> > > 
> > > Nope, no way.  Even enforcing SO_EXCLUSIVEADDRUSE results in the 
> > > second bind succeeding and the subsequent connect failing.  The 
> > > entire SO_REUSEADDR/SO_EXCLUSIVEADDRUSE semantics only works as 
> > > desired on the server side apparently
> > > 
> > > > - bindresvport could check every local address for being free prior
> > > >   to calling bind.  However, there's a potential race here.
> > > > 
> > > > - DisconnectEx?  Never tried this Winsock extension but it might be
> > > >   worth a shot.
> > 
> > I think I have a very simple solution for the scenario which calls 
> > bindresvport with port number.  Still looking for a solution for the 
> > second problem...
> 
> I've pushed a few patches and uploaded new developer snapshots to
> https://cygwin.com/snapshots.  Please give them a try.
> 
> with the snapshot of cygwin1.dll and using bindresvport() from Cygwin
> for libtirpc (instead of the original bindresvport() from libtirpc)
> all my testcases work without error.
> 
> Many thanks
> Raimund

Thanks for testing.  Please note that this should work most of the time,
but is still not 100% foolproof.  There's a systematic race between
checking existing connections and calling bind which can't be easily
worked around by Cygwin.  Still, should be better than before :}


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-02-06 11:29 PAULUS, Raimund, TI-ABN
  2018-02-06 14:20 ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-02-06 11:29 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 3326 bytes --]

Hello Corinna,

with the snapshot of cygwin1.dll and using bindresvport() from Cygwin for libtirpc (instead of the original bindresvport() from libtirpc) all my testcases work without error.

Many thanks
Raimund



-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Corinna Vinschen
Gesendet: Montag, 5. Februar 2018 21:15
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

On Feb  5 15:06, Corinna Vinschen wrote:
> On Feb  5 14:34, Corinna Vinschen wrote:
> > On Feb  5 12:26, Corinna Vinschen wrote:
> > > To reiterate the problem we observe:
> > > 
> > > - socket()
> > > - setsockopt (SO_REUSEADDR)
> > > - bind() succeeds
> > > - connect() fails with EADDRINUSE while socket is still in 
> > > TIME_WAIT
> > > 
> > > using bindresvport in place of bind only marginally changes the 
> > > situation, in particular if the second parameter is set and 
> > > requests a port number != 0.  What happens in that case is that 
> > > bindresvport calls bind with this port number and checks if bind returns EADDRINUSE.
> > > 
> > > Only then it tries to bind other port numbers in the reserved range.
> > > But we now know that bind will never return EADDINUSE if the 
> > > SO_REUSEADDR socket option has been set.
> > > 
> > > Even assuming the process calls bindresvport(sock, NULL) we may 
> > > end up returning a port number already in use if the process is 
> > > the only Cygwin process on the system.  The reason is that Cygwin 
> > > uses a round robin approach which relies on having a globally 
> > > shared value called last_used_bindresvport.  If the process is the 
> > > only Cygwin process on the system, this information is lost after 
> > > exiting the process, so the next process will start with the same 
> > > start port number and bind will again fail to notice the client with EADDRINUSE.
> > > 
> > > What potential solutions to this problem do we have?
> > > 
> > > - bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
> > >   sure bind fails.
> > 
> > Nope, no way.  Even enforcing SO_EXCLUSIVEADDRUSE results in the 
> > second bind succeeding and the subsequent connect failing.  The 
> > entire SO_REUSEADDR/SO_EXCLUSIVEADDRUSE semantics only works as 
> > desired on the server side apparently
> > 
> > > - bindresvport could check every local address for being free prior
> > >   to calling bind.  However, there's a potential race here.
> > > 
> > > - DisconnectEx?  Never tried this Winsock extension but it might be
> > >   worth a shot.
> 
> I think I have a very simple solution for the scenario which calls 
> bindresvport with port number.  Still looking for a solution for the 
> second problem...

I've pushed a few patches and uploaded new developer snapshots to https://cygwin.com/snapshots.  Please give them a try.


Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
\x03B‹KCB”\x1c›Ø›\x19[H\x1c™\^[ܝ\x1cΈ\b\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÜ\x1c›Ø›\x19[\Ëš\x1d^[[\x03B‘TNˆ\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÙ˜\KÃB‘^[ØÝ[Y[\x18]\x1a[ÛŽˆ\b\b\b\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÙ^[ØÜËš\x1d^[[\x03B•[œÝXœØÜšX™H\x1a[™›Îˆ\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÛ[\vÈÝ[œÝXœØÜšX™K\Ú[\^[\x19CBƒB

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-05 14:06       ` Corinna Vinschen
@ 2018-02-05 20:15         ` Corinna Vinschen
  0 siblings, 0 replies; 34+ messages in thread
From: Corinna Vinschen @ 2018-02-05 20:15 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 2600 bytes --]

On Feb  5 15:06, Corinna Vinschen wrote:
> On Feb  5 14:34, Corinna Vinschen wrote:
> > On Feb  5 12:26, Corinna Vinschen wrote:
> > > To reiterate the problem we observe:
> > > 
> > > - socket()
> > > - setsockopt (SO_REUSEADDR)
> > > - bind() succeeds
> > > - connect() fails with EADDRINUSE while socket is still in TIME_WAIT
> > > 
> > > using bindresvport in place of bind only marginally changes the
> > > situation, in particular if the second parameter is set and requests a
> > > port number != 0.  What happens in that case is that bindresvport calls
> > > bind with this port number and checks if bind returns EADDRINUSE.
> > > 
> > > Only then it tries to bind other port numbers in the reserved range.
> > > But we now know that bind will never return EADDINUSE if the SO_REUSEADDR
> > > socket option has been set.
> > > 
> > > Even assuming the process calls bindresvport(sock, NULL) we may end up
> > > returning a port number already in use if the process is the only Cygwin
> > > process on the system.  The reason is that Cygwin uses a round robin
> > > approach which relies on having a globally shared value called
> > > last_used_bindresvport.  If the process is the only Cygwin process on
> > > the system, this information is lost after exiting the process, so the
> > > next process will start with the same start port number and bind will
> > > again fail to notice the client with EADDRINUSE.
> > > 
> > > What potential solutions to this problem do we have?
> > > 
> > > - bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
> > >   sure bind fails.
> > 
> > Nope, no way.  Even enforcing SO_EXCLUSIVEADDRUSE results in the
> > second bind succeeding and the subsequent connect failing.  The
> > entire SO_REUSEADDR/SO_EXCLUSIVEADDRUSE semantics only works as
> > desired on the server side apparently
> > 
> > > - bindresvport could check every local address for being free prior
> > >   to calling bind.  However, there's a potential race here.
> > > 
> > > - DisconnectEx?  Never tried this Winsock extension but it might be
> > >   worth a shot.
> 
> I think I have a very simple solution for the scenario which calls
> bindresvport with port number.  Still looking for a solution for
> the second problem...

I've pushed a few patches and uploaded new developer snapshots to
https://cygwin.com/snapshots.  Please give them a try.


Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-02-05 14:58 PAULUS, Raimund, TI-ABN
  0 siblings, 0 replies; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-02-05 14:58 UTC (permalink / raw)
  To: cygwin

Hi Mark and Corinna,

i use my program in a production environment running 24 hours a day. Therefore it must be as stable as possible and I have different test scenarios. Normally the program is the only Cygwin program running at this time. It is running only for a short time for data exchange with a linux server. Subsequently an other program (not Cygwin) does the rest of the job with the transferred data. After some seconds (or minutes) the other program starts my program again for data exchange. My program is started by a VB-script (windows script host) or a DOS shell script but never in the bash.

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Montag, 5. Februar 2018 11:29
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

PAULUS, Raimund, TI-ABN wrote:
> Hello Mark,
>
> unfortunately i must correct my statement from Friday.
> The program works, but only if the connections to the server are established in a loop inside the program.
> If the program ends and you start it anew, a connection is not possible for a long time. you have to wait before you can establish a new connection.

That isn't what I saw in my testing.  At one point I had three copies of your test_rpc.exe running simultaneously and they all were able to establish 20 connections and the allocated port numbers were interleaved.

Are you running your test programs directly from a Windows Command Prompt or from one of the Cygwin shells like bash?

> Actually only our approaches in the original bindresvport() seem to work for all cases.
> You have proposed to use the static variable usecount in 
> bindresvport(). But how is the value of the variable handled if the program starts anew. Is it possible to get an used portnumber and run in EADDRINUSE?

You must understand that none of the libtirpc approaches is guaranteed to work 100% of the time.  The problem is that without a lot of extra work we can't get libtirpc to "know" which ports to avoid.  Our approaches are just different strategies for avoiding a port collision, with different chances of working.

Libtirpc's original approach is essentially to have a range of port numbers it will try, 600 thru 1023, start with one of them randomly (based on the pid of the calling process), increment by one on each use.  This won't work when you're calling bindresvport() multiple times within one program because it starts from the same port number each time.

My "usecount" modification changes things so we start with the same port number as before but increment each time we bindresvport().  Good for one program making multiple calls and sort of good for multiple programs at same time.. but there is a chance of port number collision between the programs.

Using Cygwin's bindresvport() is the best solution because Cygwin keeps track of the last port number it has allocated *to any Cygwin program*.  This is the only approach that can deal with multiple programs and multiple calls in one program. 
  So we need to nail down why it doesn't seem to work for you.

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-05 13:34     ` Corinna Vinschen
@ 2018-02-05 14:06       ` Corinna Vinschen
  2018-02-05 20:15         ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: Corinna Vinschen @ 2018-02-05 14:06 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 2332 bytes --]

On Feb  5 14:34, Corinna Vinschen wrote:
> On Feb  5 12:26, Corinna Vinschen wrote:
> > To reiterate the problem we observe:
> > 
> > - socket()
> > - setsockopt (SO_REUSEADDR)
> > - bind() succeeds
> > - connect() fails with EADDRINUSE while socket is still in TIME_WAIT
> > 
> > using bindresvport in place of bind only marginally changes the
> > situation, in particular if the second parameter is set and requests a
> > port number != 0.  What happens in that case is that bindresvport calls
> > bind with this port number and checks if bind returns EADDRINUSE.
> > 
> > Only then it tries to bind other port numbers in the reserved range.
> > But we now know that bind will never return EADDINUSE if the SO_REUSEADDR
> > socket option has been set.
> > 
> > Even assuming the process calls bindresvport(sock, NULL) we may end up
> > returning a port number already in use if the process is the only Cygwin
> > process on the system.  The reason is that Cygwin uses a round robin
> > approach which relies on having a globally shared value called
> > last_used_bindresvport.  If the process is the only Cygwin process on
> > the system, this information is lost after exiting the process, so the
> > next process will start with the same start port number and bind will
> > again fail to notice the client with EADDRINUSE.
> > 
> > What potential solutions to this problem do we have?
> > 
> > - bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
> >   sure bind fails.
> 
> Nope, no way.  Even enforcing SO_EXCLUSIVEADDRUSE results in the
> second bind succeeding and the subsequent connect failing.  The
> entire SO_REUSEADDR/SO_EXCLUSIVEADDRUSE semantics only works as
> desired on the server side apparently
> 
> > - bindresvport could check every local address for being free prior
> >   to calling bind.  However, there's a potential race here.
> > 
> > - DisconnectEx?  Never tried this Winsock extension but it might be
> >   worth a shot.

I think I have a very simple solution for the scenario which calls
bindresvport with port number.  Still looking for a solution for
the second problem...


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-05 11:26   ` Corinna Vinschen
@ 2018-02-05 13:34     ` Corinna Vinschen
  2018-02-05 14:06       ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: Corinna Vinschen @ 2018-02-05 13:34 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 2507 bytes --]

On Feb  5 12:26, Corinna Vinschen wrote:
> On Feb  5 02:29, Mark Geisert wrote:
> > Using Cygwin's bindresvport() is the best solution because Cygwin keeps
> > track of the last port number it has allocated *to any Cygwin program*.
> > This is the only approach that can deal with multiple programs and multiple
> > calls in one program.  So we need to nail down why it doesn't seem to work
> > for you.
> 
> Apart from all the above, there may still be a problem in the given scenario.
> 
> To reiterate the problem we observe:
> 
> - socket()
> - setsockopt (SO_REUSEADDR)
> - bind() succeeds
> - connect() fails with EADDRINUSE while socket is still in TIME_WAIT
> 
> using bindresvport in place of bind only marginally changes the
> situation, in particular if the second parameter is set and requests a
> port number != 0.  What happens in that case is that bindresvport calls
> bind with this port number and checks if bind returns EADDRINUSE.
> 
> Only then it tries to bind other port numbers in the reserved range.
> But we now know that bind will never return EADDINUSE if the SO_REUSEADDR
> socket option has been set.
> 
> Even assuming the process calls bindresvport(sock, NULL) we may end up
> returning a port number already in use if the process is the only Cygwin
> process on the system.  The reason is that Cygwin uses a round robin
> approach which relies on having a globally shared value called
> last_used_bindresvport.  If the process is the only Cygwin process on
> the system, this information is lost after exiting the process, so the
> next process will start with the same start port number and bind will
> again fail to notice the client with EADDRINUSE.
> 
> What potential solutions to this problem do we have?
> 
> - bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
>   sure bind fails.

Nope, no way.  Even enforcing SO_EXCLUSIVEADDRUSE results in the
second bind succeeding and the subsequent connect failing.  The
entire SO_REUSEADDR/SO_EXCLUSIVEADDRUSE semantics only works as
desired on the server side apparently

> - bindresvport could check every local address for being free prior
>   to calling bind.  However, there's a potential race here.
> 
> - DisconnectEx?  Never tried this Winsock extension but it might be
>   worth a shot.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-05 10:29 ` Mark Geisert
@ 2018-02-05 11:26   ` Corinna Vinschen
  2018-02-05 13:34     ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: Corinna Vinschen @ 2018-02-05 11:26 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 4217 bytes --]

On Feb  5 02:29, Mark Geisert wrote:
> PAULUS, Raimund, TI-ABN wrote:
> > Hello Mark,
> > 
> > unfortunately i must correct my statement from Friday.
> > The program works, but only if the connections to the server are established in a loop inside the program.
> > If the program ends and you start it anew, a connection is not possible for a long time. you have to wait before you can establish a new connection.
> 
> That isn't what I saw in my testing.  At one point I had three copies of
> your test_rpc.exe running simultaneously and they all were able to establish
> 20 connections and the allocated port numbers were interleaved.
> 
> Are you running your test programs directly from a Windows Command Prompt or
> from one of the Cygwin shells like bash?
> 
> > Actually only our approaches in the original bindresvport() seem to work for all cases.
> > You have proposed to use the static variable usecount in bindresvport(). But how is the value of the variable handled if the program starts anew. Is it possible to get an used portnumber
> > and run in EADDRINUSE?
> 
> You must understand that none of the libtirpc approaches is guaranteed to
> work 100% of the time.  The problem is that without a lot of extra work we
> can't get libtirpc to "know" which ports to avoid.  Our approaches are just
> different strategies for avoiding a port collision, with different chances
> of working.
> 
> Libtirpc's original approach is essentially to have a range of port numbers
> it will try, 600 thru 1023, start with one of them randomly (based on the
> pid of the calling process), increment by one on each use.  This won't work
> when you're calling bindresvport() multiple times within one program because
> it starts from the same port number each time.
> 
> My "usecount" modification changes things so we start with the same port
> number as before but increment each time we bindresvport().  Good for one
> program making multiple calls and sort of good for multiple programs at same
> time.. but there is a chance of port number collision between the programs.
> 
> Using Cygwin's bindresvport() is the best solution because Cygwin keeps
> track of the last port number it has allocated *to any Cygwin program*.
> This is the only approach that can deal with multiple programs and multiple
> calls in one program.  So we need to nail down why it doesn't seem to work
> for you.

Apart from all the above, there may still be a problem in the given scenario.

To reiterate the problem we observe:

- socket()
- setsockopt (SO_REUSEADDR)
- bind() succeeds
- connect() fails with EADDRINUSE while socket is still in TIME_WAIT

using bindresvport in place of bind only marginally changes the
situation, in particular if the second parameter is set and requests a
port number != 0.  What happens in that case is that bindresvport calls
bind with this port number and checks if bind returns EADDRINUSE.

Only then it tries to bind other port numbers in the reserved range.
But we now know that bind will never return EADDINUSE if the SO_REUSEADDR
socket option has been set.

Even assuming the process calls bindresvport(sock, NULL) we may end up
returning a port number already in use if the process is the only Cygwin
process on the system.  The reason is that Cygwin uses a round robin
approach which relies on having a globally shared value called
last_used_bindresvport.  If the process is the only Cygwin process on
the system, this information is lost after exiting the process, so the
next process will start with the same start port number and bind will
again fail to notice the client with EADDRINUSE.

What potential solutions to this problem do we have?

- bindresvport could enforce SO_EXCLUSIVEADDRUSE temporarily to make
  sure bind fails.

- bindresvport could check every local address for being free prior
  to calling bind.  However, there's a potential race here.

- DisconnectEx?  Never tried this Winsock extension but it might be
  worth a shot.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-02-05  8:19 PAULUS, Raimund, TI-ABN
@ 2018-02-05 10:29 ` Mark Geisert
  2018-02-05 11:26   ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: Mark Geisert @ 2018-02-05 10:29 UTC (permalink / raw)
  To: cygwin

PAULUS, Raimund, TI-ABN wrote:
> Hello Mark,
>
> unfortunately i must correct my statement from Friday.
> The program works, but only if the connections to the server are established in a loop inside the program.
> If the program ends and you start it anew, a connection is not possible for a long time. you have to wait before you can establish a new connection.

That isn't what I saw in my testing.  At one point I had three copies of your 
test_rpc.exe running simultaneously and they all were able to establish 20 
connections and the allocated port numbers were interleaved.

Are you running your test programs directly from a Windows Command Prompt or 
from one of the Cygwin shells like bash?

> Actually only our approaches in the original bindresvport() seem to work for all cases.
> You have proposed to use the static variable usecount in bindresvport(). But how is the value of the variable handled if the program starts anew. Is it possible to get an used portnumber
> and run in EADDRINUSE?

You must understand that none of the libtirpc approaches is guaranteed to work 
100% of the time.  The problem is that without a lot of extra work we can't get 
libtirpc to "know" which ports to avoid.  Our approaches are just different 
strategies for avoiding a port collision, with different chances of working.

Libtirpc's original approach is essentially to have a range of port numbers it 
will try, 600 thru 1023, start with one of them randomly (based on the pid of 
the calling process), increment by one on each use.  This won't work when you're 
calling bindresvport() multiple times within one program because it starts from 
the same port number each time.

My "usecount" modification changes things so we start with the same port number 
as before but increment each time we bindresvport().  Good for one program 
making multiple calls and sort of good for multiple programs at same time.. but 
there is a chance of port number collision between the programs.

Using Cygwin's bindresvport() is the best solution because Cygwin keeps track of 
the last port number it has allocated *to any Cygwin program*.  This is the only 
approach that can deal with multiple programs and multiple calls in one program. 
  So we need to nail down why it doesn't seem to work for you.

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-02-05  8:19 PAULUS, Raimund, TI-ABN
  2018-02-05 10:29 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-02-05  8:19 UTC (permalink / raw)
  To: cygwin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 3428 bytes --]

Hello Mark,

unfortunately i must correct my statement from Friday.
The program works, but only if the connections to the server are established in a loop inside the program.
If the program ends and you start it anew, a connection is not possible for a long time. you have to wait before you can establish a new connection.

Actually only our approaches in the original bindresvport() seem to work for all cases.
You have proposed to use the static variable usecount in bindresvport(). But how is the value of the variable handled if the program starts anew. Is it possible to get an used portnumber 
and run in EADDRINUSE?

Greetings
Raimund

-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von PAULUS, Raimund, TI-ABN
Gesendet: Freitag, 2. Februar 2018 13:58
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

Hi Mark,

it works. Maybe it's the best solution for the problem.

Greetings

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Freitag, 2. Februar 2018 09:11
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

Mark Geisert wrote:
> Corinna Vinschen wrote:
>> On Jan 31 00:15, Mark Geisert wrote:
>>> PAULUS, Raimund, TI-ABN wrote:
>>>> Hi Mark,
>>>>
>>>> in my email
>>>> (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i described 2 approaches. I prefer  nr 1.
>>>> Here the part of the source in bindresvport.c:
>>>> [...]
> [...]
>>
>> I'm a bit puzzled here in terms of using your own bindresvport.  
>> Cygwin implements bindresvport{_sa} for quite some time, 2006 or earlier.
>
> Yeesh; I did not know that.  Thanks for pointing that out. So that 
> means there's another possible way to try solving the OP's issue: by 
> using Cygwin's
> bindresvport* in place of the one supplied with libtirpc.
>
> If we see the OP's issue with Cygwin's bindresvport*, I think it makes 
> more sense to patch libtirpc than to change Cygwin's bindresvport*.
> The crux of OP's issue is that libtirpc's code expects to see 
> EADDRINUSE errors from bind() whereas on Cygwin they aren't often seen until you connect().
>
> I'll look into using Cygwin's bindresvport() in the next day or two.

My testing shows that OP's original issue goes away when libtirpc is compiled to use Cygwin's bindresvport() directly rather than using its own version of that function.

Raimund, could you try this newest possible solution?  Before the first #include in bindresvport.c, add the line
     #ifndef __CYGWIN__
and at the end of the file, add the line
     #endif
Then rebuild your libtirpc and your test programs linking against it, then run your tests.  If this proves to solve your original problem then I'll submit a patch of libtirpc to the Cygwin package maintainer.

Thank you,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

\x03B‹KCB”\x1c›Ø›\x19[H\x1c™\^[ܝ\x1cΈ\b\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÜ\x1c›Ø›\x19[\Ëš\x1d^[[\x03B‘TNˆ\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÙ˜\KÃB‘^[ØÝ[Y[\x18]\x1a[ÛŽˆ\b\b\b\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÙ^[ØÜËš\x1d^[[\x03B•[œÝXœØÜšX™H\x1a[™›Îˆ\b\b\b\b\b\x1a\x1d\x1d\x1c\x0e‹ËØÞYÝÚ[‹˜ÛÛKÛ[\vÈÝ[œÝXœØÜšX™K\Ú[\^[\x19CBƒB

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-02-02 12:58 PAULUS, Raimund, TI-ABN
  0 siblings, 0 replies; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-02-02 12:58 UTC (permalink / raw)
  To: cygwin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2515 bytes --]

Hi Mark,

it works. Maybe it's the best solution for the problem.

Greetings

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Freitag, 2. Februar 2018 09:11
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

Mark Geisert wrote:
> Corinna Vinschen wrote:
>> On Jan 31 00:15, Mark Geisert wrote:
>>> PAULUS, Raimund, TI-ABN wrote:
>>>> Hi Mark,
>>>>
>>>> in my email 
>>>> (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i described 2 approaches. I prefer  nr 1.
>>>> Here the part of the source in bindresvport.c:
>>>> [...]
> [...]
>>
>> I'm a bit puzzled here in terms of using your own bindresvport.  
>> Cygwin implements bindresvport{_sa} for quite some time, 2006 or earlier.
>
> Yeesh; I did not know that.  Thanks for pointing that out. So that 
> means there's another possible way to try solving the OP's issue: by 
> using Cygwin's
> bindresvport* in place of the one supplied with libtirpc.
>
> If we see the OP's issue with Cygwin's bindresvport*, I think it makes 
> more sense to patch libtirpc than to change Cygwin's bindresvport*.  
> The crux of OP's issue is that libtirpc's code expects to see 
> EADDRINUSE errors from bind() whereas on Cygwin they aren't often seen until you connect().
>
> I'll look into using Cygwin's bindresvport() in the next day or two.

My testing shows that OP's original issue goes away when libtirpc is compiled to use Cygwin's bindresvport() directly rather than using its own version of that function.

Raimund, could you try this newest possible solution?  Before the first #include in bindresvport.c, add the line
     #ifndef __CYGWIN__
and at the end of the file, add the line
     #endif
Then rebuild your libtirpc and your test programs linking against it, then run your tests.  If this proves to solve your original problem then I'll submit a patch of libtirpc to the Cygwin package maintainer.

Thank you,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

\0ТÒÐÐ¥\a&ö&ÆVÒ\a&W\x06÷'G3¢\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒ÷\a&ö&ÆV×2æ‡FÖÀФd\x15\x13¢\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöf\x17\x12ðФFö7VÖVçF\x17F–öã¢\x02\x02\x02\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöFö72æ‡FÖÀÐ¥Vç7V'67&–&R\x06–æfó¢\x02\x02\x02\x02\x02\x06‡GG\x03¢òö7–wv–âæ6öÒöÖÂò7Vç7V'67&–&R×6–×\x06ÆPРÐ

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-01-31  9:35     ` Mark Geisert
@ 2018-02-02  8:11       ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2018-02-02  8:11 UTC (permalink / raw)
  To: cygwin

Mark Geisert wrote:
> Corinna Vinschen wrote:
>> On Jan 31 00:15, Mark Geisert wrote:
>>> PAULUS, Raimund, TI-ABN wrote:
>>>> Hi Mark,
>>>>
>>>> in my email (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i
>>>> described 2 approaches. I prefer  nr 1.
>>>> Here the part of the source in bindresvport.c:
>>>> [...]
> [...]
>>
>> I'm a bit puzzled here in terms of using your own bindresvport.  Cygwin
>> implements bindresvport{_sa} for quite some time, 2006 or earlier.
>
> Yeesh; I did not know that.  Thanks for pointing that out. So that means there's
> another possible way to try solving the OP's issue: by using Cygwin's
> bindresvport* in place of the one supplied with libtirpc.
>
> If we see the OP's issue with Cygwin's bindresvport*, I think it makes more
> sense to patch libtirpc than to change Cygwin's bindresvport*.  The crux of OP's
> issue is that libtirpc's code expects to see EADDRINUSE errors from bind()
> whereas on Cygwin they aren't often seen until you connect().
>
> I'll look into using Cygwin's bindresvport() in the next day or two.

My testing shows that OP's original issue goes away when libtirpc is compiled to 
use Cygwin's bindresvport() directly rather than using its own version of that 
function.

Raimund, could you try this newest possible solution?  Before the first #include 
in bindresvport.c, add the line
     #ifndef __CYGWIN__
and at the end of the file, add the line
     #endif
Then rebuild your libtirpc and your test programs linking against it, then run 
your tests.  If this proves to solve your original problem then I'll submit a 
patch of libtirpc to the Cygwin package maintainer.

Thank you,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-01-31  9:11   ` Corinna Vinschen
@ 2018-01-31  9:35     ` Mark Geisert
  2018-02-02  8:11       ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: Mark Geisert @ 2018-01-31  9:35 UTC (permalink / raw)
  To: cygwin

Corinna Vinschen wrote:
> On Jan 31 00:15, Mark Geisert wrote:
>> PAULUS, Raimund, TI-ABN wrote:
>>> Hi Mark,
>>>
>>> in my email (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i described 2 approaches. I prefer  nr 1.
>>> Here the part of the source in bindresvport.c:
>>> [...]
[...]
>
> I'm a bit puzzled here in terms of using your own bindresvport.  Cygwin
> implements bindresvport{_sa} for quite some time, 2006 or earlier.

Yeesh; I did not know that.  Thanks for pointing that out. So that means there's 
another possible way to try solving the OP's issue: by using Cygwin's 
bindresvport* in place of the one supplied with libtirpc.

If we see the OP's issue with Cygwin's bindresvport*, I think it makes more 
sense to patch libtirpc than to change Cygwin's bindresvport*.  The crux of OP's 
issue is that libtirpc's code expects to see EADDRINUSE errors from bind() 
whereas on Cygwin they aren't often seen until you connect().

I'll look into using Cygwin's bindresvport() in the next day or two.
Thanks all,

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-01-31  8:15 ` Mark Geisert
@ 2018-01-31  9:11   ` Corinna Vinschen
  2018-01-31  9:35     ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: Corinna Vinschen @ 2018-01-31  9:11 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 1836 bytes --]

On Jan 31 00:15, Mark Geisert wrote:
> PAULUS, Raimund, TI-ABN wrote:
> > Hi Mark,
> > 
> > in my email (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i described 2 approaches. I prefer  nr 1.
> > Here the part of the source in bindresvport.c:
> > [...]
> > This causes bind() to search an unused port. I use libtirpc with this fix since several weeks and it works for me. I don't know an other way (fixing Cygwin) to success.
> > The RPC-client on my pc is started every few minutes and has to connect to the RPC-server.  Without the fix libtirpc is not usable and I have to use Cygwin 1.5.18 with the old librpc.
> [...]
> 
> Hi Raimund,
> Thanks for attaching the complete source for your modified bindresvport.c.
> I had been treating your setting of port to 0 as a workaround rather than as
> a solution.  My misunderstanding.
> 
> We can't solve the issue that way because when bind() is called with a
> zeroed port number, it picks a random port number that's often outside the
> range of ports bindresvport() is supposed to return (i.e., a port between
> STARTPORT and ENDPORT).
> 
> I thought of something similar to your idea but obeying the bindresvport()
> semantics.  I add a static short value named 'usecount' to the function's
> local variables.  Mid-function, I have this code to choose a port number:
>     if (port == 0) {
>         port = ((getpid() + usecount++) % NPORTS) + STARTPORT;
>     }
> 
> Can you try this with your testcase(s) and make sure it works for you?

I'm a bit puzzled here in terms of using your own bindresvport.  Cygwin
implements bindresvport{_sa} for quite some time, 2006 or earlier.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-01-30 10:07 PAULUS, Raimund, TI-ABN
@ 2018-01-31  8:15 ` Mark Geisert
  2018-01-31  9:11   ` Corinna Vinschen
  0 siblings, 1 reply; 34+ messages in thread
From: Mark Geisert @ 2018-01-31  8:15 UTC (permalink / raw)
  To: cygwin

PAULUS, Raimund, TI-ABN wrote:
> Hi Mark,
>
> in my email (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i described 2 approaches. I prefer  nr 1.
> Here the part of the source in bindresvport.c:
> ------------------------------------------------------------------------------------------------------------------
>         if (port == 0) {
>                 port = (getpid() % NPORTS) + STARTPORT;
>         }
>         res = -1;
>         errno = EADDRINUSE;
>
> /* fix for bind() */
> port = 0;
>                 again:
>         for (i = 0; i < nports; ++i) {
>                 *portp = htons(port++);
>                  if (port > endport)
>                         port = startport;
>                 res = bind(sd, sa, salen);
>                 if (res >= 0 || errno != EADDRINUSE)
>                         break;
>         }
>         if (i == nports && startport != LOWPORT) {
>             startport = LOWPORT;
>             endport = STARTPORT - 1;
>             nports = STARTPORT - LOWPORT;
>             port = LOWPORT + port % (STARTPORT - LOWPORT);
>             goto again;
>         }
>         mutex_unlock(&port_lock);
>
>         return (res);
> }
> -------------------------------------------------------------------------------------------------------
>
> This causes bind() to search an unused port. I use libtirpc with this fix since several weeks and it works for me. I don't know an other way (fixing Cygwin) to success.
> The RPC-client on my pc is started every few minutes and has to connect to the RPC-server.  Without the fix libtirpc is not usable and I have to use Cygwin 1.5.18 with the old librpc.
[...]

Hi Raimund,
Thanks for attaching the complete source for your modified bindresvport.c.  I 
had been treating your setting of port to 0 as a workaround rather than as a 
solution.  My misunderstanding.

We can't solve the issue that way because when bind() is called with a zeroed 
port number, it picks a random port number that's often outside the range of 
ports bindresvport() is supposed to return (i.e., a port between STARTPORT and 
ENDPORT).

I thought of something similar to your idea but obeying the bindresvport() 
semantics.  I add a static short value named 'usecount' to the function's local 
variables.  Mid-function, I have this code to choose a port number:
     if (port == 0) {
         port = ((getpid() + usecount++) % NPORTS) + STARTPORT;
     }

Can you try this with your testcase(s) and make sure it works for you?

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-01-30 10:07 PAULUS, Raimund, TI-ABN
  2018-01-31  8:15 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-01-30 10:07 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 3510 bytes --]

Hi Mark,

in my email (https://sourceware.org/ml/cygwin/2017-12/msg00194.html) i described 2 approaches. I prefer  nr 1.
Here the part of the source in bindresvport.c:
------------------------------------------------------------------------------------------------------------------
        if (port == 0) {
                port = (getpid() % NPORTS) + STARTPORT;
        }
        res = -1;
        errno = EADDRINUSE;

/* fix for bind() */
port = 0;
                again:
        for (i = 0; i < nports; ++i) {
                *portp = htons(port++);
                 if (port > endport)
                        port = startport;
                res = bind(sd, sa, salen);
                if (res >= 0 || errno != EADDRINUSE)
                        break;
        }
        if (i == nports && startport != LOWPORT) {
            startport = LOWPORT;
            endport = STARTPORT - 1;
            nports = STARTPORT - LOWPORT;
            port = LOWPORT + port % (STARTPORT - LOWPORT);
            goto again;
        }
        mutex_unlock(&port_lock);

        return (res);
}
-------------------------------------------------------------------------------------------------------

This causes bind() to search an unused port. I use libtirpc with this fix since several weeks and it works for me. I don't know an other way (fixing Cygwin) to success.
The RPC-client on my pc is started every few minutes and has to connect to the RPC-server.  Without the fix libtirpc is not usable and I have to use Cygwin 1.5.18 with the old librpc.

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Dienstag, 30. Januar 2018 10:05
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

PAULUS, Raimund, TI-ABN wrote:
> Hi Mark,
> as Corinna wrote in the thread " Cygwin socket option SO_REUSEADDR operates unlike Linux", the cause for the problem in libtirpc is Microsofts implementation of socket handling. If i implement a simple socket client, that is not so much of an issue, because I call the functions separately and can handle the error. Moreover in this case bind() is not necessary.
> But in the case of libtirpc the implementation of clnttcp_create() determines the sequence of bind() and connect() for the local port and you cannot correct the error of bind() after the call of connect(). Therefore I think best is to set the port number to zero (port = 0) before the call to bind().
>
> Raimund
>
>
> -----Ursprüngliche Nachricht-----
> Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im 
> Auftrag von PAULUS, Raimund, TI-ABN
> Gesendet: Dienstag, 9. Januar 2018 09:14
> An: cygwin@cygwin.com
> Betreff: WG: AW: RPC clnt_create() adress already in use
[...]

Hi Raimund,
Where, exactly, would you set the port number to zero?  I can imagine how this would solve the problem you're seeing but I'm concerned about other use cases.

It also seems a little odd to me we'd be making a Cygwin-specific patch rather than "fixing" Cygwin itself so the patch would not be necessary.  But I don't feel strongly either way here.  libtirpc already has Cygwin-specific patches.

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


[-- Attachment #2: bindresvport.c --]
[-- Type: text/plain, Size: 6301 bytes --]

/*
 * Copyright (c) 2009, Sun Microsystems, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name of Sun Microsystems, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */


/*
 * Copyright (c) 1987 by Sun Microsystems, Inc.
 *
 * Portions Copyright(C) 1996, Jason Downs.  All rights reserved.
 */

#include <sys/types.h>
#include <sys/socket.h>

#include <netdb.h>
#include <netinet/in.h>

#include <errno.h>
#include <string.h>
#include <unistd.h>

#include <rpc/rpc.h>

#include <string.h>
#include <reentrant.h>

extern pthread_mutex_t port_lock;

/*
 * Bind a socket to a privileged IP port
 */
int
bindresvport(sd, sin)
        int sd;
        struct sockaddr_in *sin;
{
        return bindresvport_sa(sd, (struct sockaddr *)sin);
}

#if defined(__linux__) || defined(__CYGWIN__)

#define STARTPORT 600
#define LOWPORT 512
#define ENDPORT (IPPORT_RESERVED - 1)
#define NPORTS  (ENDPORT - STARTPORT + 1)

int
bindresvport_sa(sd, sa)
        int sd;
        struct sockaddr *sa;
{
        int res, af;
        struct sockaddr_storage myaddr;
	struct sockaddr_in *sin;
#ifdef INET6
	struct sockaddr_in6 *sin6;
#endif
	u_int16_t *portp;
	static u_int16_t port;
	static short startport = STARTPORT;
	socklen_t salen;
	int nports;
	int endport = ENDPORT;
	int i;

	mutex_lock(&port_lock);
	nports = ENDPORT - startport + 1;

        if (sa == NULL) {
                salen = sizeof(myaddr);
                sa = (struct sockaddr *)&myaddr;

                if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
                    mutex_unlock(&port_lock);
                    return -1;      /* errno is correctly set */
                }

                af = myaddr.ss_family;
        } else
                af = sa->sa_family;

        switch (af) {
        case AF_INET:
		sin = (struct sockaddr_in *)sa;
                salen = sizeof(struct sockaddr_in);
                port = ntohs(sin->sin_port);
		portp = &sin->sin_port;
		break;
#ifdef INET6
        case AF_INET6:
		sin6 = (struct sockaddr_in6 *)sa;
                salen = sizeof(struct sockaddr_in6);
                port = ntohs(sin6->sin6_port);
                portp = &sin6->sin6_port;
                break;
#endif
        default:
                errno = EPFNOSUPPORT;
                mutex_unlock(&port_lock);
                return (-1);
        }
        sa->sa_family = af;

        if (port == 0) {
                port = (getpid() % NPORTS) + STARTPORT;
        }
        res = -1;
        errno = EADDRINUSE;
/* fix for bind() */
port = 0;
		again:
        for (i = 0; i < nports; ++i) {
                *portp = htons(port++);
                 if (port > endport) 
                        port = startport;
                res = bind(sd, sa, salen);
		if (res >= 0 || errno != EADDRINUSE)
	                break;
        }
	if (i == nports && startport != LOWPORT) {
	    startport = LOWPORT;
	    endport = STARTPORT - 1;
	    nports = STARTPORT - LOWPORT;
	    port = LOWPORT + port % (STARTPORT - LOWPORT);
	    goto again;
	}
	mutex_unlock(&port_lock);

        return (res);
}
#else

#define IP_PORTRANGE 19
#define IP_PORTRANGE_LOW 2

/*
 * Bind a socket to a privileged IP port
 */
int
bindresvport_sa(sd, sa)
	int sd;
	struct sockaddr *sa;
{
	int old, error, af;
	struct sockaddr_storage myaddr;
	struct sockaddr_in *sin;
#ifdef INET6
	struct sockaddr_in6 *sin6;
#endif
	int proto, portrange, portlow;
	u_int16_t *portp;
	socklen_t salen;

	if (sa == NULL) {
		salen = sizeof(myaddr);
		sa = (struct sockaddr *)&myaddr;

		if (getsockname(sd, sa, &salen) == -1)
			return -1;	/* errno is correctly set */

		af = sa->sa_family;
		memset(sa, 0, salen);
	} else
		af = sa->sa_family;

	switch (af) {
	case AF_INET:
		proto = IPPROTO_IP;
		portrange = IP_PORTRANGE;
		portlow = IP_PORTRANGE_LOW;
		sin = (struct sockaddr_in *)sa;
		salen = sizeof(struct sockaddr_in);
		portp = &sin->sin_port;
		break;
#ifdef INET6
	case AF_INET6:
		proto = IPPROTO_IPV6;
		portrange = IPV6_PORTRANGE;
		portlow = IPV6_PORTRANGE_LOW;
		sin6 = (struct sockaddr_in6 *)sa;
		salen = sizeof(struct sockaddr_in6);
		portp = &sin6->sin6_port;
		break;
#endif
	default:
		errno = EPFNOSUPPORT;
		return (-1);
	}
	sa->sa_family = af;

	if (*portp == 0) {
		socklen_t oldlen = sizeof(old);

		error = getsockopt(sd, proto, portrange, &old, &oldlen);
		if (error < 0)
			return (error);

		error = setsockopt(sd, proto, portrange, &portlow,
		    sizeof(portlow));
		if (error < 0)
			return (error);
	}

	error = bind(sd, sa, salen);

	if (*portp == 0) {
		int saved_errno = errno;

		if (error < 0) {
			if (setsockopt(sd, proto, portrange, &old,
			    sizeof(old)) < 0)
				errno = saved_errno;
			return (error);
		}

		if (sa != (struct sockaddr *)&myaddr) {
			/* Hmm, what did the kernel assign? */
			if (getsockname(sd, sa, &salen) < 0)
				errno = saved_errno;
			return (error);
		}
	}
	return (error);
}
#endif

[-- Attachment #3: Type: text/plain, Size: 219 bytes --]


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2018-01-30  7:01 PAULUS, Raimund, TI-ABN
@ 2018-01-30  9:05 ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2018-01-30  9:05 UTC (permalink / raw)
  To: cygwin

PAULUS, Raimund, TI-ABN wrote:
> Hi Mark,
> as Corinna wrote in the thread " Cygwin socket option SO_REUSEADDR operates unlike Linux", the cause for the problem in libtirpc is Microsofts implementation of socket handling. If i implement a simple socket client, that is not so much of an issue, because I call the functions separately and can handle the error. Moreover in this case bind() is not necessary.
> But in the case of libtirpc the implementation of clnttcp_create() determines the sequence of bind() and connect() for the local port and you cannot correct the error of bind() after the call of connect(). Therefore I think best is to set the port number to zero (port = 0) before the call to bind().
>
> Raimund
>
>
> -----Ursprüngliche Nachricht-----
> Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von PAULUS, Raimund, TI-ABN
> Gesendet: Dienstag, 9. Januar 2018 09:14
> An: cygwin@cygwin.com
> Betreff: WG: AW: RPC clnt_create() adress already in use
[...]

Hi Raimund,
Where, exactly, would you set the port number to zero?  I can imagine how this 
would solve the problem you're seeing but I'm concerned about other use cases.

It also seems a little odd to me we'd be making a Cygwin-specific patch rather 
than "fixing" Cygwin itself so the patch would not be necessary.  But I don't 
feel strongly either way here.  libtirpc already has Cygwin-specific patches.

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2018-01-30  7:01 PAULUS, Raimund, TI-ABN
  2018-01-30  9:05 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2018-01-30  7:01 UTC (permalink / raw)
  To: cygwin

Hi Mark,
as Corinna wrote in the thread " Cygwin socket option SO_REUSEADDR operates unlike Linux", the cause for the problem in libtirpc is Microsofts implementation of socket handling. If i implement a simple socket client, that is not so much of an issue, because I call the functions separately and can handle the error. Moreover in this case bind() is not necessary.
But in the case of libtirpc the implementation of clnttcp_create() determines the sequence of bind() and connect() for the local port and you cannot correct the error of bind() after the call of connect(). Therefore I think best is to set the port number to zero (port = 0) before the call to bind().

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von PAULUS, Raimund, TI-ABN
Gesendet: Dienstag, 9. Januar 2018 09:14
An: cygwin@cygwin.com
Betreff: WG: AW: RPC clnt_create() adress already in use

Hi Mark,

i have just tested it with the client-program from my email from December 29. The server-program is running on a linux-machine (SuSE Enterprise).
I compiled and linked the client.exe in Cygwin 1.5.18 on a PC with Windows XP SP3 and it works (loop 100 times). It was running in the bash-shell.
Thereafter I copied the client.exe to a Laptop with Windows 7 Home Premium. I started the program from the command prompt (cmd.exe) because rxvt doesn't work. 
The program works (loop 100 times).

Greetings

Raimund



-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Dienstag, 9. Januar 2018 05:52
An: cygwin@cygwin.com
Betreff: Re: AW: RPC clnt_create() adress already in use

Hi Raimund,
I think I might have an idea where the root cause is.  But first I want to revisit your very first email on this subject, from last September 22.  You mentioned test results from various Cygwin versions vs various Windows versions.

Are you absolutely sure your test program ran correctly on Cygwin 1.5.18 on
*both* Windows XP and Windows 7?

The reason I ask is that Windows' handling of socket option SO_REUSEADDR has changed over time and Cygwin has had to make accommodations to keep up.  There might possibly be a need to revisit this within Cygwin.

I want to test a possible solution within the Cygwin DLL on my test machine but it has another two days to go on a factorization problem it's running (under Cygwin).  So I will respond again after I test.
Thank you,

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2017-09-29  9:52 PAULUS, Raimund, TI-ABN
@ 2017-09-29 17:36 ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2017-09-29 17:36 UTC (permalink / raw)
  To: cygwin

PAULUS, Raimund, TI-ABN wrote:
> Hello Mark,
>
> i downloaded the sources of libtirpc from this url: https://sourceforge.net/projects/libtirpc/files/libtirpc/1.0.1/ and unpacked it in the local subdirectory libtirpc-1.0.1.
> I had to make the following changes:
>
> libtirpc-1.0.1/src/clnt_bcast.c (because POLLRDNORM, POLLRDBAND are already defined in /usr/include/sys/poll.h) :
>
> --> #ifndef POLLRDNORM
> --> # define POLLRDNORM     0x040           /* Normal data may be read.  */
> --> # define POLLRDBAND     0x080           /* Priority data may be read.  */
> --> #endif
>
> libtirpc-1.0.1/tirpc/rpc/xdr.h (typedefs where missed):
>
> --> #include <rpc/types.h>
>
> --> typedef __uint64_t      u_quad_t;
> --> typedef __int64_t       quad_t;
>
>
> I linked the necessary source files with my testprogram:
>
> gcc -D__GLIBC__ -D__linux__ -I/c/dh-progs/tstdir/libtirpc-1.0.1/tirpc \
> tst_rpc.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_bcast.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_dg.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_generic.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_perror.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_vc.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_callmsg.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_commondata.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_generic.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_prot.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/rpcb_clnt.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/rpcb_prot.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr.c  \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_array.c  \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_mem.c  \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_rec.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_reference.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/getnetconfig.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/getnetpath.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/auth_none.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/auth_unix.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/authunix_prot.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/mt_misc.c \
> /c/dh-progs/tstdir/libtirpc-1.0.1/src/debug.c \
> -o tst_rpc-libtirpc-1-0-1
>
> The program works perfectly (no errors is test cases 1 and 2).
>
> I assume, there must be a difference between the downloaded lib-files and the Cygwin-libtirpc.

Thank you Raimund for debugging this to the root cause.  Cygwin claims to be 
providing libtirpc 1.0.1 so I suspect you're correct about the cause.  I will 
figure out what the differences are and take the issue up with the Cygwin 
libtirpc maintainer.  Congrats on solving the problem yourself!
Thanks again,

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2017-09-29  9:52 PAULUS, Raimund, TI-ABN
  2017-09-29 17:36 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2017-09-29  9:52 UTC (permalink / raw)
  To: cygwin

Hello Mark,

i downloaded the sources of libtirpc from this url: https://sourceforge.net/projects/libtirpc/files/libtirpc/1.0.1/ and unpacked it in the local subdirectory libtirpc-1.0.1.
I had to make the following changes:

libtirpc-1.0.1/src/clnt_bcast.c (because POLLRDNORM, POLLRDBAND are already defined in /usr/include/sys/poll.h) :

--> #ifndef POLLRDNORM
--> # define POLLRDNORM     0x040           /* Normal data may be read.  */
--> # define POLLRDBAND     0x080           /* Priority data may be read.  */
--> #endif

libtirpc-1.0.1/tirpc/rpc/xdr.h (typedefs where missed):

--> #include <rpc/types.h>

--> typedef __uint64_t      u_quad_t;
--> typedef __int64_t       quad_t;


I linked the necessary source files with my testprogram:

gcc -D__GLIBC__ -D__linux__ -I/c/dh-progs/tstdir/libtirpc-1.0.1/tirpc \
tst_rpc.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_bcast.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_dg.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_generic.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_perror.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/clnt_vc.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_callmsg.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_commondata.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_generic.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/rpc_prot.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/rpcb_clnt.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/rpcb_prot.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr.c  \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_array.c  \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_mem.c  \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_rec.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/xdr_reference.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/getnetconfig.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/getnetpath.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/auth_none.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/auth_unix.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/authunix_prot.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/mt_misc.c \
/c/dh-progs/tstdir/libtirpc-1.0.1/src/debug.c \
-o tst_rpc-libtirpc-1-0-1

The program works perfectly (no errors is test cases 1 and 2).

I assume, there must be a difference between the downloaded lib-files and the Cygwin-libtirpc.

Raimund Paulus


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Mittwoch, 27. September 2017 11:50
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

Hello Raimund,
Let's keep this on the mailing list please.

PAULUS, Raimund, TI-ABN wrote:
> Hallo Mark Geisert,
>
> many thanks for your answer. I supposed this too.
>
> I included in my source code the following function calls after clnt_create():
>
> int fd = 0;
> bool bool_ret = clnt_control(cl, CLGET_FD, &fd); if(bool_ret == true) {
>   printf("fd: %d\n", fd);
>
>   int enable = 1;
>   retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
>   if(retval < 0)
>     fprintf(stderr, "Fehler setsockopt(): %s\n", strerror(errno)); }
>
> The function clnt_control() delivers the socket of the RPC-Client-Handle.
> The result is the same as before. Moreover i think, the effect of setsockopt() would be valid only during the process is running (my test scenarios 1 and 2).
> But it wouldn't change anything regarding my test scenario 3 (several restarts).
>
> Raimund

I looked through the libtirpc source code and nowhere is SO_REUSEADDR being set. 
  You are on the right track with how to do it, but by the time clnt_create() returns to you it is already too late.  As far as I can tell there is no way to get access to the socket between the time it's created within libtirpc and the time it's made available to you by clnt_create().

I did try running your testcase (thanks for supplying that) but I don't have a local machine running RPC services and don't wish to poke at random machines on the Internet ;-).  I had to compile it as so:
     gcc -g -o test_rpc -I/usr/include/tirpc test_rpc.c -ltirpc You are taking care to compile against the correct RPC-package includes and link against the correct RPC-package libraries, yes?

Speculation: There might be a way to decompose what clnt_create() does into other libtirpc functions that accomplish the same thing, but in smaller pieces such that you could set the socket option before bind() is called.  That would be a fair amount of work though and given my cursory look at the source I don't know if it's even possible.

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2017-09-27 12:51 PAULUS, Raimund, TI-ABN
  0 siblings, 0 replies; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2017-09-27 12:51 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

Hello Mark,

i compiled and linked just as you.
As i mentioned in an other email, if I use socket-connections in the same manner with a socket-service, in don't need to setsockopt(.., SO_REUSEADDR, ...) and it works.

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Mittwoch, 27. September 2017 11:50
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

Hello Raimund,
Let's keep this on the mailing list please.

PAULUS, Raimund, TI-ABN wrote:
> Hallo Mark Geisert,
>
> many thanks for your answer. I supposed this too.
>
> I included in my source code the following function calls after clnt_create():
>
> int fd = 0;
> bool bool_ret = clnt_control(cl, CLGET_FD, &fd); if(bool_ret == true) {
>   printf("fd: %d\n", fd);
>
>   int enable = 1;
>   retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
>   if(retval < 0)
>     fprintf(stderr, "Fehler setsockopt(): %s\n", strerror(errno)); }
>
> The function clnt_control() delivers the socket of the RPC-Client-Handle.
> The result is the same as before. Moreover i think, the effect of setsockopt() would be valid only during the process is running (my test scenarios 1 and 2).
> But it wouldn't change anything regarding my test scenario 3 (several restarts).
>
> Raimund

I looked through the libtirpc source code and nowhere is SO_REUSEADDR being set. 
  You are on the right track with how to do it, but by the time clnt_create() returns to you it is already too late.  As far as I can tell there is no way to get access to the socket between the time it's created within libtirpc and the time it's made available to you by clnt_create().

I did try running your testcase (thanks for supplying that) but I don't have a local machine running RPC services and don't wish to poke at random machines on the Internet ;-).  I had to compile it as so:
     gcc -g -o test_rpc -I/usr/include/tirpc test_rpc.c -ltirpc You are taking care to compile against the correct RPC-package includes and link against the correct RPC-package libraries, yes?

Speculation: There might be a way to decompose what clnt_create() does into other libtirpc functions that accomplish the same thing, but in smaller pieces such that you could set the socket option before bind() is called.  That would be a fair amount of work though and given my cursory look at the source I don't know if it's even possible.

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2017-09-25  6:44 PAULUS, Raimund, TI-ABN
@ 2017-09-27  9:50 ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2017-09-27  9:50 UTC (permalink / raw)
  To: cygwin

Hello Raimund,
Let's keep this on the mailing list please.

PAULUS, Raimund, TI-ABN wrote:
> Hallo Mark Geisert,
>
> many thanks for your answer. I supposed this too.
>
> I included in my source code the following function calls after clnt_create():
>
> int fd = 0;
> bool bool_ret = clnt_control(cl, CLGET_FD, &fd); if(bool_ret == true) {
>   printf("fd: %d\n", fd);
>
>   int enable = 1;
>   retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
>   if(retval < 0)
>     fprintf(stderr, "Fehler setsockopt(): %s\n", strerror(errno)); }
>
> The function clnt_control() delivers the socket of the RPC-Client-Handle.
> The result is the same as before. Moreover i think, the effect of setsockopt() would be valid only during the process is running (my test scenarios 1 and 2).
> But it wouldn't change anything regarding my test scenario 3 (several restarts).
>
> Raimund

I looked through the libtirpc source code and nowhere is SO_REUSEADDR being set. 
  You are on the right track with how to do it, but by the time clnt_create() 
returns to you it is already too late.  As far as I can tell there is no way to 
get access to the socket between the time it's created within libtirpc and the 
time it's made available to you by clnt_create().

I did try running your testcase (thanks for supplying that) but I don't have a 
local machine running RPC services and don't wish to poke at random machines on 
the Internet ;-).  I had to compile it as so:
     gcc -g -o test_rpc -I/usr/include/tirpc test_rpc.c -ltirpc
You are taking care to compile against the correct RPC-package includes and link 
against the correct RPC-package libraries, yes?

Speculation: There might be a way to decompose what clnt_create() does into 
other libtirpc functions that accomplish the same thing, but in smaller pieces 
such that you could set the socket option before bind() is called.  That would 
be a fair amount of work though and given my cursory look at the source I don't 
know if it's even possible.

..mark

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
@ 2017-09-25  6:44 PAULUS, Raimund, TI-ABN
  2017-09-27  9:50 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2017-09-25  6:44 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

Hallo Mark Geisert,

many thanks for your answer. I supposed this too.

I included in my source code the following function calls after clnt_create():

int fd = 0;
bool bool_ret = clnt_control(cl, CLGET_FD, &fd); if(bool_ret == true) {
  printf("fd: %d\n", fd);

  int enable = 1;
  retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
  if(retval < 0)
    fprintf(stderr, "Fehler setsockopt(): %s\n", strerror(errno)); }

The function clnt_control() delivers the socket of the RPC-Client-Handle.
The result is the same as before. Moreover i think, the effect of setsockopt() would be valid only during the process is running (my test scenarios 1 and 2). 
But it wouldn't change anything regarding my test scenario 3 (several restarts).

Raimund


-----Ursprüngliche Nachricht-----
Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag von Mark Geisert
Gesendet: Sonntag, 24. September 2017 11:49
An: cygwin@cygwin.com
Betreff: Re: RPC clnt_create() adress already in use

PAULUS, Raimund, TI-ABN wrote:
> In our environment we have a Linux-Server and several Windows-PCs (Windows XP SP3, in the past Windows NT too). On the Linux-Server RPC-Services (Remote Procedure Call) are running, one service for one Windows-PC each. To build the RPC-clients on the Windows-boxes, I used Cygwin 1.5.18 and actually Cygwin 2.5.1 (because we now have Windows 7 too).
>
> The RPC-Client (*.exe) on the Windows-box is started at any time by hand, establishes a connection to the server (clnt_create), executes a few calls to the server (clnt_call), closes the connection (clnt_destroy) and exits. The time-interval between the program starts can be 10 seconds up to 2 minutes.
>
> This worked over many years without any error (Cygwin 1.5.18).
> Now I upgraded to Cygwin 2_5_1 (libtirpc instead librpc) and there are problems. Sometimes the RPC-Client cannot establish a connection to the server. The error message from clnt_spcreateerror():
>
> Remote system error - Address already in use
>
> I think it is "EADDRINUSE".

I can only answer generally as I haven't tried your testcase and don't know anything about either RPC library on Cygwin.  If EADDRINUSE is the error you're getting, it might be due to a difference between libtirpc and the older librpc. 
When a program binds a specific address and port to a socket, uses the socket then later closes it, the system keeps the <address, port> tuple in a "locked" 
state until enough time has passed for the other end of the connection to notice the connection's been closed.  During that time, attempting to bind() with the same address and port will result in EADDRINUSE.  It's a TCP/IP safety mechanism.

If you wish to override that behavior, you set a specific option SO_REUSEADDR on the socket with setsockopt() before you issue the bind().  Perhaps libtirpc is not doing that, though librpc was doing that.  Only way to know is to examine the source to both libraries.  It's possible an strace of a broken session compared to an strace of a working session might shed some light.

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: RPC clnt_create() adress already in use
  2017-09-22  7:22 PAULUS, Raimund, TI-ABN
@ 2017-09-24  9:49 ` Mark Geisert
  0 siblings, 0 replies; 34+ messages in thread
From: Mark Geisert @ 2017-09-24  9:49 UTC (permalink / raw)
  To: cygwin

PAULUS, Raimund, TI-ABN wrote:
> In our environment we have a Linux-Server and several Windows-PCs (Windows XP SP3, in the past Windows NT too). On the Linux-Server RPC-Services (Remote Procedure Call) are running, one service for one Windows-PC each. To build the RPC-clients on the Windows-boxes, I used Cygwin 1.5.18 and actually Cygwin 2.5.1 (because we now have Windows 7 too).
>
> The RPC-Client (*.exe) on the Windows-box is started at any time by hand, establishes a connection to the server (clnt_create), executes a few calls to the server (clnt_call), closes the connection (clnt_destroy) and exits. The time-interval between the program starts can be 10 seconds up to 2 minutes.
>
> This worked over many years without any error (Cygwin 1.5.18).
> Now I upgraded to Cygwin 2_5_1 (libtirpc instead librpc) and there are problems. Sometimes the RPC-Client cannot establish a connection to the server. The error message from clnt_spcreateerror():
>
> Remote system error - Address already in use
>
> I think it is "EADDRINUSE".

I can only answer generally as I haven't tried your testcase and don't know 
anything about either RPC library on Cygwin.  If EADDRINUSE is the error you're 
getting, it might be due to a difference between libtirpc and the older librpc. 
When a program binds a specific address and port to a socket, uses the socket 
then later closes it, the system keeps the <address, port> tuple in a "locked" 
state until enough time has passed for the other end of the connection to notice 
the connection's been closed.  During that time, attempting to bind() with the 
same address and port will result in EADDRINUSE.  It's a TCP/IP safety mechanism.

If you wish to override that behavior, you set a specific option SO_REUSEADDR on 
the socket with setsockopt() before you issue the bind().  Perhaps libtirpc is 
not doing that, though librpc was doing that.  Only way to know is to examine 
the source to both libraries.  It's possible an strace of a broken session 
compared to an strace of a working session might shed some light.

..mark


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 34+ messages in thread

* RPC clnt_create() adress already in use
@ 2017-09-22  7:22 PAULUS, Raimund, TI-ABN
  2017-09-24  9:49 ` Mark Geisert
  0 siblings, 1 reply; 34+ messages in thread
From: PAULUS, Raimund, TI-ABN @ 2017-09-22  7:22 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

[-- Attachment #1: Type: text/plain, Size: 4916 bytes --]

In our environment we have a Linux-Server and several Windows-PCs (Windows XP SP3, in the past Windows NT too). On the Linux-Server RPC-Services (Remote Procedure Call) are running, one service for one Windows-PC each. To build the RPC-clients on the Windows-boxes, I used Cygwin 1.5.18 and actually Cygwin 2.5.1 (because we now have Windows 7 too).

The RPC-Client (*.exe) on the Windows-box is started at any time by hand, establishes a connection to the server (clnt_create), executes a few calls to the server (clnt_call), closes the connection (clnt_destroy) and exits. The time-interval between the program starts can be 10 seconds up to 2 minutes.

This worked over many years without any error (Cygwin 1.5.18).
Now I upgraded to Cygwin 2_5_1 (libtirpc instead librpc) and there are problems. Sometimes the RPC-Client cannot establish a connection to the server. The error message from clnt_spcreateerror():

Remote system error - Address already in use

I think it is "EADDRINUSE".

I wrote a program for tests in Cygwin 1.5.18, 1.7.32 and 2.5.1:

The program reads argv[1] as a sleeptime. If no argv[1] exists, sleeptime has a default value of  10 seconds. Afterwards is a loop (20 times) of the following actions:

-       establish a connection to the server and sleep for 1 second

-       destroy the connection

-       sleep(sleeptime)

test_rpc.c:


/*=================*/
/*  Include-Files  */
/*=================*/
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
/*#include <posix.h>*/
#include <sys/types.h>
#include <sys/stat.h>

#include <rpc/rpc.h>

/*===========================================*/
/*  global definitions                                                              */
/*===========================================*/

char local_errmsg[512];

char host[] = "nazv";
u_int prognum = 0x2000002F;
u_int versnum = 2;
char nettype[] = "tcp";

/*=============================*/
/*  main-program                                     */
/*=============================*/
int main (int argc, char *argv[])
{
int retval = 0;
int sleeptime = 0;
CLIENT *cl;     /* a client handle */

  // read sleep-Time
  if(argc < 2)
  {
    printf("no input for sleep-Time --> default\n");
    sleeptime = 10;
  }
  else
  {
    char *endptr;
    errno = 0;
    sleeptime = (int)strtol(argv[1], &endptr, 10);
    if ( (errno == ERANGE && (sleeptime == LONG_MAX || sleeptime == LONG_MIN))
         || (errno != 0 && sleeptime == 0))
    {
      fprintf(stderr, "input for sleeptime (%s) invalid: %s\n",
                      argv[1], strerror(errno));
      exit(1);
    }
  }

  printf("sleep-Time = %d \n", sleeptime);

  // loop for 20 connection
  for(int i=0; i<20; i++)
  {
    if(!(cl = clnt_create(host, prognum, versnum, nettype)))
    {
      // couldn't start client handle
      sprintf(local_errmsg, "%s: %s", host, clnt_spcreateerror("clnt_create"));
      retval = -1;
      break;
    }

    printf("connection nr. %d established \n", i+1);
    sleep(1);

    clnt_destroy(cl);
    printf("connection closed\n");

    printf("wait for %d sec.\n", sleeptime);
    sleep(sleeptime);

  };

  if(retval < 0)
    fprintf(stderr, "%s\n", local_errmsg);

  return(0);
} // end main()


Test 1: The program is started with argument "60" (sleep = 60 secs.)

Results:

Cygwin 1_5_18 (Windows XP, Windows 7)
The loop is completed without error (20 times the connection was opened and closed).

Cygwin 1_7_32 and 2_5_1 (Windows 7)
After the first connection is closed, a second connection in the loop is not possible (error message above) and the program exits.

RPC-Client on Linux (openSuSe Leap 42.1)
The loop is completed without error (20 times the connection was opened and closed).



Test 2: The program is started with argument "0" (sleep = 0 secs.)

Results:

Cygwin 1_5_18 (Windows XP, Windows 7)
The loop is completed without error (20 times the connection was opened and closed).

Cygwin 1_7_32 and 2_5_1 (Windows 7)
After the first connection is closed, a second connection in the loop is not possible (error message above) and the program exits.

RPC-Client on Linux (openSuSe Leap 42.1)
The loop is completed without error (20 times the connection was opened and closed).



Test 3: The program is started with argument "0" (sleep = 0 secs.)
Windows 7 only
Cygwin 1_7_32 and 2_5_1
After the program exited with the error, the program was immediately restarted. The start was ok (but always the program exited with the known error). But after several starts a new error was there:

Remote system error - Connection timed out


What is the reason for the error? I have to develop RPC-Clients for Windows XP SP3 and Windows 7.


Raimund Paulus


^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2018-03-08 22:30 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-19 16:13 RPC clnt_create() adress already in use PAULUS, Raimund, TI-ABN
2017-12-28  0:03 ` Mark Geisert
  -- strict thread matches above, loose matches on Subject: below --
2018-03-08 11:44 PAULUS, Raimund, TI-ABN
2018-03-08 15:24 ` Corinna Vinschen
2018-03-08 23:00 ` Mark Geisert
2018-03-02 10:39 PAULUS, Raimund, TI-ABN
2018-02-27  9:54 PAULUS, Raimund, TI-ABN
2018-02-27 10:37 ` Corinna Vinschen
2018-02-28  6:00   ` Mark Geisert
2018-02-06 11:29 PAULUS, Raimund, TI-ABN
2018-02-06 14:20 ` Corinna Vinschen
2018-02-07  6:54   ` Mark Geisert
2018-02-05 14:58 PAULUS, Raimund, TI-ABN
2018-02-05  8:19 PAULUS, Raimund, TI-ABN
2018-02-05 10:29 ` Mark Geisert
2018-02-05 11:26   ` Corinna Vinschen
2018-02-05 13:34     ` Corinna Vinschen
2018-02-05 14:06       ` Corinna Vinschen
2018-02-05 20:15         ` Corinna Vinschen
2018-02-02 12:58 PAULUS, Raimund, TI-ABN
2018-01-30 10:07 PAULUS, Raimund, TI-ABN
2018-01-31  8:15 ` Mark Geisert
2018-01-31  9:11   ` Corinna Vinschen
2018-01-31  9:35     ` Mark Geisert
2018-02-02  8:11       ` Mark Geisert
2018-01-30  7:01 PAULUS, Raimund, TI-ABN
2018-01-30  9:05 ` Mark Geisert
2017-09-29  9:52 PAULUS, Raimund, TI-ABN
2017-09-29 17:36 ` Mark Geisert
2017-09-27 12:51 PAULUS, Raimund, TI-ABN
2017-09-25  6:44 PAULUS, Raimund, TI-ABN
2017-09-27  9:50 ` Mark Geisert
2017-09-22  7:22 PAULUS, Raimund, TI-ABN
2017-09-24  9:49 ` Mark Geisert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).