Changeset 2116

Show
Ignore:
Timestamp:
03/02/2008 03:42:14 PM (6 months ago)
Author:
stbuehler
Message:

mod_cgi: add a event-handler for STDERR_FILENO and log it with ERROR()

  • it was not a good idea to just close STDERR_FILENO; if the cgi
    opens a file and gets the filedescriptor 2 it will write its errors
    to this file too (imagine a cgi generating some images... )
Location:
trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/NEWS

    r2110 r2116  
    2020  * fix sending source of cgi script instead of 500 error if fork fails 
    2121  * fix min-procs handling in mod_scgi.c, just set to max-procs (patch from #623) 
     22  * mod_cgi: add a event-handler for STDERR_FILENO and log it with ERROR() 
    2223 
    2324- 1.5.0-r19.. - 
  • trunk/src/mod_cgi.c

    r2108 r2116  
    7878 
    7979        iosocket *sock; 
     80        iosocket *sock_err; 
    8081        iosocket *wb_sock; 
    8182 
    8283        chunkqueue *rb; 
     84        chunkqueue *rb_err; 
    8385        chunkqueue *wb; 
    8486 
     
    9395 
    9496        sess->sock = iosocket_init(); 
     97        sess->sock_err = iosocket_init(); 
    9598        sess->wb_sock = iosocket_init(); 
    9699        sess->wb = chunkqueue_init(); 
    97100        sess->rb = chunkqueue_init(); 
     101        sess->rb_err = chunkqueue_init(); 
    98102 
    99103        return sess; 
     
    104108 
    105109        iosocket_free(sess->sock); 
     110        iosocket_free(sess->sock_err); 
    106111        iosocket_free(sess->wb_sock); 
    107112 
    108113        chunkqueue_free(sess->wb); 
    109114        chunkqueue_free(sess->rb); 
     115        chunkqueue_free(sess->rb_err); 
    110116 
    111117        free(sess); 
     
    402408        } 
    403409 
     410        if (sess->sock_err->fd != -1) { 
     411                /* close connection to the cgi-script */ 
     412                fdevent_event_del(srv->ev, sess->sock_err); 
     413                fdevent_unregister(srv->ev, sess->sock_err); 
     414        } 
     415 
    404416        if (sess->wb_sock->fd != -1) { 
    405417                close(sess->wb_sock->fd); 
     
    547559} 
    548560 
     561/* so all cgi errors have the same source line as origin */ 
     562static void cgi_log_err(const char *msg) { 
     563        ERROR("error from cgi: %s", msg); 
     564} 
     565 
     566static void cgi_copy_err(chunkqueue *cq) { 
     567        buffer *line = buffer_init(); 
     568        chunk *c; 
     569 
     570        for (c = cq->first; c; c = c->next) { 
     571                off_t we_have; 
     572                char *str, *nl; 
     573 
     574                if (c->type != MEM_CHUNK) { 
     575                        ERROR("%s", "wrong chunk type"); 
     576                        chunk_set_done(c); 
     577                        continue; 
     578                } 
     579 
     580                we_have = c->mem->used - 1 - c->offset; 
     581                str = c->mem->ptr + c->offset; 
     582                if (we_have <= 0) continue; 
     583 
     584                for ( ; NULL != (nl = strchr(str, '\n')); str = nl+1) { 
     585                        *nl = '\0'; 
     586                        if (!buffer_is_empty(line)) { 
     587                                buffer_append_string(line, str); 
     588                                cgi_log_err(SAFE_BUF_STR(line)); 
     589                                buffer_reset(line); 
     590                        } else { 
     591                                cgi_log_err(str); 
     592                        } 
     593                } 
     594                if (*str) { 
     595                        buffer_append_string(line, str); 
     596                } 
     597                chunk_set_done(c); 
     598        } 
     599 
     600        if (!buffer_is_empty(line)) { 
     601                cgi_log_err(SAFE_BUF_STR(line)); 
     602        } 
     603        chunkqueue_remove_finished_chunks(cq); 
     604} 
     605 
     606static handler_t cgi_handle_err_fdevent(void *s, void *ctx, int revents) { 
     607        server      *srv  = (server *)s; 
     608        cgi_session *sess = ctx; 
     609        connection  *con  = sess->remote_con; 
     610 
     611        if (revents & FDEVENT_IN) { 
     612                switch (srv->network_backend_read(srv, con, sess->sock_err, sess->rb_err)) { 
     613                case NETWORK_STATUS_CONNECTION_CLOSE: 
     614                        fdevent_event_del(srv->ev, sess->sock_err); 
     615 
     616                        /* connection closed. close the read chunkqueue. */ 
     617                        sess->rb_err->is_closed = 1; 
     618                        break; 
     619                case NETWORK_STATUS_SUCCESS: 
     620                        break; 
     621                default: 
     622                        ERROR("%s", "oops, we failed to read"); 
     623                        break; 
     624                } 
     625 
     626                cgi_copy_err(sess->rb_err); 
     627        } 
     628 
     629        if (revents & FDEVENT_ERR) { 
     630                fdevent_event_del(srv->ev, sess->sock_err); 
     631        } 
     632 
     633        return HANDLER_FINISHED; 
     634} 
     635 
    549636 
    550637static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) { 
     
    581668        int to_cgi_fds[2]; 
    582669        int from_cgi_fds[2]; 
     670        int from_cgi_err_fds[2]; 
    583671        struct stat st; 
    584672 
     
    601689 
    602690        if (pipe(from_cgi_fds)) { 
     691                close(to_cgi_fds[0]); close(to_cgi_fds[1]); 
     692                log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno)); 
     693                return -1; 
     694        } 
     695 
     696        if (pipe(from_cgi_err_fds)) { 
     697                close(to_cgi_fds[0]); close(to_cgi_fds[1]); 
     698                close(from_cgi_fds[0]); close(from_cgi_fds[1]); 
    603699                log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno)); 
    604700                return -1; 
     
    626722                close(from_cgi_fds[0]); 
    627723 
     724                /* move stderr to from_cgi_err_fd[1] */ 
     725                close(STDERR_FILENO); 
     726                dup2(from_cgi_err_fds[1], STDERR_FILENO); 
     727                close(from_cgi_err_fds[1]); 
     728                /* not needed */ 
     729                close(from_cgi_err_fds[0]); 
     730 
    628731                /* move the stdin to to_cgi_fd[0] */ 
    629732                close(STDIN_FILENO); 
     
    632735                /* not needed */ 
    633736                close(to_cgi_fds[1]); 
    634  
    635                 /** 
    636                  * FIXME: add a event-handler for STDERR_FILENO and let it LOG() 
    637                  */ 
    638  
    639                 close(STDERR_FILENO); 
    640737 
    641738                /* create environment */ 
     
    860957                /* error */ 
    861958                ERROR("fork() failed: %s", strerror(errno)); 
     959                close(to_cgi_fds[0]); close(to_cgi_fds[1]); 
     960                close(from_cgi_fds[0]); close(from_cgi_fds[1]); 
     961                close(from_cgi_err_fds[0]); close(from_cgi_err_fds[1]); 
    862962                return -1; 
    863963                break; 
     
    867967 
    868968                close(from_cgi_fds[1]); 
     969                close(from_cgi_err_fds[1]); 
    869970                close(to_cgi_fds[0]); 
    870971 
     
    882983                sess->sock->fd = from_cgi_fds[0]; 
    883984                sess->sock->type = IOSOCKET_TYPE_PIPE; 
     985                sess->sock_err->fd = from_cgi_err_fds[0]; 
     986                sess->sock_err->type = IOSOCKET_TYPE_PIPE; 
    884987                sess->wb_sock->fd = to_cgi_fds[1]; 
    885988                sess->wb_sock->type = IOSOCKET_TYPE_PIPE; 
     
    893996                } 
    894997 
     998                if (-1 == fdevent_fcntl_set(srv->ev, sess->sock_err)) { 
     999                        log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); 
     1000 
     1001                        cgi_session_free(sess); 
     1002 
     1003                        return -1; 
     1004                } 
     1005 
    8951006                con->plugin_ctx[p->id] = sess; 
    8961007 
    8971008                fdevent_register(srv->ev, sess->sock, cgi_handle_fdevent, sess); 
    8981009                fdevent_event_add(srv->ev, sess->sock, FDEVENT_IN); 
     1010 
     1011                fdevent_register(srv->ev, sess->sock_err, cgi_handle_err_fdevent, sess); 
     1012                fdevent_event_add(srv->ev, sess->sock_err, FDEVENT_IN); 
    8991013 
    9001014                sess->state = CGI_STATE_READ_RESPONSE_HEADER; 
     
    10901204                fdevent_unregister(srv->ev, sess->sock); 
    10911205 
     1206                fdevent_event_del(srv->ev, sess->sock_err); 
     1207                fdevent_unregister(srv->ev, sess->sock_err); 
     1208 
    10921209                cgi_session_free(sess); 
    10931210                sess = NULL; 
     
    11131230                fdevent_event_del(srv->ev, sess->sock); 
    11141231                fdevent_unregister(srv->ev, sess->sock); 
     1232 
     1233                fdevent_event_del(srv->ev, sess->sock_err); 
     1234                fdevent_unregister(srv->ev, sess->sock_err); 
    11151235 
    11161236                cgi_session_free(sess);