[pgcluster: 79] Re: load balancer

Tatsuo Ishii t-ishii @ sra.co.jp
2004年 2月 4日 (水) 23:00:26 JST


石井です.

> 川村と申します。
> 
> FreeBSD 5.2R 上で PGCluster-1.0.6b を動かしていますが、ロードバランサを
> 経由して空文字列をフィールドとして持つテーブルにアクセスすると、signal 11
> が飛んで pglb が core dump してしまう現象が起きています。
> 
> 直接マスタDBなりクラスタサーバなりに接続して同じテーブルにアクセスしても
> この問題は起きません。
> 
> gdb で追ってみると、AsciiRow() 内の snprintf() で落ちているようです。
[snip]
> ソースを追ってみたところ、AsciiRow() での処理において、そのフィールドを
> 処理するかどうかの分岐条件を NULL かどうかだけで見ていて空文字列のフィー
> ルドを弾けず、その結果空文字列フィールドのデータを格納する領域を確保し
> ようとして malloc(0) が call されてしまい、その返り値であるポインタ変数
> buf に snprintf() でアクセスし、signal 11 が飛んでしまう、という現象が
> 起こっているように思います。

済みません.pgclusterにはpgpoolのコードの一部を利用していただいている
のですが,そもそもpgpoolにこのバグがありました.

> とりあえず size が 0 の場合は以降の処理を行わないというコードを追加して
> ひとおり動作はしているようですが、adhoc な感は否めません。この場合、ど
> のように修正するのがよいのでしょうか。

オリジナルのPostgreSQLでもsizeが0の場合はデータの送受信を行わないよう
に実装されていますので,この対処で正しいと思います.

参考までにpgpool 0.1.7に対する修正を付けておきます.川村さんの修正とほ
とんど同じです.
--
Tatsuo Ishii

*** pool_process_query.c	21 Jan 2004 08:19:53 -0000	1.5
--- pool_process_query.c	4 Feb 2004 12:23:17 -0000
***************
*** 422,441 ****
  
  			pool_write(frontend, &size, sizeof(int));
  			size = htonl(size) - 4;
! 			buf = malloc(size);
! 			if (buf == NULL)
  			{
! 				pool_error("AsciiRow: out of memory");
! 				return POOL_END;
  			}
- 			/* actual data */
- 			if (pool_read(backend, buf, size) < 0)
- 				return POOL_END;
- 
- 			pool_write(frontend, buf, size);
- 			snprintf(msgbuf, Min(sizeof(msgbuf), size), "%s", buf);
  			pool_debug("AsciiRow: len:%d data: %s", size, msgbuf);
- 			free(buf);
  		}
  		mask >>= 1;
  	}
--- 422,452 ----
  
  			pool_write(frontend, &size, sizeof(int));
  			size = htonl(size) - 4;
! 
! 			/* read and send actual data only when size > 0 */
! 			if (size > 0)
  			{
! 				buf = malloc(size);
! 				if (buf == NULL)
! 				{
! 					pool_error("AsciiRow: out of memory");
! 					return POOL_END;
! 				}
! 				/* actual data */
! 				if (pool_read(backend, buf, size) < 0)
! 				{
! 					free(buf);
! 					return POOL_END;
! 				}
! 				pool_write(frontend, buf, size);
! 				snprintf(msgbuf, Min(sizeof(msgbuf), size), "%s", buf);
! 				free(buf);
! 			}
! 			else
! 			{
! 				*msgbuf = '\0';
  			}
  			pool_debug("AsciiRow: len:%d data: %s", size, msgbuf);
  		}
  		mask >>= 1;
  	}



pgcluster メーリングリストの案内