Skip to content

Commit 2167a41

Browse files
committed
Fixed ConnectTimeout behavior
1 parent c20bd50 commit 2167a41

1 file changed

Lines changed: 108 additions & 25 deletions

File tree

src/remote/inet.cpp

Lines changed: 108 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,45 @@ constexpr ULONG DEF_MAX_DATA = 8192;
253253

254254
constexpr int SELECT_TIMEOUT = 60; // Dispatch thread select timeout (sec)
255255

256+
class ForRead
257+
{
258+
public:
259+
static constexpr int SEL_INIT_EVENTS = POLLIN;
260+
static constexpr int SEL_CHECK_MASK = POLLIN;
261+
262+
static fd_set* readSet(fd_set* set)
263+
{
264+
return set;
265+
}
266+
267+
static fd_set* writeSet(fd_set* set)
268+
{
269+
return nullptr;
270+
}
271+
};
272+
273+
class ForWrite
274+
{
275+
public:
276+
static constexpr int SEL_INIT_EVENTS = POLLOUT;
277+
static constexpr int SEL_CHECK_MASK = POLLOUT;
278+
279+
static fd_set* readSet(fd_set* set)
280+
{
281+
return nullptr;
282+
}
283+
284+
static fd_set* writeSet(fd_set* set)
285+
{
286+
return set;
287+
}
288+
};
289+
290+
template <class Traits>
256291
class Select
257292
{
258293
#ifdef HAVE_POLL
259294
private:
260-
static constexpr int SEL_INIT_EVENTS = POLLIN;
261-
static constexpr int SEL_CHECK_MASK = POLLIN;
262295

263296
pollfd* getPollFd(int n)
264297
{
@@ -377,7 +410,7 @@ class Select
377410

378411
if (pf)
379412
{
380-
HandleState ret = pf->events & SEL_CHECK_MASK ? SEL_READY : SEL_NO_DATA;
413+
HandleState ret = pf->events & Traits::SEL_CHECK_MASK ? SEL_READY : SEL_NO_DATA;
381414
pf->events = 0; // unset
382415
return ret;
383416
}
@@ -416,13 +449,13 @@ class Select
416449
FB_SIZE_T pos;
417450
if (slct_poll.find(handle, pos))
418451
{
419-
slct_poll[pos].events = SEL_INIT_EVENTS;
452+
slct_poll[pos].events = Traits::SEL_INIT_EVENTS;
420453
}
421454
else
422455
{
423456
pollfd f;
424457
f.fd = handle;
425-
f.events = SEL_INIT_EVENTS;
458+
f.events = Traits::SEL_INIT_EVENTS;
426459
slct_poll.insert(pos, f);
427460
}
428461
#else
@@ -460,7 +493,7 @@ class Select
460493
for (pollfd* pf = slct_poll.begin(); pf < end; ++pf)
461494
{
462495
pf->revents = pf->events;
463-
if (pf->events & SEL_CHECK_MASK)
496+
if (pf->events & Traits::SEL_CHECK_MASK)
464497
hasRequest = true;
465498
}
466499

@@ -479,15 +512,15 @@ class Select
479512
for (pollfd* pf = slct_poll.begin(); pf < end; ++pf)
480513
{
481514
pf->events = pf->revents;
482-
if (pf->revents & SEL_CHECK_MASK)
515+
if (pf->revents & Traits::SEL_CHECK_MASK)
483516
slct_ready.add(pf);
484517
}
485518
}
486519
#else
487520
#ifdef WIN_NT
488-
slct_count = ::select(FD_SETSIZE, &slct_fdset, NULL, NULL, timeout);
521+
slct_count = ::select(FD_SETSIZE, readSet(&slct_fdset), writeSet(&slct_fdset), NULL, timeout);
489522
#else
490-
slct_count = ::select(slct_width, &slct_fdset, NULL, NULL, timeout);
523+
slct_count = ::select(slct_width, readSet(&slct_fdset), writeSet(&slct_fdset), NULL, timeout);
491524
#endif // WIN_NT
492525
#endif // HAVE_POLL
493526
}
@@ -616,9 +649,9 @@ static rem_port* receive(rem_port*, PACKET *);
616649
static rem_port* select_accept(rem_port*);
617650
static bool is_listener(const rem_port*);
618651

619-
static void select_port(rem_port*, Select*, RemPortPtr&);
652+
static void select_port(rem_port*, Select<ForRead>*, RemPortPtr&);
620653
static bool select_multi(rem_port*, UCHAR* buffer, SSHORT bufsize, SSHORT* length, RemPortPtr&);
621-
static bool select_wait(rem_port*, Select*);
654+
static bool select_wait(rem_port*, Select<ForRead>*);
622655
static int send_full(rem_port*, PACKET *);
623656
static int send_partial(rem_port*, PACKET *);
624657

@@ -667,7 +700,7 @@ ULONG INET_remote_buffer;
667700
static GlobalPtr<Mutex> init_mutex;
668701
static volatile bool INET_initialized = false;
669702
static volatile bool INET_shutting_down = false;
670-
static GlobalPtr<Select> INET_select;
703+
static GlobalPtr<Select<ForRead>> INET_select;
671704
static rem_port* inet_async_receive = NULL;
672705

673706

@@ -1199,13 +1232,63 @@ rem_port* INET_connect(const TEXT* name,
11991232
gds__log("setsockopt: error setting TCP_NODELAY");
12001233
else
12011234
{
1235+
int flags;
1236+
if (port->port_connect_timeout)
1237+
{
1238+
flags = fcntl(port->port_handle, F_GETFL, 0);
1239+
if (flags < 0)
1240+
{
1241+
SOCLOSE(port->port_handle);
1242+
continue;
1243+
}
1244+
1245+
if (fcntl(port->port_handle, F_SETFL, flags | O_NONBLOCK) < 0)
1246+
{
1247+
SOCLOSE(port->port_handle);
1248+
continue;
1249+
}
1250+
}
1251+
12021252
n = connect(port->port_handle, pai->ai_addr, static_cast<socklen_t>(pai->ai_addrlen));
1203-
if (n != -1)
1253+
if (n != -1 || errno == EINPROGRESS)
12041254
{
1205-
port->port_peer_name = host;
1206-
get_peer_info(port);
1207-
if (send_full(port, packet))
1208-
return port;
1255+
bool connected = true;
1256+
if (n == -1 && errno == EINPROGRESS)
1257+
{
1258+
fb_assert(port->port_connect_timeout);
1259+
1260+
timeval timeout {};
1261+
timeout.tv_sec = port->port_connect_timeout;
1262+
1263+
Select<ForWrite> slct;
1264+
slct.set(port->port_handle);
1265+
slct.select(&timeout);
1266+
connected = (slct.getCount() > 0);
1267+
1268+
if (connected)
1269+
{
1270+
int optError;
1271+
socklen_t len = sizeof(optError);
1272+
if (getsockopt(port->port_handle, SOL_SOCKET, SO_ERROR, &optError, &len) < 0)
1273+
connected = false;
1274+
else
1275+
connected = (optError == 0);
1276+
}
1277+
1278+
if (connected)
1279+
{
1280+
if (fcntl(port->port_handle, F_SETFL, flags) < 0)
1281+
connected = false;
1282+
}
1283+
}
1284+
1285+
if (connected)
1286+
{
1287+
port->port_peer_name = host;
1288+
get_peer_info(port);
1289+
if (send_full(port, packet))
1290+
return port;
1291+
}
12091292
}
12101293
}
12111294

@@ -1838,7 +1921,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet)
18381921
timeval timeout {};
18391922
timeout.tv_sec = port->port_connect_timeout;
18401923

1841-
Select slct;
1924+
Select<ForRead> slct;
18421925
slct.set(port->port_channel);
18431926

18441927
int inetErrNo = 0;
@@ -2649,7 +2732,7 @@ static rem_port* select_accept( rem_port* main_port)
26492732
return 0;
26502733
}
26512734

2652-
static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port)
2735+
static void select_port(rem_port* main_port, Select<ForRead>* selct, RemPortPtr& port)
26532736
{
26542737
/**************************************
26552738
*
@@ -2670,23 +2753,23 @@ static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port)
26702753
MutexLockGuard guard(port_mutex, FB_FUNCTION);
26712754
while (true)
26722755
{
2673-
const Select::HandleState result = selct->checkNext(port);
2756+
const Select<ForRead>::HandleState result = selct->checkNext(port);
26742757
if (!port)
26752758
return;
26762759

26772760
switch (result)
26782761
{
2679-
case Select::SEL_BAD:
2762+
case Select<ForRead>::SEL_BAD:
26802763
if (port->port_state == rem_port::BROKEN || (port->port_flags & PORT_connecting))
26812764
continue;
26822765
if (port->port_flags & PORT_async)
26832766
continue;
26842767
return;
26852768

2686-
case Select::SEL_DISCONNECTED:
2769+
case Select<ForRead>::SEL_DISCONNECTED:
26872770
continue;
26882771

2689-
case Select::SEL_READY:
2772+
case Select<ForRead>::SEL_READY:
26902773
port->port_dummy_timeout = port->port_dummy_packet_interval;
26912774
return;
26922775

@@ -2699,7 +2782,7 @@ static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port)
26992782
}
27002783
}
27012784

2702-
static bool select_wait( rem_port* main_port, Select* selct)
2785+
static bool select_wait( rem_port* main_port, Select<ForRead>* selct)
27032786
{
27042787
/**************************************
27052788
*
@@ -3487,7 +3570,7 @@ static bool packet_receive(rem_port* port, UCHAR* buffer, SSHORT buffer_length,
34873570

34883571
if ( !(port->port_flags & PORT_async) )
34893572
{
3490-
Select slct;
3573+
Select<ForRead> slct;
34913574
slct.set(ph);
34923575

34933576
int slct_count;

0 commit comments

Comments
 (0)