Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 33 additions & 25 deletions vm/src/stdlib/socket.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::cell::{Cell, Ref, RefCell};
use std::io::{self, prelude::*};
use std::net::{Ipv4Addr, Shutdown, SocketAddr, ToSocketAddrs};
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::time::Duration;

use byteorder::{BigEndian, ByteOrder};
use crossbeam_utils::atomic::AtomicCell;
use gethostname::gethostname;
#[cfg(all(unix, not(target_os = "redox")))]
use nix::unistd::sethostname;
Expand All @@ -21,7 +22,8 @@ use crate::obj::objstr::{PyString, PyStringRef};
use crate::obj::objtuple::PyTupleRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{
Either, IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
Either, IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, ThreadSafe,
TryFromObject,
};
use crate::vm::VirtualMachine;

Expand All @@ -44,12 +46,14 @@ mod c {
#[pyclass]
#[derive(Debug)]
pub struct PySocket {
kind: Cell<i32>,
family: Cell<i32>,
proto: Cell<i32>,
sock: RefCell<Socket>,
kind: AtomicCell<i32>,
family: AtomicCell<i32>,
proto: AtomicCell<i32>,
sock: RwLock<Socket>,
}

impl ThreadSafe for PySocket {}

impl PyValue for PySocket {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("_socket", "socket")
Expand All @@ -60,17 +64,21 @@ pub type PySocketRef = PyRef<PySocket>;

#[pyimpl(flags(BASETYPE))]
impl PySocket {
fn sock(&self) -> Ref<Socket> {
self.sock.borrow()
fn sock(&self) -> RwLockReadGuard<'_, Socket> {
self.sock.read().unwrap()
}

fn sock_mut(&self) -> RwLockWriteGuard<'_, Socket> {
self.sock.write().unwrap()
}

#[pyslot]
fn tp_new(cls: PyClassRef, _args: PyFuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
PySocket {
kind: Cell::default(),
family: Cell::default(),
proto: Cell::default(),
sock: RefCell::new(invalid_sock()),
kind: AtomicCell::default(),
family: AtomicCell::default(),
proto: AtomicCell::default(),
sock: RwLock::new(invalid_sock()),
}
.into_ref_with_type(vm, cls)
}
Expand Down Expand Up @@ -103,12 +111,12 @@ impl PySocket {
)
.map_err(|err| convert_sock_error(vm, err))?;

self.family.set(family);
self.kind.set(socket_kind);
self.proto.set(proto);
self.family.store(family);
self.kind.store(socket_kind);
self.proto.store(proto);
sock
};
self.sock.replace(sock);
*self.sock.write().unwrap() = sock;
Ok(())
}

Expand Down Expand Up @@ -191,7 +199,7 @@ impl PySocket {
#[pymethod]
fn sendall(&self, bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<()> {
bytes
.with_ref(|b| self.sock.borrow_mut().write_all(b))
.with_ref(|b| self.sock_mut().write_all(b))
.map_err(|err| convert_sock_error(vm, err))
}

Expand All @@ -206,11 +214,11 @@ impl PySocket {

#[pymethod]
fn close(&self) {
self.sock.replace(invalid_sock());
*self.sock_mut() = invalid_sock();
}
#[pymethod]
fn detach(&self) -> RawSocket {
into_sock_fileno(self.sock.replace(invalid_sock()))
into_sock_fileno(std::mem::replace(&mut *self.sock_mut(), invalid_sock()))
}

#[pymethod]
Expand Down Expand Up @@ -384,29 +392,29 @@ impl PySocket {

#[pyproperty(name = "type")]
fn kind(&self) -> i32 {
self.kind.get()
self.kind.load()
}
#[pyproperty]
fn family(&self) -> i32 {
self.family.get()
self.family.load()
}
#[pyproperty]
fn proto(&self) -> i32 {
self.proto.get()
self.proto.load()
}
}

impl io::Read for PySocketRef {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
<Socket as io::Read>::read(&mut self.sock.borrow_mut(), buf)
<Socket as io::Read>::read(&mut self.sock_mut(), buf)
}
}
impl io::Write for PySocketRef {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
<Socket as io::Write>::write(&mut self.sock.borrow_mut(), buf)
<Socket as io::Write>::write(&mut self.sock_mut(), buf)
}
fn flush(&mut self) -> io::Result<()> {
<Socket as io::Write>::flush(&mut self.sock.borrow_mut())
<Socket as io::Write>::flush(&mut self.sock_mut())
}
}

Expand Down
49 changes: 30 additions & 19 deletions vm/src/stdlib/subprocess.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
use std::cell::RefCell;
use std::ffi::OsString;
use std::fs::File;
use std::io::ErrorKind;
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::time::Duration;

use crate::function::OptionalArg;
use crate::obj::objbytes::PyBytesRef;
use crate::obj::objlist::PyListRef;
use crate::obj::objstr::{self, PyStringRef};
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{Either, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue};
use crate::pyobject::{Either, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, ThreadSafe};
use crate::stdlib::io::io_open;
use crate::stdlib::os::{convert_io_error, raw_file_number, rust_file};
use crate::vm::VirtualMachine;

#[derive(Debug)]
struct Popen {
process: RefCell<subprocess::Popen>,
process: RwLock<subprocess::Popen>,
args: PyObjectRef,
}

// Remove once https://github.com/hniksic/rust-subprocess/issues/42 is resolved
#[cfg(windows)]
unsafe impl Sync for Popen {}

impl ThreadSafe for Popen {}

impl PyValue for Popen {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("_subprocess", "Popen")
Expand Down Expand Up @@ -103,6 +109,14 @@ fn convert_to_file_io(file: &Option<File>, mode: &str, vm: &VirtualMachine) -> P
}

impl PopenRef {
fn borrow_process(&self) -> RwLockReadGuard<'_, subprocess::Popen> {
self.process.read().unwrap()
}

fn borrow_process_mut(&self) -> RwLockWriteGuard<'_, subprocess::Popen> {
self.process.write().unwrap()
}

fn new(cls: PyClassRef, args: PopenArgs, vm: &VirtualMachine) -> PyResult<PopenRef> {
let stdin = convert_redirection(args.stdin, vm)?;
let stdout = convert_redirection(args.stdout, vm)?;
Expand Down Expand Up @@ -130,27 +144,26 @@ impl PopenRef {
.map_err(|s| vm.new_os_error(format!("Could not start program: {}", s)))?;

Popen {
process: RefCell::new(process),
process: RwLock::new(process),
args: args.args.into_object(),
}
.into_ref_with_type(vm, cls)
}

fn poll(self) -> Option<subprocess::ExitStatus> {
self.process.borrow_mut().poll()
self.borrow_process_mut().poll()
}

fn return_code(self) -> Option<subprocess::ExitStatus> {
self.process.borrow().exit_status()
self.borrow_process().exit_status()
}

fn wait(self, args: PopenWaitArgs, vm: &VirtualMachine) -> PyResult<i64> {
let timeout = match args.timeout {
Some(timeout) => self
.process
.borrow_mut()
.borrow_process_mut()
.wait_timeout(Duration::new(timeout, 0)),
None => self.process.borrow_mut().wait().map(Some),
None => self.borrow_process_mut().wait().map(Some),
}
.map_err(|s| vm.new_os_error(format!("Could not start program: {}", s)))?;
if let Some(exit) = timeout {
Expand All @@ -167,27 +180,25 @@ impl PopenRef {
}

fn stdin(self, vm: &VirtualMachine) -> PyResult {
convert_to_file_io(&self.process.borrow().stdin, "wb", vm)
convert_to_file_io(&self.borrow_process().stdin, "wb", vm)
}

fn stdout(self, vm: &VirtualMachine) -> PyResult {
convert_to_file_io(&self.process.borrow().stdout, "rb", vm)
convert_to_file_io(&self.borrow_process().stdout, "rb", vm)
}

fn stderr(self, vm: &VirtualMachine) -> PyResult {
convert_to_file_io(&self.process.borrow().stderr, "rb", vm)
convert_to_file_io(&self.borrow_process().stderr, "rb", vm)
}

fn terminate(self, vm: &VirtualMachine) -> PyResult<()> {
self.process
.borrow_mut()
self.borrow_process_mut()
.terminate()
.map_err(|err| convert_io_error(vm, err))
}

fn kill(self, vm: &VirtualMachine) -> PyResult<()> {
self.process
.borrow_mut()
self.borrow_process_mut()
.kill()
.map_err(|err| convert_io_error(vm, err))
}
Expand All @@ -202,7 +213,7 @@ impl PopenRef {
OptionalArg::Present(ref bytes) => Some(bytes.get_value().to_vec()),
OptionalArg::Missing => None,
};
let mut communicator = self.process.borrow_mut().communicate_start(bytes);
let mut communicator = self.borrow_process_mut().communicate_start(bytes);
if let OptionalArg::Present(timeout) = args.timeout {
communicator = communicator.limit_time(Duration::new(timeout, 0));
}
Expand All @@ -217,7 +228,7 @@ impl PopenRef {
}

fn pid(self) -> Option<u32> {
self.process.borrow().pid()
self.borrow_process().pid()
}

fn enter(self) -> Self {
Expand All @@ -230,7 +241,7 @@ impl PopenRef {
_exception_value: PyObjectRef,
_traceback: PyObjectRef,
) {
let mut process = self.process.borrow_mut();
let mut process = self.borrow_process_mut();
process.stdout.take();
process.stdin.take();
process.stderr.take();
Expand Down
6 changes: 5 additions & 1 deletion vm/src/stdlib/symtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustpython_parser::parser;

use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue};
use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, ThreadSafe};
use crate::vm::VirtualMachine;

pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
Expand Down Expand Up @@ -72,6 +72,8 @@ struct PySymbolTable {
symtable: symboltable::SymbolTable,
}

impl ThreadSafe for PySymbolTable {}

impl fmt::Debug for PySymbolTable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SymbolTable()")
Expand Down Expand Up @@ -158,6 +160,8 @@ struct PySymbol {
symbol: symboltable::Symbol,
}

impl ThreadSafe for PySymbol {}

impl fmt::Debug for PySymbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Symbol()")
Expand Down
4 changes: 3 additions & 1 deletion vm/src/stdlib/unicodedata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::function::OptionalArg;
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue};
use crate::pyobject::{PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue, ThreadSafe};
use crate::vm::VirtualMachine;

use itertools::Itertools;
Expand Down Expand Up @@ -60,6 +60,8 @@ struct PyUCD {
unic_version: UnicodeVersion,
}

impl ThreadSafe for PyUCD {}

impl PyValue for PyUCD {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("unicodedata", "UCD")
Expand Down
Loading