[완료] exec 계열 함수의 오류 처리

freesky의 이미지

현재 리눅스 프로그래밍 초보라서 모르는 것이 많습니다.
현재 졸업과제로 웹서버를 만들고 있는데 CGI 처리 부분을 구현하고 있습니다.
내용은 프로세스를 분기한 다음 exec함수로 다른 프로그램을 실행하는 것입니다.
개요를 말씀드리자면...

1. fork 함수로 프로세스를 분기합니다.
2. execl 함수로 자식 프로세스에서 다른 프로그램을 실행합니다.
3. 만약 execl로 실행하려는 프로그램이 존재하지 않는다면 자식 프로세스를 비정상 종료합니다.
4. 자식 프로세스의 비정상 종료에 대한 처리는 부모 프로세스에서 합니다.

부모 프로세스에서 WIFEXITED 등의 매크로를 이용하여 자식 프로세스의 종료 상황을 알 수 있다는 것은 책을 통해 알았습니다.
그런데 자식 프로세스를 비정상적으로 종료하는 방법을 잘 모르겠습니다.

제가 작성한 코드의 일부분입니다.

1) 자식 프로세스 부분

			if(execl(filename, req->uri+5, (char*) 0) == -1)
				abort();

2) 부모 프로세스 부분

                wait(&status);
		if(WIFEXITED(status) == 0)
		{
			req->uri[query_index] = '\0';
			make_response_header(404, req, NULL, send_buf);
			write(csock, send_buf, strlen(send_buf));
			return ;
		}

execl 함수가 오류를 일으키면 -1을 반환한다고 하더군요.(해당 파일이 없을 경우에도 이렇게 되는지는 모르겠습니다.)
그래서 자식 프로세스 부분에서 execl 함수의 반환값이 -1이면 비정상적으로 종료하도록 abort() 함수를 넣었습니다.
파일을 제대로 지정했을 때에는 정상적으로 동작하는데 틀린 파일 이름을 주었을 때에는 웹브라우저에서 처리를 못하고 무한 루프를 돕니다. 그리고 자식 프로세스도 종료가 되지 않습니다.
아무래도 오류 발생 시 자식 프로세스 종료가 잘못된 것 같은데 부모 프로세스에서 WIFEXITED를 이용하여 오류처리를 하려면 어떻게 해야 할까요?

kgykingdom의 이미지

실행하고자 하는 해당 파일이 없는 경우에는 에러 처리를 할 수 없습니다. 저도 예전에 그거에 대해서 고민을 해봤는데. 프로그램이 실행되었을때 해당 프로그램에 대한 결과값을 받아 올 수 있지만, 프로그램이 있는지 없는지에 대해서는 exec() 가 결과를 리턴하지 않는 걸로 알고 있습니다. 차라리 access() 를 이용해서 파일이 존재하는지 알아 보시고 있으면 exec() 로 실행하는 방향으로 하시는게 좋을듯 싶습니다.

제가 잘못 알고 있을 수도 있으니.. 다른 분들께도 조언들어 보세요. ㅎㅎ

freesky의 이미지

답변 감사합니다.

올해에는 꼭 노트북이 생기게 해 주세요.

freesky의 이미지

갖은 노력 끝에 결국 해결했습니다.
exec 계열 함수들은 오류가 발생될 시 -1을 반환하고 errno에 다음과 같은 오류 코드를 넣는다는군요.

Quote:

E2BIG
새로운 프로세스의 인자와 환경변수 리스트가 시스템에서 정한 ARG_MAX 크기제한보다 큼

EINVAL
새로운 프로세스가 적절한 권한을 가지며 실행 가능한 이진 파일형식이지만 시스템에서 해당 형식으로 구성된 실행파일을 실행할 수 없음

ENOENT
Path 또는 file의 구성요소가 존재하지 않는 파일이거나, path나 file이 비어있는 문자열임

ENOEXEC
이미지 파일이 적절한 접근권한을 갖지만 시스템이 인식하지 못하는 형식임(execlp나 execvp에는 적용되지 않음)

ELOOP
Path 또는 file 인자의 검색에 루프가 존재함

ENAMETOOLONG
Path 또는 file의 길이가 PATH_MAX보다 크거나, 경로명의 구성요소가 NAME_MAX보다 큼

EACCES
새로운 프로세스의 경로명 앞부분에 대한 검색권한이 없거나,
새로운 프로세스의 이미지 파일에 대한 실행권한이 없거나,
새로운 프로세스의 이미지 파일이 정규파일이 아니어서 실행할 수 없음

ENOTDIR
이미지 파일 경로명의 앞부분이 디렉토리가 아님

웹 브라우저에서 무한 루프를 돌던 이유는 이전에 따로 설정해 놓은 SIGCHLD 신호 핸들러가 문제였습니다. 프로세스를 두 번 분기했는데 첫 번째 분기 시 설정해 놓은 신호 처리 함수 때문에 두 번째 분기된 프로세스가 종료 정보를 제대로 전달하지 못하더군요. 그래서

signal(SIGCHLD, SIG_DFL)

로 기본 동작으로 복구한 다음에 실행하니 종료 코드를 제대로 반환합니다.

올해에는 꼭 노트북이 생기게 해 주세요.

eungkyu의 이미지

아, 그런데 파일이 없는 것을 처리할 때 abort()를 사용하는 것은 약간 어울리지 않는 면이 있는 것 같습니다. 보통 abort()는 더 이상 해결할 수 없는 상태가 되었을 때 core dump를 내고 강제로 죽이는 용도로 사용하지, 앞 상황처럼 정상적인 에러 처리로 사용하는 함수는 아닙니다.

이와 같은 경우에는 exit(error_code); 이런 식으로 종료시킨 다음에 error_code를 검사하는 방법이 더 좋아보입니다.

아니면 아예 fork()를 하기 전에 파일이 존재하고 실행 가능한지 살펴보고 그렇지 않으면 fork() 자체를 하지 않는게 퍼포먼스 측면에서는 좋아보이네요. 물론 fork() 후 다시 한번 에러 처리를 하긴 해야겠지만요.

freesky의 이미지

충고 감사합니다. 현재 abort() 함수는 뺐고요. 말씀하신 대로 exit() 함수로 처리를 했습니다.

저도 fork()로 프로세스를 분기하기 전에 파일 존재 여부와 실행 가능 여부를 조사해서 미리 프로세스를 종료하는 방법을 생각하긴 했는데 exec 함수 연습 겸 그냥 이런 식으로 했습니다.

임베디드 시스템에 들어갈 소스라서 분기 전에 조사하는 것이 좋을 것 같기도 합니다.

올해에는 꼭 노트북이 생기게 해 주세요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.