Bug fixes for fcntl and o_cloexec

Add fcntl to schemes
Fix debug: hang
This commit is contained in:
Jeremy Soller
2017-04-19 21:56:09 -06:00
parent 40ff16e42d
commit efd64d55e1
19 changed files with 204 additions and 43 deletions
+34 -15
View File
@@ -6,7 +6,7 @@ use scheme::{self, FileHandle};
use syscall;
use syscall::data::{Packet, Stat};
use syscall::error::*;
use syscall::flag::{F_SETFL, O_ACCMODE, O_RDONLY, O_WRONLY, MODE_DIR, MODE_FILE};
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_RDONLY, O_WRONLY, MODE_DIR, MODE_FILE};
pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
let (file, pid, uid, gid) = {
@@ -303,7 +303,7 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: &[u8]) -> Result<FileHandle
}
}
// File descriptor controls
/// File descriptor controls
pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
let file = {
let contexts = context::contexts();
@@ -313,6 +313,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
file
};
// Communicate fcntl with scheme
let res = {
let scheme = {
let schemes = scheme::schemes();
@@ -322,17 +323,29 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
scheme.fcntl(file.number, cmd, arg)?
};
if cmd == F_SETFL {
// Perform kernel operation if scheme agrees
{
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut files = context.files.lock();
let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?;
let accmode = file.flags & O_ACCMODE;
file.flags = accmode | arg & !O_ACCMODE;
match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
Some(ref mut file) => match cmd {
F_GETFL => {
Ok(file.flags)
},
F_SETFL => {
let new_flags = (file.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
file.flags = new_flags;
Ok(0)
},
_ => {
Err(Error::new(EINVAL))
}
},
None => Err(Error::new(EBADF))
}
}
Ok(res)
}
/// Register events for file
@@ -342,12 +355,16 @@ pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut files = context.files.lock();
let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?;
if let Some(event_id) = file.event.take() {
println!("{:?}: {:?}:{}: events already registered: {}", fd, file.scheme, file.number, event_id);
context::event::unregister(fd, file.scheme, event_id);
match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
Some(ref mut file) => {
if let Some(event_id) = file.event.take() {
println!("{:?}: {:?}:{}: events already registered: {}", fd, file.scheme, file.number, event_id);
context::event::unregister(fd, file.scheme, event_id);
}
file.clone()
},
None => return Err(Error::new(EBADF))
}
file.clone()
};
let scheme = {
@@ -361,8 +378,10 @@ pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut files = context.files.lock();
let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?;
file.event = Some(event_id);
match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
Some(ref mut file) => file.event = Some(event_id),
None => return Err(Error::new(EBADF)),
}
}
context::event::register(fd, file.scheme, event_id);
Ok(0)
+4 -6
View File
@@ -253,15 +253,14 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
// This has to be done outside the context lock to prevent deadlocks
if flags & CLONE_FILES == 0 {
for (_fd, mut file_option) in files.lock().iter_mut().enumerate() {
let new_file_option = if let Some(file) = *file_option {
let new_file_option = if let Some(ref file) = *file_option {
let result = {
let scheme = {
let schemes = scheme::schemes();
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
scheme.clone()
};
let result = scheme.dup(file.number, b"clone");
result
scheme.dup(file.number, b"clone")
};
match result {
Ok(new_number) => {
@@ -731,7 +730,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
// Duplicate current files using b"exec", close previous
for (fd, mut file_option) in files.lock().iter_mut().enumerate() {
let new_file_option = if let Some(file) = *file_option {
let new_file_option = if let Some(ref file) = *file_option {
// Duplicate
let result = {
if file.flags & O_CLOEXEC == O_CLOEXEC {
@@ -742,8 +741,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
schemes.get(file.scheme).map(|scheme| scheme.clone())
};
if let Some(scheme) = scheme_option {
let result = scheme.dup(file.number, b"exec");
result
scheme.dup(file.number, b"exec")
} else {
Err(Error::new(EBADF))
}