# 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