job000287 #3

  • //
  • spec/
  • job/
  • job000287
  • View
  • Commits
  • Open Download .zip Download (8 KB)
# The form data below was edited by perforce
# Perforce Workshop Jobs
#
#  Job:           The job name. 'new' generates a sequenced job number.
#
#  Status:        Job status; required field.  There is no enforced or
#                 promoted workflow for transition of jobs from one
#                 status to another, just a set of job status values
#                 for users to apply as they see fit.  Possible values:
#
#                 open - Issue is available to be worked on.
#
#                 inprogress - Active development is in progress.
#
#                 blocked - Issue cannot be implemented for some reason.
#
#                 fixed - Fixed, optional status to use before closed.
#                 
#                 closed - Issue has been dealt with definitively.
#
#                 punted - Decision made not to address the issue,
#                    possibly not ever.
#
#                 suspended - Decision made not to address the issue
#                    in the immediate future, but noting that it may
#                    have some merit and may be revisited later.
#
#                 duplicate - Duplicate of another issue that.
#
#                 obsolete - The need behind the request has become
#                    overcome by events.
#
#  Project:       The project this job is for. Required.
#
#  Severity:      [A/B/C] (A is highest)  Required.
#
#  ReportedBy     The user who created the job. Can be changed.
#
#  ReportedDate:  The date the job was created.  Automatic.
#
#  ModifiedBy:    The user who last modified this job. Automatic.
#
#  ModifiedDate:  The date this job was last modified. Automatic.
#
#  OwnedBy:       The owner, responsible for doing the job. Optional.
#
#  Description:   Description of the job.  Required.
#
#  DevNotes:      Developer's comments.  Optional.  Can be used to
#                 explain a status, e.g. for blocked, punted,
#                 obsolete or duplicate jobs.  May also provide
#                 additional information such as the earliest release
#                 in which a bug is known to exist.
#
# Component:      Projects may use this optional field to indicate
#                 which component of the project a givenjob is associated
#                 with.
#
#                 For the SDP, the list of components is defined in:
#                 //guest/perforce_software/sdp/tools/components.txt
#
#  Type:          Type of job [Bug/Feature].  Required.
#
#  Release:       Release in which job is intended to be fixed.

Job:	job000287

Status:	open

Project:	perforce-software-p4api-net

Severity:	B

ReportedBy:	norman_morse

ReportedDate:	2015/05/27 11:14:29

ModifiedBy:	perforce

ModifiedDate:	2019/02/19 10:51:16

OwnedBy:	norman_morse

Description:
	Cancelled commands cause next command issued to fail.  Reported in internal case 00152113
	
	I can reproduce this with the following code:
	
	The error returned in the second "try" is: 
	      Perforce.P4.P4Exception RpcTransport: partial message read, TCP recieve interrupted by client.
	
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;
	using System.Threading;
	using Perforce.P4;
	
	namespace DotNetCancel
	{
	    class Program
	    {
	        static void Main(string[] args)
	        {
	            P4APICancelBug();
	        }
	
	        private static P4Server m_server;
	
	        private static bool s_cancelCommand = false;
	
	        private static string P4user = "norman";
	        private static string P4port = "localhost:2666";
	        private static string P4client = "nomo_canceltest";
	        private static string P4clientRoot = "c:\\projects\\p4api.netTest\\p4_client";
	
	        public class MyKeepAlive : IKeepAlive
	        {
	
	            public void CommandCompleted(uint cmdId)
	            {
	
	            }
	
	            public bool StartQueryCancel(P4Server server, uint cmdId, Thread cmdRunThread, string cmdLine)
	            {
	                System.Threading.Thread.Sleep(1);
	                s_cancelCommand = true;
	                return true;
	            }
	        }
	
	        //[TestMethod]
	
	        static public void P4APICancelBug()
	        {
	            Server server = new Server(new ServerAddress(P4port));
	
	            Repository repository = new Repository(server);
	
	            Options opts = new Options();
	
	            repository.Connection.UserName = P4user;
	
	            repository.Connection.Client = new Client() { Name = P4client };
	
	            repository.Connection.Connect(null);
	
	            //Assert.IsTrue(repository.Connection.Status == ConnectionStatus.Connected);
	
	            List<string> files = new List<string>();
	
	            int numFiles = 1000;
	
	            for (int i = 0; i < numFiles; i++)
	            {
	                string filename = System.IO.Path.Combine(P4clientRoot, "file" + i + ".txt");
	
	                System.IO.File.WriteAllText(filename, i.ToString());
	
	                files.Add(filename);
	            }
	
	            using (P4Command cmd = new P4Command(repository.Connection, "add", true, files.ToArray()))
	            {
	                P4CommandResult result = cmd.Run();
	                //Assert.IsTrue(result.TaggedOutput.Count == numFiles);
	            }
	
	            for (int i = 0; i < 100; ++i)
	            {
	                try
	                {
	                    repository.Connection.TaggedOutputReceived += P4APICancelBug_TaggedOutputReceived;
	
	                    s_cancelCommand = false;
	
	                    repository.Connection.KeepAlive = new MyKeepAlive();
	
	                    using (P4Command cmd = new P4Command(repository.Connection, "fstat", true, "//" + P4client + "/..."))
	                    {
	                        m_server = cmd.pServer;
	
	                        // Saw this in P4 unit tests, would be nice if this was available on Connection, like KeepAlive is :)
	                        m_server.KeepAliveDelay = TimeSpan.FromSeconds(0.0);
	
	                        try
	                        {
	                            P4CommandResult result = cmd.Run();
	                        }
	
	                        catch (Exception)
	                        {
	
	                        }
	                    }
	                }
	
	                finally
	                {
	                    repository.Connection.KeepAlive = null;
	                    repository.Connection.TaggedOutputReceived -= P4APICancelBug_TaggedOutputReceived;
	                }
	
	                s_cancelCommand = false;
	
	                try
	                {
	                    // start a new command - why does this one get errors? To get past the errors in our code, I had to sleep for a second :-(
	                    repository.Connection.TaggedOutputReceived += P4APICancelBug_TaggedOutputReceived;
	
	                    using (P4Command cmd = new P4Command(repository.Connection, "fstat", true, "//" + P4client + "/..."))
	                    {
	                        try
	                        {
	                            P4CommandResult result = cmd.Run();
	                        }
	
	                        catch (Exception ex)
	                        {
	                            Console.WriteLine(ex.Message);
	                        }
	                    }
	                }
	
	                finally
	                {
	                    repository.Connection.TaggedOutputReceived -= P4APICancelBug_TaggedOutputReceived;
	                }
	            }
	        }
	
	
	        private static void P4APICancelBug_TaggedOutputReceived(uint cmdId, int ObjId, TaggedObject Obj)
	        {
	            if (s_cancelCommand)
	            {
	                m_server.CancelCommand(cmdId);
	            }
	        }
	
	    }
	}

DevNotes:

Type:	Bug
# Change User Description Committed
#3 default
#2 default
#1 default