【问题标题】:Unix domain socket file still present after closing itUnix域套接字文件在关闭后仍然存在
【发布时间】:2014-03-06 16:36:48
【问题描述】:

这就是我在 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 entry for unix 提到:

使用文件名绑定到套接字会在文件系统中创建一个套接字 调用者在不再需要时必须删除(使用 取消链接(2))。通常的 UNIX 紧随语义适用;插座 可以随时取消链接,最终会从 文件系统的最后一次引用被关闭时。

因此,用户希望unlink 明确地使用套接字,但这仍然不能回答我的问题。如果你不能对套接字做任何事情,那还有什么理由呢?

我的高级编程偏见在这里开始了吗?在进行系统级编程时,这种明确性是常态吗?

【问题讨论】:

  • @wildplasser 我无法绑定到同一个文件系统对象...我更新了问题。
  • Exception: bind: resource busy (Address already in use) 一次只有一个进程可以绑定到一个地址。可能另一个进程已经在使用它。
  • 我找不到任何使用套接字的进程 (ss -aA unix)。即使在系统重新启动后,我仍然会收到同样的错误。
  • 对于 unix 域套接字,您应该使用 ss -l -a -funix(或者只是普通的旧 netstat -a)
  • @wildplasser,无论当前是否有其他进程在使用它,您都无法监听预先存在的 unix 域套接字。

标签: sockets unix unix-socket


【解决方案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 ()

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 2014-09-18
  • 1970-01-01
  • 2019-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多