S h o r t S t o r i e s

// Tales from software development

What account should you run Perforce server under ?

leave a comment »

Excluding files

I’m using Perforce as SCM for my private source code. I’ve used Microsoft’s own internally licenced and developed version of Perforce, Source Depot, on the project that I’ve been working on for the past 21 months. When using Perforce, I’ve been missing a feature that Source Depot implements but Perforce doesn’t – being able to reject certain file types from being submitted to the depot.

Triggers

Perforce implements triggers that run macros, scripts, or programs when certain events occur. As there is a ‘change-submit’ trigger that fires when a submit command is issued to check in code, this seemed to be the obvious mechanism to implement a solution to block a check-in if it includes a prohibitied file.

All I wanted to do was exclude *.suo and *.csproj.user files (user preference files for Visual Studio solutions and C# projects). It would have been easy enough to write a VBScript or JScript script to do this.  Actually, even an MS-DOS batch file could have done the job. However, I decided to write the trigger in C# 2.0 to give me a chance to try out the .NET interface for Perforce being developed at http://p4dotnet.sourceforge.net/.

P4SubmitFilter

P4SubmitFilter took a couple of hours to write and uses values in its config file to specify the settings to be used when connecting to the Perforce server and a list of semicolon delimited filemasks for the files that are to be blocked from check-in, e.g. “*.suo;*.csproj”.

The program is passed the changelist number and then issues a Perforce “describe -s” command to get a list of the files that the changelist contains. The list of files is checked against the list of filemasks for blocked files and exits with a non-zero return code and a message to SYSOUT if a match is made.

I tested the program in a command window against previously submitted changelists and everything seemed to work as expected. The program exited quietly with rc=0 for changelists that did not contain any files that matched the exclusion filemask list but exited with rc=1 and a message when a match was made.

Next, I started a virtual machine running Windows XP that had a copy of Perforce installed. I configured the trigger using the Perforce “triggers” command. The following line was added to the trigger specifications file:

P4SubmitFilter    change-submit    //depot/...    "P4SubmitFilter %changelist%"

The first item is an arbitrary name for the trigger and the second is the trigger type. The third item is the depot file specification for files that the trigger is to be applied to. The specification used indicates that the trigger is to be applied to all files in the depot. The last item is the command to be executed with ‘%changelist%’ being a Perforce token that is replaced with the changelist number when the command is executed.

Testing

I created a changelist that contained a .suo file and attempted to submit it. The trigger worked as expected – the submit command was rejected and a message was displayed indicating that *.suo files were blocked. I removed the .suo file from the changelist and ran the submit command again. This time the changelist was successfully submitted.

Thinking that I now had a production ready program, I recompiled the program in Release configuration and copied it to the server running my Perforce depot. I ran the ‘triggers’ command again and configured the new trigger as before. I then ran a test “submit” command against a changelist containing a .suo file. After a bit of a wait an error message was displayed indicating that the P4SubmitFilter command had failed and that no output was available. Strange… What was wrong ?

I ran the P4SubmitFilter program in a command window on the server and it executed as expected. I checked the trigger specification file and confirmed that there weren’t any typos. I re-tried the submit command and it failed as before. At this point I thought that the problem was somewhere in my code so I compiled a new version that included debug output.

I copied the new version to the server and started SysInternals’ DbgView on the server. I ran the submit command again but instead of seeing at least some debug output, the DbgView output window remained blank. So, the problem appeared to be that P4SubmitFilter wasn’t being successfully invoked by Perforce.

I checked the event logs but there was no indication of a problem with Perforce or P4SubmitFilter. I began to suspect the the issue was security and wondered if the Perforce server was running under different accounts on my server and my XP virtual machine. I checked but found that both machines were configured for Perforce to run under the Local System account.

What other differences were there between the two machines ? Well, the most obvious one was that my server is running Windows Server 2008 and the virtual machine is running Windows XP. Was that the problem ? Logically, it seemed unlikely but my gut feeling was that it was quite possible that Windows Server’s tighter security might be the cause of the problem.

Local System account

The quickest way to test this was to run the Perforce service under a local Administrator account rather than the Local System account. I made the change and re-started the Perforce service. I attempted to submit the changelist again… Success! This time the submit command was rejected with a message indicating that the .suo file could not be submitted.

This still seemed a little odd but a quick search on the internet showed that Microsoft has made some changes to at least one of the API functions used to start a process with the result that a process running under the Local System account can no longer start another process. The documentation for the CreateProcessWithLogonW function now includes this caveat:

Windows XP SP2 and Windows Server 2003:  You cannot call CreateProcessWithLogonW from a process that is running under the LocalSystem account, because the function uses the logon SID in the caller token, and the token for the LocalSystem account does not contain this SID. As an alternative, use the CreateProcessAsUser and LogonUser functions.

So, if you’re running Perforce under Windows Server 2003 or Windows Server 2008 then you may need to configure the service to run under a different account from the default Local System account.

Advertisements

Written by Sea Monkey

September 21, 2008 at 9:00 pm

Posted in Development

Tagged with , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: