Reputation: 279
Im stuck. I have joined the project that uses Named Pipes, and have lets say "not ideal architecture". And seems like I accidentally received a deadlock:(
The logic is following. There is Named Pipe. Client and Server model. On server part there is a loop, that always pings named pipe and process what client sends, sometimes sending back responses.
On Client side of my pipe, I have following method, from other developer, that is being used to send request to server and receive and return the response.
private object locker = new Object();
private string ListenOnce(string msg)
{
Debug.WriteLine("Will listen for message " + msg);
string msgFrom = "";
if (run) {
string toReturn = "";
lock (locker) {
sw.WriteLine(msg); //Writing command to the pipes
stream.WaitForPipeDrain(); //Waiting for another process to read the command
msgFrom = sr.ReadLine(); //Reading
toReturn = sr.ReadLine ();
if (toReturn.Contains('¥'))
{
string[] split = toReturn.Split('¥');
if (split.Length > 1)
{
var roomNames = this.connection.application.GameCache.GetRoomNames();
for (int i = 1; i < split.Length; i++)
{
string[] split2 = split[i].Split('¶');
if (split2.Length > 1)
{
string accountName = split2[0];
int offenderActorID = int.Parse(split2[1]);
string offenderRoomName = split2[2];
foreach (var roomName in roomNames)
{
Room room;
if (this.connection.application.GameCache.TryGetRoomWithoutReference(roomName, out room))
{
Game game = room as Game;
if (game != null && game.Name == offenderRoomName)
{
GameClientPeer peer = (GameClientPeer)game.ActorsManager.ActorsGetActorByNumber(offenderActorID).Peer;
if (peer != null)
{
peer.KickPlayer();
}
}
}
}
}
}
}
}
}
if (toReturn.Contains('¥'))
{
return toReturn.Split('¥')[0];
}
else
{
return toReturn;
}
}
return "";
}
The problem is - in some cases I cant receive response from pipe right when requested, and need to start what I called here "poller". This is a task, that loops 5 times, and during those 5 times "polls" the pipe through this ListenOnce method.
private void PollTargets()
{
timer.Dispose();
Debug.WriteLine("Going to start polling");
Task.Factory.StartNew(() => {
int runCount = 0;
while (true)
{
runCount++;
PipeOperation request = new PipeOperation(Consts.Pipes.RequestTargets, uniqueID);
string responseStr = unityConnection.client.SendMessage(JsonConvert.SerializeObject(request));
Debug.WriteLine("Task is running, response is " + responseStr);
if (!string.IsNullOrEmpty(responseStr))
{
try
{
PipeOperation pipeResponse = JsonConvert.DeserializeObject<PipeOperation>(responseStr);
if (!string.IsNullOrEmpty(pipeResponse.Payload))
{
GrenadeExplosionData explosionData = JsonConvert.DeserializeObject<GrenadeExplosionData>(pipeResponse.Payload);
if (explosionData != null)
{
//probably need to invoke that in main thread
DealDamage(explosionData);
//isRunning = false;
Debug.WriteLine("Received nice response, will damage targets");
break;
}
}
}
catch (Exception exc)
{
Debug.WriteLine("Something went wrong while polling...");
Debug.WriteLine(exc.Message);
break;
}
}
if (runCount > 5)
{
Debug.WriteLine("run count exceed " + runCount.ToString());
break;
}
}
RemoveGrenadeFromUnityConnection();
});
}
I am starting poller when the Grenade explodes, from timer like that:
timer = new System.Threading.Timer((obj) =>
{
PollTargets();
},
null, 4000, System.Threading.Timeout.Infinite);
And thats it. After people play 2-3 hrs. Seems like I receive a deadlock. It should be taken into account that there might be many grenades on server who starts that poller, so probably it just goes mad at some point over there. Pls help, Im stuck with that. Who has ideas? We should keep in mind, that
sw.WriteLine(msg); //Writing command to the pipes
stream.WaitForPipeDrain();
msgFrom = sr.ReadLine(); //Reading
toReturn = sr.ReadLine ();
should be used only by one thread at a time, as stream might be read only from one source.
There are several calls to ListenOnce from the code, but not a lot. One is being fired every 4 minutes.The rest ones are not constant, but conditional.
Hope somebody would see where is a mistake here...
Upvotes: 1
Views: 862
Reputation: 279
Found what locks everything...However, it does not help a lot:) Its stream.WaitForPipeDrain();
it tries to read another end of pipe, but because of there is no timeouts in message mode, it just hangs for ever..
Upvotes: 1