powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Unix-системы [игнор отключен] [закрыт для гостей] / Сокеты и тайм аут закрытия
4 сообщений из 4, страница 1 из 1
Сокеты и тайм аут закрытия
    #35521271
GerdaS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
есть такая проблема :

Есть 2 СУБД (postgresql) и приложение для их репликации (pgpool), результаты работы смотрю по логам.

pgpool переодически прослушивает postgresql и если кто отвалился, то выводит его из кластера

если один postgresql просто стопнуть, то pgpool достаточно быстро это замечает,
если положить машину на которой стоит postgresql то pgpool замечает, что вторая субд лежит только мин, через 3

в доке pgpool ничего не нашла, эксперементы тоже пока не дают положительный результат.
Во втором случае , в лог валится следующие
connect_inet_domain_socket: connect() failed: Connection timed out

по src pgpool видно, что у него действо происходит с сокетами, при этом тайм аут задаётся нулевой

Код: plaintext
1.
2.
3.
4.
 
                      struct timeval t;
.....
 528 	
 529 	                t.tv_sec = t.tv_usec =  0 ;



вот тут не совсем понятно, если он нулевой то берётся какое - то системное значение или вообще разрыв никогда не произойдет ? Такое ощущением, что он обнаруживает , отсутствие 2 СУБД когда пытается создать к ней ещё одно подключение..

параметры

tcp_retries2 5
tcp_fin_timeout 20
tcp_syn_retries 5

никакого эффекта не дают.

Чего ещё может влиять на закрытие соединения и как с этим бороться ? RedHat 4 up4


pgpool src
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
/* -*-pgsql-c-*- */
/*
 * $Header: /cvsroot/pgpool/pgpool-II/pool_connection_pool.c,v 1.12 2008/03/27 16:01:40 y-asaba Exp $
 *
 * pgpool: a language independent connection pool server for PostgreSQL 
 * written by Tatsuo Ishii
 *
 * Copyright (c) 2003-2008	PgPool Global Development Group
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of the
 * author not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission. The author makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * poo_connection_pool.c: connection pool stuff
 */
#include "config.h"

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#include <netdb.h>

#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include "pool.h"

POOL_CONNECTION_POOL *pool_connection_pool;	/* connection pool */
volatile sig_atomic_t backend_timer_expired =  0 ; /* flag for connection closed timer is expired */

static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot);
static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p);
static int check_socket_status(int fd);

/*
* initialize connection pools. this should be called once at the startup.
*/
int pool_init_cp(void)
{
	int i;

	pool_connection_pool = (POOL_CONNECTION_POOL *)malloc(sizeof(POOL_CONNECTION_POOL)*pool_config->max_pool);
	if (pool_connection_pool == NULL)
	{
		pool_error("pool_init_cp: malloc() failed");
		return - 1 ;
	}
	memset(pool_connection_pool,  0 , sizeof(POOL_CONNECTION_POOL)*pool_config->max_pool);
	
	for (i =  0 ; i < pool_config->max_pool; i++)
	{
		pool_connection_pool[i].info = &(MY_PROCESS_INFO.connection_info[i]);
		memset(pool_connection_pool[i].info,  0 , sizeof(ConnectionInfo));
	}
	return  0 ;
}

/*
* find connection by user and database
*/
POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int protoMajor, int check_socket)
{
#ifdef HAVE_SIGPROCMASK
	sigset_t oldmask;
#else
	int	oldmask;
#endif

	int i, j, freed =  0 ;
	ConnectionInfo *info;

	POOL_CONNECTION_POOL *p = pool_connection_pool;

	if (p == NULL)
	{
		pool_error("pool_get_cp: pool_connection_pool is not initialized");
		return NULL;
	}

	POOL_SETMASK2(&BlockSig, &oldmask);

	for (i= 0 ;i<pool_config->max_pool;i++)
	{
		if (MASTER_CONNECTION(p) &&
			MASTER_CONNECTION(p)->sp->major == protoMajor &&
			MASTER_CONNECTION(p)->sp->user != NULL &&
			strcmp(MASTER_CONNECTION(p)->sp->user, user) ==  0  &&
			strcmp(MASTER_CONNECTION(p)->sp->database, database) ==  0 )
		{
			int sock_broken =  0 ;

			/* mark this connection is under use */
			MASTER_CONNECTION(p)->closetime =  0 ;
			p->info->counter++;
			POOL_SETMASK(&oldmask);

			if (check_socket)
			{
				for (j= 0 ;j<NUM_BACKENDS;j++)
				{
					if (!VALID_BACKEND(j))
						continue;

					if  (CONNECTION_SLOT(p, j))
					{
						sock_broken = check_socket_status(CONNECTION(p, j)->fd);
						if (sock_broken <  0 )
							break;
					}
					else
					{
						sock_broken = - 1 ;
						break;
					}
				}

				if (sock_broken <  0 )
				{
					pool_log("connection closed. retry to create new connection pool.");
					for (j= 0 ;j<NUM_BACKENDS;j++)
					{
						if (!VALID_BACKEND(j) || (CONNECTION_SLOT(p, j) == NULL))
							continue;

						if (!freed)
						{
							pool_free_startup_packet(CONNECTION_SLOT(p, j)->sp);
							freed =  1 ;
						}

						pool_close(CONNECTION(p, j));
						free(CONNECTION_SLOT(p, j));
					}
					info = p->info;
					memset(p,  0 , sizeof(POOL_CONNECTION_POOL_SLOT));
					p->info = info;
					memset(p->info,  0 , sizeof(ConnectionInfo));
					POOL_SETMASK(&oldmask);
					return NULL;
				}
			}
			POOL_SETMASK(&oldmask);
			return p;
		}
		p++;
	}

	POOL_SETMASK(&oldmask);
	return NULL;
}

/*
 * disconnect and release a connection to the database
 */
void pool_discard_cp(char *user, char *database, int protoMajor)
{
	POOL_CONNECTION_POOL *p = pool_get_cp(user, database, protoMajor,  0 );
	ConnectionInfo *info;
	int i, freed =  0 ;

	if (p == NULL)
	{
		pool_error("pool_discard_cp: cannot get connection pool for user %s datbase %s", user, database);
		return;
	}

	for (i= 0 ;i<NUM_BACKENDS;i++)
	{
		if (!VALID_BACKEND(i))
			continue;

		if (!freed)
		{
			pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp);
			freed =  1 ;
		}
		pool_close(CONNECTION(p, i));
		free(CONNECTION_SLOT(p, i));
	}

	info = p->info;
	memset(p,  0 , sizeof(POOL_CONNECTION_POOL));
	p->info = info;
	memset(p->info,  0 , sizeof(ConnectionInfo));
}


/*
* create a connection pool by user and database
*/
POOL_CONNECTION_POOL *pool_create_cp(void)
{
	int i, freed =  0 ;
	time_t closetime;
	POOL_CONNECTION_POOL *oldestp;
	ConnectionInfo *info;

	POOL_CONNECTION_POOL *p = pool_connection_pool;

	if (p == NULL)
	{
		pool_error("pool_create_cp: pool_connection_pool is not initialized");
		return NULL;
	}

	for (i= 0 ;i<pool_config->max_pool;i++)
	{
		if (MASTER_CONNECTION(p) == NULL)
			return new_connection(p);
		p++;
	}

	pool_debug("no empty connection slot was found");

	/*
	 * no empty connection slot was found. look for the oldest connection and discard it.
	 */
	oldestp = p = pool_connection_pool;
	closetime = MASTER_CONNECTION(p)->closetime;
	for (i= 0 ;i<pool_config->max_pool;i++)
	{
		pool_debug("user: %s database: %s closetime: %d",
				   MASTER_CONNECTION(p)->sp->user,
				   MASTER_CONNECTION(p)->sp->database,
				   MASTER_CONNECTION(p)->closetime);
		if (MASTER_CONNECTION(p)->closetime < closetime)
		{
			closetime = MASTER_CONNECTION(p)->closetime;
			oldestp = p;
		}
		p++;
	}

	p = oldestp;
	pool_send_frontend_exits(p);

	pool_debug("discarding old %d th connection. user: %s database: %s", 
			   oldestp - pool_connection_pool,
			   MASTER_CONNECTION(p)->sp->user,
			   MASTER_CONNECTION(p)->sp->database);

	for (i= 0 ;i<NUM_BACKENDS;i++)
	{
		if (!VALID_BACKEND(i))
			continue;

		if (!freed)
		{
			pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp);
			freed =  1 ;
		}

		pool_close(CONNECTION(p, i));
		free(CONNECTION_SLOT(p, i));
	}

	info = p->info;
	memset(p,  0 , sizeof(POOL_CONNECTION_POOL));
	p->info = info;
	memset(p->info,  0 , sizeof(ConnectionInfo));

	return new_connection(p);
}

/*
 * set backend connection close timer
 */
void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend)
{
	POOL_CONNECTION_POOL *p = pool_connection_pool;
	int i;

	pool_debug("pool_connection_pool_timer: set close time %d", time(NULL));

	MASTER_CONNECTION(backend)->closetime = time(NULL);		/* set connection close time */

	if (pool_config->connection_life_time ==  0 )
		return;

	/* look for any other timeout */
	for (i= 0 ;i<pool_config->max_pool;i++, p++)
	{
		if (!MASTER_CONNECTION(p))
			continue;
		if (MASTER_CONNECTION(p)->sp->user == NULL)
			continue;

		if (p != backend && MASTER_CONNECTION(p)->closetime)
			return;
	}

	/* no other timer found. set my timer */
	pool_debug("pool_connection_pool_timer: set alarm after %d seconds", pool_config->connection_life_time);
	pool_signal(SIGALRM, pool_backend_timer_handler);
	alarm(pool_config->connection_life_time);
}

/*
 * backend connection close timer handler
 */
RETSIGTYPE pool_backend_timer_handler(int sig)
{
	backend_timer_expired =  1 ;
}

void pool_backend_timer(void)
{
#define TMINTMAX 0x7fffffff

	POOL_CONNECTION_POOL *p = pool_connection_pool;
	int i, j;
	time_t now;
	time_t nearest = TMINTMAX;
	ConnectionInfo *info;

	POOL_SETMASK(&BlockSig);

	now = time(NULL);

	pool_debug("pool_backend_timer_handler called at %d", now);

	for (i= 0 ;i<pool_config->max_pool;i++, p++)
	{
		if (!MASTER_CONNECTION(p))
			continue;
		if (MASTER_CONNECTION(p)->sp->user == NULL)
			continue;

		/* timer expire? */
		if (MASTER_CONNECTION(p)->closetime)
		{
			int freed =  0 ;

			pool_debug("pool_backend_timer_handler: expire time: %d",
					   MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time);

			if (now >= (MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time))
			{
				/* discard expired connection */
				pool_debug("pool_backend_timer_handler: expires user %s database %s",
						   MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database);

				pool_send_frontend_exits(p);

				for (j= 0 ;j<NUM_BACKENDS;j++)
				{
					if (!VALID_BACKEND(j))
						continue;

					if (!freed)
					{
						pool_free_startup_packet(CONNECTION_SLOT(p, j)->sp);
						freed =  1 ;
					}

					pool_close(CONNECTION(p, j));
					free(CONNECTION_SLOT(p, j));
				}
				info = p->info;
				memset(p,  0 , sizeof(POOL_CONNECTION_POOL));
				p->info = info;
				memset(p->info,  0 , sizeof(ConnectionInfo));
			}
			else
			{
				/* look for nearest timer */
				if (MASTER_CONNECTION(p)->closetime < nearest)
					nearest = MASTER_CONNECTION(p)->closetime;
			}
		}
	}

	/* any remaining timer */
	if (nearest != TMINTMAX)
	{
		nearest = pool_config->connection_life_time - (now - nearest);
		if (nearest <=  0 )
		  nearest =  1 ;
		pool_signal(SIGALRM, pool_backend_timer_handler);
		alarm(nearest);
	}

	POOL_SETMASK(&UnBlockSig);
}

/*
 * connect to postmaster through INET domain socket
 */
int connect_inet_domain_socket(int slot)
{
	char *host;
	int port;

	host = pool_config->backend_desc->backend_info[slot].backend_hostname;
	port = pool_config->backend_desc->backend_info[slot].backend_port;

	return connect_inet_domain_socket_by_port(host, port);
}

/*
 * connect to postmaster through UNIX domain socket
 */
int connect_unix_domain_socket(int slot)
{
	int port;
	char *socket_dir;

	port = pool_config->backend_desc->backend_info[slot].backend_port;
	socket_dir = pool_config->backend_socket_dir;

	return connect_unix_domain_socket_by_port(port, socket_dir);
}

int connect_unix_domain_socket_by_port(int port, char *socket_dir)
{
	struct sockaddr_un addr;
	int fd;
	int len;

	fd = socket(AF_UNIX, SOCK_STREAM,  0 );
	if (fd == - 1 )
	{
		pool_error("connect_unix_domain_socket_by_port: setsockopt() failed: %s", strerror(errno));
		return - 1 ;
	}

	memset((char *) &addr,  0 , sizeof(addr));
	((struct sockaddr *)&addr)->sa_family = AF_UNIX;
	snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.s.PGSQL.%d", socket_dir, port);
	len = sizeof(struct sockaddr_un);

	for (;;)
	{
		if (connect(fd, (struct sockaddr *)&addr, len) <  0 )
		{
			if (errno == EINTR || errno == EAGAIN)
				continue;

			pool_error("connect_unix_domain_socket_by_port: connect() failed: %s", strerror(errno));
			close(fd);
			return - 1 ;
		}
		break;
	}

	return fd;
}

int connect_inet_domain_socket_by_port(char *host, int port)
{
	int fd;
	int len;
	int on =  1 ;
	struct sockaddr_in addr;
	struct hostent *hp;

	fd = socket(AF_INET, SOCK_STREAM,  0 );
	if (fd <  0 )
	{
		pool_error("connect_inet_domain_socket_by_port: socket() failed: %s", strerror(errno));
		return - 1 ;
	}

	/* set nodelay */
	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
				   (char *) &on,
				   sizeof(on)) <  0 )
	{
		pool_error("connect_inet_domain_socket_by_port: setsockopt() failed: %s", strerror(errno));
		close(fd);
		return - 1 ;
	}

	memset((char *) &addr,  0 , sizeof(addr));
	((struct sockaddr *)&addr)->sa_family = AF_INET;

	addr.sin_port = htons(port);
	len = sizeof(struct sockaddr_in);

	hp = gethostbyname(host);
	if ((hp == NULL) || (hp->h_addrtype != AF_INET))
	{
		pool_error("connect_inet_domain_socket: gethostbyname() failed: %s host: %s", strerror(errno), host);
		close(fd);
		return - 1 ;
	}
	memmove((char *) &(addr.sin_addr),
			(char *) hp->h_addr,
			hp->h_length);

	for (;;)
	{
		if (connect(fd, (struct sockaddr *)&addr, len) <  0 )
		{
			if (errno == EINTR || errno == EAGAIN)
				continue;

			pool_error("connect_inet_domain_socket: connect() failed: %s",strerror(errno));
			close(fd);
			return - 1 ;
		}
		break;
	}

	return fd;
}

/*
 * create connection pool
 */
static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot)
{
	BackendInfo *b = &pool_config->backend_desc->backend_info[slot];
	int fd;

	if (*b->backend_hostname == '\0')
	{
		fd = connect_unix_domain_socket(slot);
	}
	else
	{
		fd = connect_inet_domain_socket(slot);
	}

	if (fd <  0 )
	{
		pool_error("connection to %s(%d) failed", b->backend_hostname, b->backend_port);
		return NULL;
	}

	cp->con = pool_open(fd);
	cp->closetime =  0 ;
	return cp;
}

/*
 * create actual connections to backends
 */
static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p)
{
	POOL_CONNECTION_POOL_SLOT *s;
	int active_backend_count =  0 ;
	int i;

	for (i= 0 ;i<NUM_BACKENDS;i++)
	{
		pool_debug("new_connection: connecting %d backend", i);

		if (!VALID_BACKEND(i))
		{
			pool_debug("new_connection: skipping slot %d because backend_status = %d",
					   i, BACKEND_INFO(i).backend_status);
			continue;
		}

		s = malloc(sizeof(POOL_CONNECTION_POOL_SLOT));
		if (s == NULL)
		{
			pool_error("new_connection: malloc() failed");
			return NULL;
		}

		p->slots[i] = s;

		if (create_cp(s, i) == NULL)
		{
			/* connection failed. mark this backend down */
			pool_error("new_connection: create_cp() failed");

			/* send failover request to parent if operated in pgpool-I mode */
			/* notice_backend_error() returns immediately if in pgpool-II */
			notice_backend_error(i);
			child_exit( 1 );
		}

		if (pool_init_params(&s->con->params))
		{
			return NULL;
		}

		BACKEND_INFO(i).backend_status = CON_UP;
		active_backend_count++;
	}

	if (active_backend_count >  0 )
	{
		p->info->create_time = time(NULL);
		return p;
	}

	return NULL;
}

/* check_socket_status()
 * RETURN: 0 => OK
 *        -1 => broken socket.
 */
static int check_socket_status(int fd)
{
	fd_set rfds;
	int result;
	struct timeval t;

	for (;;)
	{
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);

		t.tv_sec = t.tv_usec =  [b]0 ;[/b]

		result = select(fd+ 1 , &rfds, NULL, NULL, &t);
		if (result <  0  && errno == EINTR)
		{
			continue;
		}
		else
		{
			return (result ==  0  ?  0  : - 1 );
		}
	}

	return - 1 ;
}

...
Рейтинг: 0 / 0
Сокеты и тайм аут закрытия
    #35522064
--null--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В select() если в timeval стоит 0, то функция немедленно вернёт значение.
А сниффером смотрели, на чём сессия висит?
...
Рейтинг: 0 / 0
Сокеты и тайм аут закрытия
    #35523387
GerdaS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
--null--В select() если в timeval стоит 0, то функция немедленно вернёт значение.
А сниффером смотрели, на чём сессия висит?

по дампу видно, что сервера 1 ( с pgpool) и 2 ( c postgres) "общаются" потом 2 не отвечат, сессия не разрывается и 1 периодически к нему обращается по tcp не получая ответа.

Всё закончилось тем, что немного изменили pgpool исправив "багу".

если кому -то ещё понадобится то код ниже
в файле конфигурации pgpool надо добавить параметр
connect_timout
если поставить значение 0 , то будет работать по старому алгоритму , любое другое значение задаёт tim out ожидания отклика сервера

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
/* -*-pgsql-c-*- */
/*
 * $Header: /cvsroot/pgpool/pgpool-II/pool_connection_pool.c,v 1.12 2008/03/27 16:01:40 y-asaba Exp $
 *
 * pgpool: a language independent connection pool server for PostgreSQL 
 * written by Tatsuo Ishii
 *
 * Copyright (c) 2003-2008	PgPool Global Development Group
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of the
 * author not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission. The author makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * poo_connection_pool.c: connection pool stuff
 */
#include "config.h"

#include <sys/poll.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#include <netdb.h>

#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include "pool.h"

POOL_CONNECTION_POOL *pool_connection_pool;	/* connection pool */
volatile sig_atomic_t backend_timer_expired =  0 ; /* flag for connection closed timer is expired */

static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot);
static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p);
static int check_socket_status(int fd);

/*
* initialize connection pools. this should be called once at the startup.
*/
int pool_init_cp(void)
{
	int i;

	pool_connection_pool = (POOL_CONNECTION_POOL *)malloc(sizeof(POOL_CONNECTION_POOL)*pool_config->max_pool);
	if (pool_connection_pool == NULL)
	{
		pool_error("pool_init_cp: malloc() failed");
		return - 1 ;
	}
	memset(pool_connection_pool,  0 , sizeof(POOL_CONNECTION_POOL)*pool_config->max_pool);
	
	for (i =  0 ; i < pool_config->max_pool; i++)
	{
		pool_connection_pool[i].info = &(MY_PROCESS_INFO.connection_info[i]);
		memset(pool_connection_pool[i].info,  0 , sizeof(ConnectionInfo));
	}
	return  0 ;
}

/*
* find connection by user and database
*/
POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int protoMajor, int check_socket)
{
#ifdef HAVE_SIGPROCMASK
	sigset_t oldmask;
#else
	int	oldmask;
#endif

	int i, j, freed =  0 ;
	ConnectionInfo *info;

	POOL_CONNECTION_POOL *p = pool_connection_pool;

	if (p == NULL)
	{
		pool_error("pool_get_cp: pool_connection_pool is not initialized");
		return NULL;
	}

	POOL_SETMASK2(&BlockSig, &oldmask);

	for (i= 0 ;i<pool_config->max_pool;i++)
	{
		if (MASTER_CONNECTION(p) &&
			MASTER_CONNECTION(p)->sp->major == protoMajor &&
			MASTER_CONNECTION(p)->sp->user != NULL &&
			strcmp(MASTER_CONNECTION(p)->sp->user, user) ==  0  &&
			strcmp(MASTER_CONNECTION(p)->sp->database, database) ==  0 )
		{
			int sock_broken =  0 ;

			/* mark this connection is under use */
			MASTER_CONNECTION(p)->closetime =  0 ;
			p->info->counter++;
			POOL_SETMASK(&oldmask);

			if (check_socket)
			{
				for (j= 0 ;j<NUM_BACKENDS;j++)
				{
					if (!VALID_BACKEND(j))
						continue;

					if  (CONNECTION_SLOT(p, j))
					{
						sock_broken = check_socket_status(CONNECTION(p, j)->fd);
						if (sock_broken <  0 )
							break;
					}
					else
					{
						sock_broken = - 1 ;
						break;
					}
				}

				if (sock_broken <  0 )
				{
					pool_log("connection closed. retry to create new connection pool.");
					for (j= 0 ;j<NUM_BACKENDS;j++)
					{
						if (!VALID_BACKEND(j) || (CONNECTION_SLOT(p, j) == NULL))
							continue;

						if (!freed)
						{
							pool_free_startup_packet(CONNECTION_SLOT(p, j)->sp);
							freed =  1 ;
						}

						pool_close(CONNECTION(p, j));
						free(CONNECTION_SLOT(p, j));
					}
					info = p->info;
					memset(p,  0 , sizeof(POOL_CONNECTION_POOL_SLOT));
					p->info = info;
					memset(p->info,  0 , sizeof(ConnectionInfo));
					POOL_SETMASK(&oldmask);
					return NULL;
				}
			}
			POOL_SETMASK(&oldmask);
			return p;
		}
		p++;
	}

	POOL_SETMASK(&oldmask);
	return NULL;
}

/*
 * disconnect and release a connection to the database
 */
void pool_discard_cp(char *user, char *database, int protoMajor)
{
	POOL_CONNECTION_POOL *p = pool_get_cp(user, database, protoMajor,  0 );
	ConnectionInfo *info;
	int i, freed =  0 ;

	if (p == NULL)
	{
		pool_error("pool_discard_cp: cannot get connection pool for user %s datbase %s", user, database);
		return;
	}

	for (i= 0 ;i<NUM_BACKENDS;i++)
	{
		if (!VALID_BACKEND(i))
			continue;

		if (!freed)
		{
			pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp);
			freed =  1 ;
		}
		pool_close(CONNECTION(p, i));
		free(CONNECTION_SLOT(p, i));
	}

	info = p->info;
	memset(p,  0 , sizeof(POOL_CONNECTION_POOL));
	p->info = info;
	memset(p->info,  0 , sizeof(ConnectionInfo));
}


/*
* create a connection pool by user and database
*/
POOL_CONNECTION_POOL *pool_create_cp(void)
{
	int i, freed =  0 ;
	time_t closetime;
	POOL_CONNECTION_POOL *oldestp;
	ConnectionInfo *info;

	POOL_CONNECTION_POOL *p = pool_connection_pool;

	if (p == NULL)
	{
		pool_error("pool_create_cp: pool_connection_pool is not initialized");
		return NULL;
	}

	for (i= 0 ;i<pool_config->max_pool;i++)
	{
		if (MASTER_CONNECTION(p) == NULL)
			return new_connection(p);
		p++;
	}

	pool_debug("no empty connection slot was found");

	/*
	 * no empty connection slot was found. look for the oldest connection and discard it.
	 */
	oldestp = p = pool_connection_pool;
	closetime = MASTER_CONNECTION(p)->closetime;
	for (i= 0 ;i<pool_config->max_pool;i++)
	{
		pool_debug("user: %s database: %s closetime: %d",
				   MASTER_CONNECTION(p)->sp->user,
				   MASTER_CONNECTION(p)->sp->database,
				   MASTER_CONNECTION(p)->closetime);
		if (MASTER_CONNECTION(p)->closetime < closetime)
		{
			closetime = MASTER_CONNECTION(p)->closetime;
			oldestp = p;
		}
		p++;
	}

	p = oldestp;
	pool_send_frontend_exits(p);

	pool_debug("discarding old %d th connection. user: %s database: %s", 
			   oldestp - pool_connection_pool,
			   MASTER_CONNECTION(p)->sp->user,
			   MASTER_CONNECTION(p)->sp->database);

	for (i= 0 ;i<NUM_BACKENDS;i++)
	{
		if (!VALID_BACKEND(i))
			continue;

		if (!freed)
		{
			pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp);
			freed =  1 ;
		}

		pool_close(CONNECTION(p, i));
		free(CONNECTION_SLOT(p, i));
	}

	info = p->info;
	memset(p,  0 , sizeof(POOL_CONNECTION_POOL));
	p->info = info;
	memset(p->info,  0 , sizeof(ConnectionInfo));

	return new_connection(p);
}

/*
 * set backend connection close timer
 */
void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend)
{
	POOL_CONNECTION_POOL *p = pool_connection_pool;
	int i;

	pool_debug("pool_connection_pool_timer: set close time %d", time(NULL));

	MASTER_CONNECTION(backend)->closetime = time(NULL);		/* set connection close time */

	if (pool_config->connection_life_time ==  0 )
		return;

	/* look for any other timeout */
	for (i= 0 ;i<pool_config->max_pool;i++, p++)
	{
		if (!MASTER_CONNECTION(p))
			continue;
		if (MASTER_CONNECTION(p)->sp->user == NULL)
			continue;

		if (p != backend && MASTER_CONNECTION(p)->closetime)
			return;
	}

	/* no other timer found. set my timer */
	pool_debug("pool_connection_pool_timer: set alarm after %d seconds", pool_config->connection_life_time);
	pool_signal(SIGALRM, pool_backend_timer_handler);
	alarm(pool_config->connection_life_time);
}

/*
 * backend connection close timer handler
 */
RETSIGTYPE pool_backend_timer_handler(int sig)
{
	backend_timer_expired =  1 ;
}

void pool_backend_timer(void)
{
#define TMINTMAX 0x7fffffff

	POOL_CONNECTION_POOL *p = pool_connection_pool;
	int i, j;
	time_t now;
	time_t nearest = TMINTMAX;
	ConnectionInfo *info;

	POOL_SETMASK(&BlockSig);

	now = time(NULL);

	pool_debug("pool_backend_timer_handler called at %d", now);

	for (i= 0 ;i<pool_config->max_pool;i++, p++)
	{
		if (!MASTER_CONNECTION(p))
			continue;
		if (MASTER_CONNECTION(p)->sp->user == NULL)
			continue;

		/* timer expire? */
		if (MASTER_CONNECTION(p)->closetime)
		{
			int freed =  0 ;

			pool_debug("pool_backend_timer_handler: expire time: %d",
					   MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time);

			if (now >= (MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time))
			{
				/* discard expired connection */
				pool_debug("pool_backend_timer_handler: expires user %s database %s",
						   MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database);

				pool_send_frontend_exits(p);

				for (j= 0 ;j<NUM_BACKENDS;j++)
				{
					if (!VALID_BACKEND(j))
						continue;

					if (!freed)
					{
						pool_free_startup_packet(CONNECTION_SLOT(p, j)->sp);
						freed =  1 ;
					}

					pool_close(CONNECTION(p, j));
					free(CONNECTION_SLOT(p, j));
				}
				info = p->info;
				memset(p,  0 , sizeof(POOL_CONNECTION_POOL));
				p->info = info;
				memset(p->info,  0 , sizeof(ConnectionInfo));
			}
			else
			{
				/* look for nearest timer */
				if (MASTER_CONNECTION(p)->closetime < nearest)
					nearest = MASTER_CONNECTION(p)->closetime;
			}
		}
	}

	/* any remaining timer */
	if (nearest != TMINTMAX)
	{
		nearest = pool_config->connection_life_time - (now - nearest);
		if (nearest <=  0 )
		  nearest =  1 ;
		pool_signal(SIGALRM, pool_backend_timer_handler);
		alarm(nearest);
	}

	POOL_SETMASK(&UnBlockSig);
}

/*
 * connect to postmaster through INET domain socket
 */
int connect_inet_domain_socket(int slot)
{
	char *host;
	int port;

	host = pool_config->backend_desc->backend_info[slot].backend_hostname;
	port = pool_config->backend_desc->backend_info[slot].backend_port;

	return connect_inet_domain_socket_by_port(host, port);
}

/*
 * connect to postmaster through UNIX domain socket
 */
int connect_unix_domain_socket(int slot)
{
	int port;
	char *socket_dir;

	port = pool_config->backend_desc->backend_info[slot].backend_port;
	socket_dir = pool_config->backend_socket_dir;

	return connect_unix_domain_socket_by_port(port, socket_dir);
}

int connect_unix_domain_socket_by_port(int port, char *socket_dir)
{
	struct sockaddr_un addr;
	int fd;
	int len;

	fd = socket(AF_UNIX, SOCK_STREAM,  0 );
	if (fd == - 1 )
	{
		pool_error("connect_unix_domain_socket_by_port: setsockopt() failed: %s", strerror(errno));
		return - 1 ;
	}

	memset((char *) &addr,  0 , sizeof(addr));
	((struct sockaddr *)&addr)->sa_family = AF_UNIX;
	snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.s.PGSQL.%d", socket_dir, port);
	len = sizeof(struct sockaddr_un);

	for (;;)
	{
		if (connect(fd, (struct sockaddr *)&addr, len) <  0 )
		{
			if (errno == EINTR || errno == EAGAIN)
				continue;

			pool_error("connect_unix_domain_socket_by_port: connect() failed: %s", strerror(errno));
			close(fd);
			return - 1 ;
		}
		break;
	}

	return fd;
}




static void my_set_blocking(int fd){
    int flags = fcntl(fd, F_GETFL);
    flags &= ~O_NONBLOCK;
    if (fcntl(fd, F_SETFL, flags) == - 1  ){
        perror("fcntl");
    }
}


static void my_set_nonblocking(int fd){
  int flags = fcntl(fd, F_GETFL);
  flags |= O_NONBLOCK;
  if (fcntl(fd, F_SETFL, flags) == - 1 ){
      perror("fcntl");
  }
}



static int my_connect_with_timeout(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, time_t timeout){
    int result = - 1 ;
    my_set_nonblocking(sockfd);
    int connect_rv = connect(sockfd, (struct sockaddr *)serv_addr, addrlen);
    if (connect_rv !=  0 ) {
        time_t start_time;
        start_time = time(NULL);
        if (errno != EINPROGRESS) {
            //ConnectException
            my_set_blocking(sockfd);
        }else{
            for(;;){
                time_t new_time;
                struct pollfd pfd;
                pfd.fd = sockfd;
                pfd.events = POLLOUT;
                errno =  0 ;
                connect_rv = poll(&pfd,  1 , timeout *  1000 );
                if (connect_rv >=  0  ||  errno != EINTR) {
                    break;
                }
                new_time = time(NULL);
                timeout -= (new_time - start_time);
                if (timeout <=  0 ) {
                    connect_rv =  0 ;
                    break;
                }
                new_time = start_time;
            }
            if (connect_rv ==  0 ) {
                //SocketTimeoutException
                result = - 1 ;
                errno  = ETIMEDOUT;
            }else{
                socklen_t optlen = sizeof(connect_rv);
                
                /* has connection been established */
                if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, &optlen) <  0 ) {
                     //fprintf(stderr, "not established\n");
                     connect_rv = errno;
                     result = - 1 ;
                }else{
                     //fprintf(stderr, "established, connectrv: %d \n", connect_rv);
                     //fprintf(stderr, "strerror: %s\n", strerror(connect_rv));
                     //result =  0 ;
                     errno  = connect_rv;
                     result = connect_rv ==  0  ?  0  : - 1 ;
                }
            }
        }
        my_set_blocking(sockfd);
        /* restore errno */
        if (connect_rv !=  0 ) {
            errno = connect_rv;
            //connect_rv = - 1 ;
            result = errno ==  0  ?  0  : - 1 ;
        }
        if (errno == EINVAL){
            result = - 1 ;
        }
    }else{
        result = - 1 ;
    }
    my_set_blocking(sockfd);
    return result;
}





int connect_inet_domain_socket_by_port(char *host, int port)
{
	int fd;
	int len;
	int on =  1 ;
	struct sockaddr_in addr;
	struct hostent *hp;

	fd = socket(AF_INET, SOCK_STREAM,  0 );
	if (fd <  0 )
	{
		pool_error("connect_inet_domain_socket_by_port: socket() failed: %s", strerror(errno));
		return - 1 ;
	}

	/* set nodelay */
	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
				   (char *) &on,
				   sizeof(on)) <  0 )
	{
		pool_error("connect_inet_domain_socket_by_port: setsockopt() failed: %s", strerror(errno));
		close(fd);
		return - 1 ;
	}

	memset((char *) &addr,  0 , sizeof(addr));
	((struct sockaddr *)&addr)->sa_family = AF_INET;

	addr.sin_port = htons(port);
	len = sizeof(struct sockaddr_in);

	hp = gethostbyname(host);
	if ((hp == NULL) || (hp->h_addrtype != AF_INET))
	{
		pool_error("connect_inet_domain_socket: gethostbyname() failed: %s host: %s", strerror(errno), host);
		close(fd);
		return - 1 ;
	}
	memmove((char *) &(addr.sin_addr),
			(char *) hp->h_addr,
			hp->h_length);

	for (;;)
	{
                time_t conn_timeout = pool_config -> connect_timeout;
                int conn_ret =  0 ;
                fprintf(stderr, "connect_timeout: %d\n", conn_timeout);
                if (conn_timeout >  0 ){
                   pool_error("connecting using timeout", conn_timeout);
                   conn_ret = my_connect_with_timeout(fd, (struct sockaddr *)&addr, len, conn_timeout);
                }else{
                   conn_ret = connect(fd, (struct sockaddr *)&addr, len);
                }
                 
		if (conn_ret <  0 )
		{
			if (errno == EINTR || errno == EAGAIN)
				continue;

			pool_error("connect_inet_domain_socket: connect() failed: %s",strerror(errno));
			close(fd);
			return - 1 ;
		}
		break;
	}

	return fd;
}

/*
 * create connection pool
 */
static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot)
{
	BackendInfo *b = &pool_config->backend_desc->backend_info[slot];
	int fd;

	if (*b->backend_hostname == '\0')
	{
		fd = connect_unix_domain_socket(slot);
	}
	else
	{
		fd = connect_inet_domain_socket(slot);
	}

	if (fd <  0 )
	{
		pool_error("connection to %s(%d) failed", b->backend_hostname, b->backend_port);
		return NULL;
	}

	cp->con = pool_open(fd);
	cp->closetime =  0 ;
	return cp;
}

/*
 * create actual connections to backends
 */
static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p)
{
	POOL_CONNECTION_POOL_SLOT *s;
	int active_backend_count =  0 ;
	int i;

	for (i= 0 ;i<NUM_BACKENDS;i++)
	{
		pool_debug("new_connection: connecting %d backend", i);

		if (!VALID_BACKEND(i))
		{
			pool_debug("new_connection: skipping slot %d because backend_status = %d",
					   i, BACKEND_INFO(i).backend_status);
			continue;
		}

		s = malloc(sizeof(POOL_CONNECTION_POOL_SLOT));
		if (s == NULL)
		{
			pool_error("new_connection: malloc() failed");
			return NULL;
		}

		p->slots[i] = s;

		if (create_cp(s, i) == NULL)
		{
			/* connection failed. mark this backend down */
			pool_error("new_connection: create_cp() failed");

			/* send failover request to parent if operated in pgpool-I mode */
			/* notice_backend_error() returns immediately if in pgpool-II */
			notice_backend_error(i);
			child_exit( 1 );
		}

		if (pool_init_params(&s->con->params))
		{
			return NULL;
		}

		BACKEND_INFO(i).backend_status = CON_UP;
		active_backend_count++;
	}

	if (active_backend_count >  0 )
	{
		p->info->create_time = time(NULL);
		return p;
	}

	return NULL;
}

/* check_socket_status()
 * RETURN: 0 => OK
 *        -1 => broken socket.
 */
static int check_socket_status(int fd)
{
	fd_set rfds;
	int result;
	struct timeval t;

	for (;;)
	{
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);

		t.tv_sec = t.tv_usec =  0 ;

		result = select(fd+ 1 , &rfds, NULL, NULL, &t);
		if (result <  0  && errno == EINTR)
		{
			continue;
		}
		else
		{
			return (result ==  0  ?  0  : - 1 );
		}
	}

	return - 1 ;
}


...
Рейтинг: 0 / 0
Сокеты и тайм аут закрытия
    #35523913
Фотография Умаксуман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и нафига постить портянку?

Если приложение останавливается, то при этом соединение закрывается по-честному на обоих сторонах, а если падает машина, то приложение на другом конце провода не знает о том, что его собеседника нет. Ничего не получая в ответ модуль TCP начинает посылать пакеты, кажется SYN, и по прошествии скольких-то посылок делает вывод, что соединение разорвано и только после этого закрывает его на своей стороне, что естественно занимает какое-то время. Максимум что можно сделать в этой ситуации - уменьшить кол-во попыток проверки и таумаут ожидания
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Unix-системы [игнор отключен] [закрыт для гостей] / Сокеты и тайм аут закрытия
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]