* The close-on-exit bitmap vfs_new_io_context() created was a byte
short, if the FD table size wasn't a multiple of 8. * vfs_resize_fd_table() didn't seem to know at all about the close-on-exit bitmap. The pointer in the io_context would point to free()d memory afterwards. This explains the sporadically closed stdin/out/err descriptors in programs started from Tracker and Deskbar. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20413 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d349f3c941
commit
6376aa3f7a
@ -3244,14 +3244,14 @@ vfs_new_io_context(void *_parentContext)
|
||||
|
||||
// allocate space for FDs and their close-on-exec flag
|
||||
context->fds = (file_descriptor **)malloc(sizeof(struct file_descriptor *) * tableSize
|
||||
+ tableSize / 8);
|
||||
+ (tableSize + 7) / 8);
|
||||
if (context->fds == NULL) {
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(context->fds, 0, sizeof(struct file_descriptor *) * tableSize
|
||||
+ tableSize / 8);
|
||||
+ (tableSize + 7) / 8);
|
||||
context->fds_close_on_exec = (uint8 *)(context->fds + tableSize);
|
||||
|
||||
if (mutex_init(&context->io_mutex, "I/O context") < 0) {
|
||||
@ -3330,7 +3330,7 @@ vfs_free_io_context(void *_ioContext)
|
||||
static status_t
|
||||
vfs_resize_fd_table(struct io_context *context, const int newSize)
|
||||
{
|
||||
void *fds;
|
||||
struct file_descriptor **fds;
|
||||
int status = B_OK;
|
||||
|
||||
if (newSize <= 0 || newSize > MAX_FD_TABLE_SIZE)
|
||||
@ -3338,42 +3338,57 @@ vfs_resize_fd_table(struct io_context *context, const int newSize)
|
||||
|
||||
mutex_lock(&context->io_mutex);
|
||||
|
||||
if ((size_t)newSize < context->table_size) {
|
||||
int oldSize = context->table_size;
|
||||
int oldCloseOnExitBitmapSize = (oldSize + 7) / 8;
|
||||
int newCloseOnExitBitmapSize = (newSize + 7) / 8;
|
||||
|
||||
if (newSize < oldSize) {
|
||||
// shrink the fd table
|
||||
int i;
|
||||
|
||||
// Make sure none of the fds being dropped are in use
|
||||
for(i = context->table_size; i-- > newSize;) {
|
||||
for (int i = oldSize; i-- > newSize;) {
|
||||
if (context->fds[i]) {
|
||||
status = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
fds = malloc(sizeof(struct file_descriptor *) * newSize);
|
||||
fds = (struct file_descriptor **)malloc(
|
||||
sizeof(struct file_descriptor *) * newSize
|
||||
+ newCloseOnExitBitmapSize);
|
||||
if (fds == NULL) {
|
||||
status = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(fds, context->fds, sizeof(struct file_descriptor *) * newSize);
|
||||
|
||||
// copy close-on-exit bitmap
|
||||
memcpy(fds + newSize, context->fds + oldSize, newCloseOnExitBitmapSize);
|
||||
} else {
|
||||
// enlarge the fd table
|
||||
|
||||
fds = malloc(sizeof(struct file_descriptor *) * newSize);
|
||||
fds = (struct file_descriptor **)malloc(
|
||||
sizeof(struct file_descriptor *) * newSize
|
||||
+ newCloseOnExitBitmapSize);
|
||||
if (fds == NULL) {
|
||||
status = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// copy the fd array, and zero the additional slots
|
||||
memcpy(fds, context->fds, sizeof(void *) * context->table_size);
|
||||
memset((char *)fds + (sizeof(void *) * context->table_size), 0,
|
||||
sizeof(void *) * (newSize - context->table_size));
|
||||
memcpy(fds, context->fds, sizeof(void *) * oldSize);
|
||||
memset(fds + oldSize, 0, sizeof(void *) * (newSize - oldSize));
|
||||
|
||||
// copy close-on-exit bitmap, and zero out additional bytes
|
||||
memcpy(fds + newSize, context->fds + oldSize, oldCloseOnExitBitmapSize);
|
||||
memset((uint8*)(fds + newSize) + oldCloseOnExitBitmapSize, 0,
|
||||
newCloseOnExitBitmapSize - oldCloseOnExitBitmapSize);
|
||||
}
|
||||
|
||||
free(context->fds);
|
||||
context->fds = (file_descriptor **)fds;
|
||||
context->fds = fds;
|
||||
context->fds_close_on_exec = (uint8 *)(context->fds + newSize);
|
||||
context->table_size = newSize;
|
||||
|
||||
out:
|
||||
|
Loading…
x
Reference in New Issue
Block a user