Thread Naming Doesn't Work on Linux

Code snippet to reproduce:

 #!/usr/bin/env swift

  import Foundation

  class MyThread: Thread {
      let extraParameter: Int

      init(extraParameter: Int) {
          self.extraParameter = extraParameter
          super.init()
          self.name = "tree"
      }

      override func main() {
          print("My thread name is: \(Thread.current.name!)")
      }
  }

  var test = MyThread(extraParameter: 3)
  test.start()

  sleep(2)

Running this code on macOS 10.15.6 produces the expected output:

My thread name is: tree

However, on Ubuntu 18.04, I get this:

My thread name is: swift

When attempting this from within a package target, the thread has the name of the target, rather than "swift". I don't seem to be able to set a thread's name on Linux. When showing custom thread names in htop, I see the same thread name there. It appears to be a failure to set the thread name, not to get it.

On macOS I tried this with Xcode 12 Beta 6 toolchain as well as the Swift for Tensorflow v0.11 toolchain:

$ which swift
/Library/Developer/Toolchains/swift-tensorflow-RELEASE-0.11.xctoolchain/usr/bin/swift
$ swift --version
Swift version 5.3-dev (LLVM db8896f3f345af2, Swift 61684f62a6132c0)
Target: x86_64-apple-darwin19.6.0

On Ubuntu 18.04 I tried this with the 5.3 release branch:

$ which swift
/home/xander/swift-5.3-DEVELOPMENT-SNAPSHOT-2020-08-31-a-ubuntu18.04/usr/bin/swift
$ swift --version
Swift version 5.3-dev (LLVM 3fa9679add, Swift d24649a4d6)

And I also tried with the Swift for Tensorflow v0.10 toolchain:

$ which swift
/home/xander/swift-tensorflow-RELEASE-0.10-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift
$ swift --version
Swift version 5.3-dev (LLVM 55d27a5828, Swift 6a5d84ec08)
Target: x86_64-unknown-linux-gnu

Is this known or expected?

A friend helped me resolve this. It was a combination of issues:

  • First, the name of a pthread on Linux can have at most 15 characters, so I had to shorten the name of the thread I was using in my project (This problem does not appear in the above example).
  • Second, there are initialization and race conditions such that the Thread names needs to be set later. Setting in the main() rather than in the init() works in my above example.

My friend's explanation:

I just checked the code for Thread in swift-corelibs-foundation and it looks like the setter for name tries to access the _thread property, which is only set after the thread has been started, so the name can‘t be set. pthread_create will immediately start the thread, but Foundation doesn‘t. I agree that this behavior is unexpected, but there‘s no great option to make it work as is. To fix this specific example, the name should be set from main instead of init, but I think even then there would still be a race

5 Likes

Please copy-paste this into a bugs.swift.org bug so I can track a fix.