본문 바로가기

Engineering/DB

FreeTDS 라이브러리 사용시, "FreeTDS: db-lib: exiting because client error handler returned 0 for msgno 2000" 에러 발생시 해결방안

728x90

 FreeTDS 라이브러리를 이용하여 프로그램을 개발하여 테스트를 진행하는데, 테스트에 사용되던 MSSQL 서버에 문제가 생겨서 어느날부터 연결이 안되는 일이 발생했습니다. 여러 DBMS 에 연결하는 프로그램이었는데, 항상 잘 돌아가던 서버여서 당연히 연결될꺼라는 과정으로 프로그램을 코딩하는 바람에 서버에 연결안되는 순간부터 "FreeTDS: db-lib: exiting because client error handler returned 0 for msgno 20009" 에러가 나면서 메인 프로그램을 kill 시키는 것입니다. 
 서버에 연결실패할 경우 dbopen() 의 return 값인 dbproc 가 NULL 이 되어 에러메시지를 출력하고 return 할 것으로 예상했지만, 전체 프로그램이 kill 되면서 20009 메시지가 나옵니다.

if ((dbproc = dbopen(login, options.servername)) == NULL) { fprintf(stderr, "%s:%d: unable to connect to %s as %s\n", options.appname, __LINE__, options.servername, options.username); return; }

  이유를 찾아보니, 20009 메시지는 "서버에 연결할 수 없다" 라는 것입니다. (include/sybdb.h) 그리고, 에러가 나면 default 로 프로세스를 kill 시킨다고 합니다.

 해결방법은 의외로 간단합니다. dbinit() 함수 다음에 와  message 핸들러와 error 핸들러를 등록하는데, error 핸들러의 return 값을 "INT_CANCEL" 로 변경합니다. ("0" 은 "INT_EXIT" 입니다.)

int

msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, 

   char *msgtext, char *srvname, char *procname, int line)

{

enum {changed_database = 5701, changed_language = 5703 };

if (msgno == changed_database || msgno == changed_language) 

return 0;


if (msgno > 0) {

fprintf(stderr, "Msg %ld, Level %d, State %d\n", 

(long) msgno, severity, msgstate);


if (strlen(srvname) > 0)

fprintf(stderr, "Server '%s', ", srvname);

if (strlen(procname) > 0)

fprintf(stderr, "Procedure '%s', ", procname);

if (line > 0)

fprintf(stderr, "Line %d", line);


fprintf(stderr, "\n\t");

}

fprintf(stderr, "%s\n", msgtext);

if (severity > 10) {

fprintf(stderr, "%s: error: severity %d > 10, exiting\n", 

options.appname, severity);

exit(severity);

}


return 0;

}


int

err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, 

   char *dberrstr, char *oserrstr)

{

if (dberr) {

fprintf(stderr, "%s: Msg %d, Level %d\n", 

options.appname, dberr, severity);

fprintf(stderr, "%s\n\n", dberrstr);

}


else {

fprintf(stderr, "%s: DB-LIBRARY error:\n\t", options.appname);

fprintf(stderr, "%s\n", dberrstr);

}


return INT_CANCEL;

}




출처 : 
http://blog.gmane.org/gmane.comp.db.tds.freetds/month=20100106
http://www.freetds.org/userguide/samplecode.htm#SAMPLECODE.ERRORS