Changeset 11882

Show
Ignore:
Timestamp:
03/17/05 15:25:07 (4 years ago)
Author:
bonefish
Message:

We were handling closing of file descriptors incorrectly. The close_*()
and free_*_cookie() hooks of the underlying FS were always called
together when the reference count of the FD dropped to zero. When
blocking operations (reading/writing) on the FD were still in progress
this would never happen, though. Now we additionally maintain an open
count and call the close_*() hook when it drops to zero.

Location:
haiku/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • haiku/trunk/headers/private/kernel/fd.h

    r10434 r11882  
    3737        int32   type;               /* descriptor type */ 
    3838        int32   ref_count; 
     39        int32   open_count; 
    3940        struct fd_ops *ops; 
    4041        union { 
  • haiku/trunk/src/kernel/core/fs/fd.c

    r10221 r11882  
    5555        descriptor->cookie = NULL; 
    5656        descriptor->ref_count = 1; 
     57        descriptor->open_count = 1; 
    5758        descriptor->open_mode = 0; 
    5859        descriptor->pos = 0; 
     
    109110        // free the descriptor if we don't need it anymore 
    110111        if (atomic_add(&descriptor->ref_count, -1) == 1) { 
    111                 // close the underlying object (and free any resources allocated there) 
    112                 if (descriptor->ops->fd_close) 
    113                         descriptor->ops->fd_close(descriptor); 
     112                // free the underlying object 
    114113                if (descriptor->ops->fd_free) 
    115114                        descriptor->ops->fd_free(descriptor); 
     
    142141 
    143142 
    144 /**     Removes the file descriptor in the specified slot, and 
    145  *      reduces its reference counter. 
     143/**     Removes the file descriptor in the specified slot. 
    146144 */ 
    147145 
    148 static void 
     146static struct file_descriptor * 
    149147remove_fd(struct io_context *context, int fd) 
    150148{ 
     
    152150 
    153151        if (fd < 0) 
    154                 return; 
     152                return NULL; 
    155153 
    156154        mutex_lock(&context->io_mutex); 
     
    166164        mutex_unlock(&context->io_mutex); 
    167165 
    168         if (descriptor) 
    169                 put_fd(descriptor); 
     166        return descriptor; 
    170167} 
    171168 
     
    303300 
    304301 
     302static status_t 
     303common_close(int fd, bool kernel) 
     304{ 
     305        struct io_context *io = get_current_io_context(kernel); 
     306        struct file_descriptor *descriptor = remove_fd(io, fd); 
     307 
     308        if (descriptor == NULL) 
     309                return B_FILE_ERROR; 
     310 
     311        #ifdef TRACE_FD 
     312                if (!kernel) 
     313                        TRACE(("_user_close(descriptor = %p)\n", descriptor)); 
     314        #endif 
     315 
     316        if (atomic_add(&descriptor->open_count, -1) == 1) { 
     317                if (descriptor->ops->fd_close) 
     318                        descriptor->ops->fd_close(descriptor); 
     319        } 
     320 
     321        put_fd(descriptor); 
     322                // the reference associated with the slot 
     323 
     324        return B_OK; 
     325} 
     326 
     327 
    305328//      #pragma mark - 
    306329/*** USER routines ***/  
     
    593616_user_close(int fd) 
    594617{ 
    595         struct io_context *io = get_current_io_context(false); 
    596         struct file_descriptor *descriptor = get_fd(io, fd); 
    597  
    598         if (descriptor == NULL) 
    599                 return B_FILE_ERROR; 
    600  
    601         TRACE(("user_close(descriptor = %p)\n", descriptor)); 
    602  
    603         remove_fd(io, fd); 
    604  
    605         put_fd(descriptor); 
    606         return B_OK; 
     618        return common_close(fd, true); 
    607619} 
    608620 
     
    857869_kern_close(int fd) 
    858870{ 
    859         struct io_context *io = get_current_io_context(true); 
    860         struct file_descriptor *descriptor = get_fd(io, fd); 
    861  
    862         if (descriptor == NULL) 
    863                 return B_FILE_ERROR; 
    864  
    865         remove_fd(io, fd); 
    866  
    867         put_fd(descriptor); 
    868         return B_OK; 
     871        return common_close(fd, true); 
    869872} 
    870873