Bug 47221 - Thread.Name can only be set once inside async callback
Summary: Thread.Name can only be set once inside async callback
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: io-layer (show other bugs)
Version: 4.6.0 (C8)
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Ludovic Henry
URL:
Depends on:
Blocks:
 
Reported: 2016-11-17 18:58 UTC by Christian
Modified: 2017-02-08 21:19 UTC (History)
4 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description Christian 2016-11-17 18:58:19 UTC
After updating mono from 4.2.2 to 4.6.2.7 it is not possible anymore to name the thread in side an async callback.


public void OnAcceptTcpClient(IAsyncResult ar)
{
    Thread.CurrentThread.Name = Name;

    TcpListener listener = (TcpListener)ar.AsyncState;
    TcpClient client;

    try {
        client = listener.EndAcceptTcpClient(ar);
        // keep listening
        listener.BeginAcceptTcpClient(OnAcceptTcpClient, listener);
    }
    catch (SocketException ex) {
        Program.LogWarn("Error accepting TCP connection: {0}", ex.Message);
        return;
    }
    catch (ObjectDisposedException) {
        // The listener was Stop()'d, disposing the underlying socket and
        // triggering the completion of the callback. We're already exiting,
        // so just return.
        Program.LogDebug("Listen canceled.");
        return;
    }

    try {
        ProcessRequest(client);
    }
    catch (Exception ex) {
        Program.UnhandledException(ex);
    }
}

Unhandled Exception:
System.InvalidOperationException: Thread.Name can only be set once.
  at (wrapper managed-to-native) System.Threading.Thread:SetName_internal (System.Threading.InternalThread,string)
  at System.Threading.Thread.set_Name (System.String value) [0x00006] in <8f2c484307284b51944a1a13a14c0266>:0 
  at MyService.OnAcceptTcpClient (System.IAsyncResult ar) [0x00000] in MyService.cs:203 
  at System.Net.Sockets.SocketAsyncResult+<Complete>c__AnonStorey0.<>m__0 (System.Object _) [0x00000] in <bd46d4d4f7964dfa9beea098499ab597>:0 
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00019] in <8f2c484307284b51944a1a13a14c0266>:0 
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00096] in <8f2c484307284b51944a1a13a14c0266>:0 
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0
Comment 1 Christian 2016-11-18 11:29:45 UTC
This behavior is not right. Threads from System.Threading.ThreadPool need a kind of name reset, so that the application can set a new name once it gets the thread.
Comment 2 Zoltan Varga 2016-11-27 03:45:21 UTC
Testcase:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
using System;
using System.Threading;

public class Tests
{
	public static void Main (String[] args) {
		int count = 0;
		Action a = delegate () {
			Console.WriteLine ("A: " + Thread.CurrentThread.Name);
			try {
				Thread.CurrentThread.Name = "x" + count;
				Console.WriteLine ("B: " + Thread.CurrentThread.ManagedThreadId + " " + Thread.CurrentThread.Name);
				count ++;
			} catch (Exception ex) {
				Console.WriteLine ("EX: " + ex);
			}
			try {
				Thread.CurrentThread.Name = "x" + count;
				Console.WriteLine ("B: " + Thread.CurrentThread.ManagedThreadId + " " + Thread.CurrentThread.Name);
				count ++;
			} catch (Exception ex) {
				Console.WriteLine ("EX: " + ex);
			}
			};
		for (int i = 0; i < 10; ++i) {
			a.BeginInvoke (null, null);
			Thread.Sleep (1000);
		}
	}
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
MS prints the following:
A: 
B: 3 x0
EX: System.InvalidOperationException: This property has already been set and cannot be modified.
   at System.Threading.Thread.set_Name(String value)
   at Tests.<>c__DisplayClass1.<Main>b__0()
A: 
B: 4 x1
EX: System.InvalidOperationException: This property has already been set and cannot be modified.
   at System.Threading.Thread.set_Name(String value)
   at Tests.<>c__DisplayClass1.<Main>b__0()
A: 
B: 3 x2
EX: System.InvalidOperationException: This property has already been set and cannot be modified.
   at System.Threading.Thread.set_Name(String value)
   at Tests.<>c__DisplayClass1.<Main>b__0()

That is, it looks the tp threads's name is reset before every async call, and its allowed to be changed once inside the callback, but not twice.
Comment 3 Ludovic Henry 2017-02-08 21:19:10 UTC
This is fixed with https://github.com/mono/mono/pull/4350

Note You need to log in before you can comment on or make changes to this bug.