Файл сокета домена Unix все еще присутствует после его закрытия

Вот что я пытаюсь сделать в ghci (Haskell REPL):

>>> import Network.Socket
>>> sock <- socket AF_UNIX Stream defaultProtocol
>>> bind sock (SockAddrUnix "./test.socket")
>>> listen sock 5
>>> close sock

На данный момент ./test.socket находится в файловой системе, отказываясь от соединений, но я ожидаю, что после закрытия соединения для прослушивания файл также будет удален. Я считаю, что это стандартное соглашение Unix, не относящееся к Haskell, так в чем причина того, что файл лежит после его закрытия?

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

>>> sock2 <- socket AF_UNIX Stream defaultProtocol
>>> bind sock (SockAddrUnix "./test.socket")
*** Exception: bind: resource busy (Address already in use)

Итак, если я не могу повторно привязать другой сокет к файлу или повторно подключиться к нему, потому что он закрыт, в чем смысл?

Обновление: запись man для unix упоминает:

Привязка к сокету с именем файла создает сокет в файловой системе, который должен быть удален вызывающей стороной, когда он больше не нужен (используя unlink(2)). Применяется обычная семантика близкого окружения UNIX; сокет может быть отключен в любое время и будет окончательно удален из файловой системы, когда будет закрыта последняя ссылка на него.

Таким образом, ожидается, что пользователь unlink явно сокет, но это все еще не отвечает на мой вопрос. Какой смысл иметь его, если вы ничего не можете сделать с сокетом?

Сказывается ли здесь мое предвзятое отношение к высокоуровневому программированию? Является ли такая явность нормой при программировании на системном уровне?


person Danny Navarro    schedule 09.02.2014    source источник
comment
@wildplasser Я не могу привязаться к тому же объекту файловой системы ... Я обновил вопрос.   -  person Danny Navarro    schedule 09.02.2014
comment
Exception: bind: resource busy (Address already in use) одновременно только один процесс может привязываться к адресу. Вероятно, он уже используется другим процессом.   -  person wildplasser    schedule 09.02.2014
comment
Я не могу найти ни одного процесса, использующего сокеты (ss -aA unix). Даже после перезагрузки системы я продолжаю получать ту же ошибку.   -  person Danny Navarro    schedule 10.02.2014
comment
Для сокетов домена unix вы должны использовать ss -l -a -funix (или просто старый netstat -a)   -  person wildplasser    schedule 11.02.2014
comment
@wildplasser вы не можете прослушивать уже существующий сокет домена unix независимо от того, использует ли его в настоящее время другой процесс.   -  person Jeremy List    schedule 07.05.2014
comment
@JeremyList: Вы правы. Должно быть, я путал их с именованными каналами. Также: mknod(1) не поддерживает сокеты домена unix, они создаются автоматически вызовом socket(). ... Удаление комментария...   -  person wildplasser    schedule 07.05.2014


Ответы (1)


я написал это

createSocket :: FilePath -> IO Socket
createSocket path = do
  removeIfExists path
  sock <- socket AF_UNIX Stream 0
  bind sock $ SockAddrUnix path
  return sock

removeIfExists :: FilePath -> IO ()
removeIfExists fileName = removeLink fileName `catch` handleExists
  where handleExists e
          | isDoesNotExistError e = return ()
          | otherwise = throwIO e

ОБНОВЛЕНИЕ: закрытие сокета:

closeSocket :: Socket -> IO ()
closeSocket sock = do
  name <- getSocketName sock
  close sock
  case name of
    SockAddrUnix path -> removeIfExists path
    _ -> return ()
person Community    schedule 05.04.2016
comment
Если вы заглянете в исходники mysql (например), вы увидите, что mysqld также удаляет файл сокета. - person ; 05.04.2016