LINUX.ORG.RU

Разделение ресурсов в Rust

 , , ,


0

4

Есть такой кусок кода:

extern crate chan;
extern crate chan_signal;
use chan_signal::Signal;
use std::thread;
use std::net::UdpSocket;

fn main() {
    // Initialize system signals handler
    let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);

    // Create UDP socket
    let socket = UdpSocket::bind(
        ("0.0.0.0", 10000)
    ).unwrap();

    // Spawn handler thread
    thread::spawn( move ||  {
        let mut buf = [0; 1024];
        loop {
            // Waiting for incoming message
            let (n, src) = socket.recv_from(&mut buf).unwrap();

            println!("Received {} bytes from {}: {:?}", n, src, &buf[..n]);
        }
    });
    
    // In main thread wait for system signal
    let sig = signal.recv().unwrap();

    // Close socket
    drop(socket);
}

Он, ясно дело, не компилируется, так как сокет заимствован потоком обработчика, когда я пытаюсь его закрыть.
В сях я бы просто прихлопнул сокет и вышел, тут же все, видимо, не так просто.
Как закрыть сокет при получении SIGTERM, если в этот момент поток владеющий им заблокирован вызовом recv_from?

★★★★★

Последнее исправление: mersinvald (всего исправлений: 1)
Ответ на: комментарий от quantum-troll

Открытый сокет в системе и невозможность перебиндиться при следующем запуске приложения, говорят мне об обратном.

mersinvald ★★★★★
() автор топика
Ответ на: комментарий от quantum-troll

Нашел вот это: https://www.reddit.com/r/rust/comments/37attn/which_is_a_best_way_to_handle_s...

Прекрасный язык, настолько безопасный, что даже блокирующие вызовы использовать нельзя с безопасным освобождением ресурсов :)

Смешно, но, видимо придется использовать асинхронные сокеты.

mersinvald ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Вот это знатные костыли! =)))

Костыль - это то, что в потоке не вызывается деструктор, т.к. поток не принимает сигнал SIGTERM.

anonymous
()
Ответ на: комментарий от anonymous

О, спасибо.
Не дочитал доку.
Решено.

Если подскажете как такое поведение реализовать вручную (для своих структур), не используя unsafe, буду очень благодарен

mersinvald ★★★★★
() автор топика

Когда UdpSocket'у добавят метод shutdown, всё станет хорошо: try_clone перед отдачай сокета в поток, потом shutdown на экземпляре, который остался во владении у главного потока, как это бы делалось в случае TCP.

slonopotamus
()
Ответ на: комментарий от slonopotamus

Ну, в принципе, drop делает то же самое, только через деструктор, разве нет?
Ксатати, я немного не понимаю: drop в данном случае захватывает UdpSocket по значению, и при выходе из скопа внутри drop, объект разрушается, а ресурсы освобождаются.
Но разве на него не будет при этом указывать ссылка, созданная через try_clone, которая не даст его разрушить?
Или внутри try_clone просто пресловутое копирование дескриптора?)

mersinvald ★★★★★
() автор топика
Ответ на: комментарий от mersinvald

*На самом деле* же никакого сокета нет, есть просто int с номером дескриптора. И этот int можно копировать сколько угодно (поэтому метод try_clone может существовать вообще).

slonopotamus
()
Ответ на: комментарий от slonopotamus

Это да, но вдруг там тоже хитрое управление ресурсами)

mersinvald ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.