ts-udpsrc: Dup the socket so that both tokio and GIO can take ownership of it

Otherwise both would be closing the same socket, which a) breaks the
second user of the socket if any and b) could on the second close cause
a completely unrelated socket to be closed.

Windows part of the code is untested.
This commit is contained in:
Sebastian Dröge 2018-11-30 19:38:25 +02:00
parent 4ac6863eed
commit 9750195caa
3 changed files with 47 additions and 6 deletions

View file

@ -5,6 +5,7 @@ authors = ["Sebastian Dröge <sebastian@centricular.com>"]
license = "LGPL-2.1+"
[dependencies]
libc = "0.2"
glib-sys = { git = "https://github.com/gtk-rs/sys" }
gobject-sys = { git = "https://github.com/gtk-rs/sys" }
gio-sys = { git = "https://github.com/gtk-rs/sys" }
@ -26,6 +27,9 @@ either = "1.0"
rand = "0.5"
net2 = "0.2"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winsock2", "processthreadsapi"] }
[lib]
name = "gstthreadshare"
crate-type = ["cdylib", "rlib"]

View file

@ -17,6 +17,8 @@
#![crate_type = "cdylib"]
extern crate libc;
extern crate gio_sys as gio_ffi;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
@ -47,6 +49,9 @@ extern crate lazy_static;
extern crate net2;
#[cfg(windows)]
extern crate winapi;
mod iocontext;
mod socket;

View file

@ -95,12 +95,16 @@ impl GioSocketWrapper {
#[cfg(unix)]
fn get<T: FromRawFd>(&self) -> T {
unsafe { FromRawFd::from_raw_fd(gio_ffi::g_socket_get_fd(self.socket)) }
use libc;
unsafe { FromRawFd::from_raw_fd(libc::dup(gio_ffi::g_socket_get_fd(self.socket))) }
}
#[cfg(windows)]
fn get<T: FromRawSocket>(&self) -> T {
unsafe { FromRawSocket::from_raw_socket(ffi::g_socket_get_fd(self.socket) as _) }
unsafe {
FromRawSocket::from_raw_socket(dup_socket(ffi::g_socket_get_fd(self.socket) as _) as _)
}
}
}
@ -120,6 +124,32 @@ impl Drop for GioSocketWrapper {
}
}
#[cfg(windows)]
unsafe fn dup_socket(socket: usize) -> usize {
use std::mem;
use winapi::shared::minwindef::DWORD;
use winapi::shared::ws2def;
use winapi::um::processthreadsapi;
use winapi::um::winsock2;
use winapi::um::winsock2;
let mut proto_info = mem::zeroed();
let ret = winsock2::WSADuplicateSocketA(
socket,
processthreadsapi::GetCurrentProcess(),
&mut proto_info,
);
assert_eq!(ret, 0);
winsock2::WSASocketA(
ws2def::AF_INET,
ws2def::SOCK_DGRAM,
ws2def::IPPROTO_UDP,
&mut proto_info,
0,
0,
);
}
#[derive(Debug, Clone)]
struct Settings {
address: Option<String>,
@ -223,8 +253,8 @@ pub struct UdpReader {
}
impl UdpReader {
pub fn new(socket: net::UdpSocket) -> Self {
Self { socket: socket }
fn new(socket: net::UdpSocket) -> Self {
Self { socket }
}
}
@ -668,7 +698,9 @@ impl UdpSrc {
// Store the socket as used-socket in the settings
#[cfg(unix)]
{
let fd = socket.as_raw_fd();
use libc;
let fd = unsafe { libc::dup(socket.as_raw_fd()) };
// This is technically unsafe because it allows
// us to share the fd between the socket and the
@ -694,7 +726,7 @@ impl UdpSrc {
}
#[cfg(windows)]
{
let fd = socket.as_raw_socket();
let fd = unsafe { dup_socket(socket.as_raw_socket() as _) as _ };
// This is technically unsafe because it allows
// us to share the fd between the socket and the