다음 이전 차례

5. 문제가 있나요?

5.1 어떻게 원격지 연결을 허용하는가?

원격지 클라이언트를 위해 듣고 있다가, 연결을 위해 sqlexec 프로세스를 실행하는(fire off) sqlexecd 내의 버그 #97893 (리눅스에 국한된)와 #97889 (솔라리스에 국한된 것으로 간주되는)로 인해, sqlexec 세션이 종료될 때 프로세스 테이블에 좀비를 남긴다. ( 프로세스 테이블의 이 좀비들은 무엇인가?그것들은 어떻게 방지하는가?를 볼것). 이 경고를 듣고도 당신이 여전히 고집한다면, 이렇게 해라:

5.2 프로세스 테이블의 이 좀비들은 무엇인가?

그것들은 인포믹스 식으로 말하면 "우리는 회초리를 맞았지만 계속 똑딱거린다!"이다. ;-) 진지하게, 그것들은 버그 #97893의 표출이다. 이 버그는 데이터베이스에 대한 원격지 접근을 제공하기 위해 소켓(sesoctcp)을 사용할 때 가장 빈번하게 발생하는 것 같다. 로컬 연결 상에서 무명 파이프(seipcpip)를 사용할때도 발생한다는 보고도 있다. 재미있는 것은 glibc 릴리즈에서 버그 #97893 가 수정되었지만, 새로운 버그 #101155 가 등장했다는 것이다: SEIPCPIP 연결 프로토콜(파이프)가 레드햇 5.1 플랫폼에서 동작하지 않는 것이다.

5.3 그것들을 어떻게 방지하는가?

Jonathan Leffler ( jleffler@informix.com)가 회피책 nozombie.c 를 게시했는데, 그것은 nohup가 같은 방식으로 사용된다. 다음은 Jonathan의 코드와 그의 언급이다. 이것은 공식적인(인포믹스에 의해 입증된) 수정이 아니고, 모든 경우에 동작하는 것은 아니라는 보고도 있다는 것에 주의하라. YMMV.

설명은 꽤 간단하다 -- 만일 프로세스가 SIGCHLD를 무시한다면, 그것은 좀비 자식들을 쌓지 
않는다. 프로그램은 SIGCHLD에 대해 SIG_IGN 시그널 처리 모드를 설정한 다음 인자로 
주어진 것을 그대로 실행한다. 만일 그것이 sqlexecd에 발생한다면,
그것은 SIGCHLD 시그널을 무시하게 되고, 그래서 여기저기에 좀비를 남기지 않는다.


/*
@(#)File:            $RCSfile: nozombie.c,v $
@(#)Version:         $Revision: 1.1 $
@(#)Last changed:    $Date: 1998/08/20 21:24:40 $
@(#)Purpose:         Prevent process from accidentally creating zombies
@(#)Author:          J Leffler
@(#)Copyright:       (C) JLSS 1998
@(#)Product:         :PRODUCT:
*/
/*TABSTOP=4*/
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef lint
static const char rcs[] = "@(#)$Id: nozombie.c,v 1.1 1998/08/20 21:24:40 jleffler Exp $";
#endif
/*
** Exec program specified by arguments with SIGCHLD signals ignored.
** This ensures that unless the program re-enables the SIGCHLD signal
** handling, it does not leave zombies around, even if it doesn't
** clean up behind its children.  This works on POSIX.1 systems (such
** as Solaris 2.6 and Linux) pretty straight-forwardly.
**
** Motivation: the initial version of sqlexecd 7.24.UC1 on Linux
** caused problems with lots of zombies.
**
**      nozombie $INFORMIXDIR/lib/sqlexecd [service]
*/
int main(int argc, char **argv)
{
    signal(SIGCHLD, SIG_IGN);
    execv(argv[1], &argv[1]);
    fprintf(stderr, "Failed to execv() %s\n", argv[1]);
    return EXIT_FAILURE;
}

Jonathan의 코드로 해결이 안되면, 최근에 informix.idn.linux에 나타난 방법을 시도해 보라. 그것은 signal 함수가 작동하는 방식을 재작성함으로써 좀비 문제를 수정한다. 먼저, 다음과 같이 signalfix.c 를 만든다:


#include "signal.h"
#include <unistd.h>
#include <stdio.h>
void *signal(int signum,void (*handler)(int))
{
  struct sigaction sa;
  sa.sa_handler=handler;
  sa.sa_mask=SA_NOMASK;
  sa.sa_flags=SA_RESTART;
  sigaction(signum,&sa,(struct sigaction *)NULL);
}

다음으로, /usr/include/signal.h 를 복사하고, 시그널 함수를 주석처리 한다. 그런 다음, signalfix.c를 이런 식으로 컴파일한다:

$ gcc -fpic -shared signalfix.c -o libsig.so

마지막으로, sqlexecd 를 실행한다:

$ LD_PRELOAD=/root/sqlexecfix/libsig.so $INFORMIXDIR/lib/sqlexecd servername

5.4 DBACCESS가 xterm에서 세그먼테이션 폴트를 발생시킨다!

직접적인 문제는 dbaccess가 명백히 termcap/terminfo 항목들을 유지하는 정적인 버퍼를 할당하고 당신의 항목이 이 버퍼가 유지하는 것보다 길다는 것이다. 가까운 미래의 어느날 ©, 나는 이것을 인포믹스에 보고할 것이고, 다음 릴리즈 사이클내에 수정된 것을 얻길 바란다.

그 동안에 회피할 수 있는 방법은:

  1. $TERM 환경 변수를 linux, vt220 또는 vt100같은 xterm이 아닌 다른 것으로 변경한다
  2. termcap이나 terminfo내의 관련된 항목들을 수정한다(물론 보관용 사본을 만들어둔 후에). - dbaccess는 "ti"나 "te" 항목을 사용하지 않으므로, 그것들은 삭제될 수 있다. 이 방법은 잘 동작하지만, ti/te 항목을 실제로 사용하는 모든 xterm세션에 영향을 미친다.
  3. xterm-dbaccess같이 xterm 항목을 그대로 복제하고, "ti"와 "te"항목을 삭제하고, 당신이 xterm 창에서 dbaccess를 실행할 때 $TERM환경 변수를 xterm-dbaccess로 설정한다.
  4. http://www.informix.com/idn-secure/Linux/WebPages/termcap.html 에서 구할 수 있는 대체 termcap/terminfo 파일을 사용한다. 거기에 나열된 경고와 제언들에 주의할 것.

Roger Allen ( rja@sis.rpslmc.edu)은 세 번째 선택을 권장하고 설명하기를

/etc/termcap내에 다른 이름으로 xterm 항목의 사본을 만들고
새로운 이름을 당신의 TERM 설정으로 사용하거나 현재 항목을 변경하라.
어떤 인포믹스 매뉴얼의 부록 어딘가에 인포믹스가 사용하는 필드들의 목록이 있다.
나는 보통 ti와 te를 필드를 삭제한다.
당신도 DB-Access보다는 다른 인포믹스 툴들을 더욱 위한 것이지만,
선 그리기 문자, 그리고 몇가지 기능 키들을 할수 있게 하는
특별한 인포믹스 항목을 추가할 수 있다.

5.5 내가 사용하려는 포트가 이미 사용 중이다!

다른 것을 사용해라. 인정받은 인포믹스 포트는 1546이지만, 그것이 사용하는 소켓이 다른 서비스에 사용되는 중이 아니라면 어떤 것이라도 상관없다.

5.6 NFS-마운트된 파일시스템을 사용할 수 있는가?

아니다. 당신의 데이터베이스를 보관할 파일시스템을 NFS를 통해 마운트하기 보다는,

  1. 원격지 호스트에 sqlexecd가 실행중이어야 하고,
  2. 원격지 데이터베이스에 네트웍을 사용해서 접근해야만 한다.

SE의 리눅스 이외의 버전은 이것을 바이너리 내에서 강요하지만, 리눅스의 경우에는 해당되지 않을지도 모른다. Jonathan Leffler의 충고에 따르면, "속임수를 쓰고자 한다면 문제를 당연한 일로 여겨라 -- 데이터 손상 문제들" 이것이 바이너리에 의해 강요되든 그렇지 않든, 당신의 데이터베이스를 NFS 위에 마운트하는 것은 (적어도) 두가지 이유 때문에라도 좋지 않은 생각이다:

  1. NFS가 느리기 때문에, 접근이 느려질 것이다.
  2. 만일 NFS마운트를 잃게 된다면, 당신은 어이없게 될 것이고, 데이터베이스 파일들에 무슨 일이 생겼을지는 뻔하다.


다음 이전 차례