Bug 1171518 - cleanup maintenance service logging. r=bbondy

This commit is contained in:
Robert Strong 2015-07-14 12:08:45 -07:00
parent 4baf551671
commit 7f05087707
9 changed files with 191 additions and 94 deletions

View File

@ -262,6 +262,62 @@ Section "Uninstall"
Call un.RenameDelete
Push "$INSTDIR\update\updater.exe"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-1.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-2.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-3.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-4.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-5.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-6.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-7.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-8.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-9.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-10.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-install.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-uninstall.log"
Call un.RenameDelete
SetShellVarContext all
Push "$APPDATA\Mozilla\logs\maintenanceservice.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-1.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-2.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-3.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-4.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-5.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-6.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-7.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-8.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-9.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-10.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-install.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-uninstall.log"
Call un.RenameDelete
RMDir /REBOOTOK "$APPDATA\Mozilla\logs"
RMDir /REBOOTOK "$APPDATA\Mozilla"
RMDir /REBOOTOK "$INSTDIR\logs"
RMDir /REBOOTOK "$INSTDIR\update"
RMDir /REBOOTOK "$INSTDIR"

View File

@ -130,18 +130,13 @@ wmain(int argc, WCHAR **argv)
BOOL
GetLogDirectoryPath(WCHAR *path)
{
HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr,
SHGFP_TYPE_CURRENT, path);
if (FAILED(hr)) {
if (!GetModuleFileNameW(nullptr, path, MAX_PATH)) {
return FALSE;
}
if (!PathAppendSafe(path, L"Mozilla")) {
if (!PathRemoveFileSpecW(path)) {
return FALSE;
}
// The directory should already be created from the installer, but
// just to be safe in case someone deletes.
CreateDirectoryW(path, nullptr);
if (!PathAppendSafe(path, L"logs")) {
return FALSE;

View File

@ -390,36 +390,6 @@ PathAppendSafe(LPWSTR base, LPCWSTR extra)
return PathAppendW(base, extra);
}
/**
* Sets update.status to pending so that the next startup will not use
* the service and instead will attempt an update the with a UAC prompt.
*
* @param updateDirPath The path of the update directory
* @return TRUE if successful
*/
BOOL
WriteStatusPending(LPCWSTR updateDirPath)
{
WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' };
wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH);
if (!PathAppendSafe(updateStatusFilePath, L"update.status")) {
return FALSE;
}
const char pending[] = "pending";
HANDLE statusFile = CreateFileW(updateStatusFilePath, GENERIC_WRITE, 0,
nullptr, CREATE_ALWAYS, 0, nullptr);
if (statusFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
DWORD wrote;
BOOL ok = WriteFile(statusFile, pending,
sizeof(pending) - 1, &wrote, nullptr);
CloseHandle(statusFile);
return ok && (wrote == sizeof(pending) - 1);
}
/**
* Sets update.status to a specific failure code
*
@ -429,26 +399,41 @@ WriteStatusPending(LPCWSTR updateDirPath)
BOOL
WriteStatusFailure(LPCWSTR updateDirPath, int errorCode)
{
// The temp file is not removed on failure since there is client code that
// will remove it.
WCHAR tmpUpdateStatusFilePath[MAX_PATH + 1] = { L'\0' };
GetTempFileNameW(updateDirPath, L"svc", 0, tmpUpdateStatusFilePath);
HANDLE tmpStatusFile = CreateFileW(tmpUpdateStatusFilePath, GENERIC_WRITE, 0,
nullptr, CREATE_ALWAYS, 0, nullptr);
if (tmpStatusFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
char failure[32];
sprintf(failure, "failed: %d", errorCode);
DWORD toWrite = strlen(failure);
DWORD wrote;
BOOL ok = WriteFile(tmpStatusFile, failure,
toWrite, &wrote, nullptr);
CloseHandle(tmpStatusFile);
if (!ok || wrote != toWrite) {
return FALSE;
}
WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' };
wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH);
if (!PathAppendSafe(updateStatusFilePath, L"update.status")) {
return FALSE;
}
HANDLE statusFile = CreateFileW(updateStatusFilePath, GENERIC_WRITE, 0,
nullptr, CREATE_ALWAYS, 0, nullptr);
if (statusFile == INVALID_HANDLE_VALUE) {
if (MoveFileExW(tmpUpdateStatusFilePath, updateStatusFilePath,
MOVEFILE_REPLACE_EXISTING) == 0) {
return FALSE;
}
char failure[32];
sprintf(failure, "failed: %d", errorCode);
DWORD toWrite = strlen(failure);
DWORD wrote;
BOOL ok = WriteFile(statusFile, failure,
toWrite, &wrote, nullptr);
CloseHandle(statusFile);
return ok && wrote == toWrite;
return TRUE;
}
#endif

View File

@ -10,7 +10,6 @@ BOOL StartServiceUpdate(LPCWSTR installDir);
BOOL GetUpdateDirectoryPath(LPWSTR path);
DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR *argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
BOOL WriteStatusPending(LPCWSTR updateDirPath);
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
BOOL DoesFallbackKeyExist();

View File

@ -26,17 +26,32 @@ void UpdateLog::Init(NS_tchar* sourcePath,
if (logFP)
return;
this->sourcePath = sourcePath;
NS_tchar logFile[MAXPATHLEN];
NS_tsnprintf(logFile, sizeof(logFile)/sizeof(logFile[0]),
NS_T("%s/%s"), sourcePath, fileName);
#ifdef XP_WIN
GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath);
if (append) {
NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, alternateFileName);
MoveFileExW(mDstFilePath, mTmpFilePath, MOVEFILE_REPLACE_EXISTING);
} else {
NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, fileName);
}
if (alternateFileName && NS_taccess(logFile, F_OK)) {
NS_tsnprintf(logFile, sizeof(logFile)/sizeof(logFile[0]),
logFP = NS_tfopen(mTmpFilePath, append ? NS_T("a") : NS_T("w"));
// Delete this file now so it is possible to tell from the unelevated
// updater process if the elevated updater process has written the log.
DeleteFileW(mDstFilePath);
#else
NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, fileName);
if (alternateFileName && NS_taccess(mDstFilePath, F_OK)) {
NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, alternateFileName);
}
logFP = NS_tfopen(logFile, append ? NS_T("a") : NS_T("w"));
logFP = NS_tfopen(mDstFilePath, append ? NS_T("a") : NS_T("w"));
#endif
}
void UpdateLog::Finish()
@ -46,6 +61,16 @@ void UpdateLog::Finish()
fclose(logFP);
logFP = nullptr;
#ifdef XP_WIN
// When the log file already exists then the elevated updater has already
// written the log file and the temp file for the log should be discarded.
if (!NS_taccess(mDstFilePath, F_OK)) {
DeleteFileW(mTmpFilePath);
} else {
MoveFileW(mTmpFilePath, mDstFilePath);
}
#endif
}
void UpdateLog::Flush()

View File

@ -32,7 +32,8 @@ public:
protected:
UpdateLog();
FILE *logFP;
NS_tchar* sourcePath;
NS_tchar mTmpFilePath[MAXPATHLEN];
NS_tchar mDstFilePath[MAXPATHLEN];
};
#define LOG_WARN(args) UpdateLog::GetPrimaryLog().WarnPrintf args

View File

@ -1272,6 +1272,41 @@ function getTestDirFile(aRelPath, aAllowNonExists) {
return do_get_file(relpath, !!aAllowNonExists);
}
/**
* Helper function for getting the nsIFile for the maintenance service
* directory on Windows.
*
* @return The nsIFile for the maintenance service directory.
*/
function getMaintSvcDir() {
if (!IS_WIN) {
do_throw("Windows only function called by a different platform!");
}
const CSIDL_PROGRAM_FILES = 0x26;
const CSIDL_PROGRAM_FILESX86 = 0x2A;
// This will return an empty string on our Win XP build systems.
let maintSvcDir = getSpecialFolderDir(CSIDL_PROGRAM_FILESX86);
if (maintSvcDir) {
maintSvcDir.append("Mozilla Maintenance Service");
debugDump("using CSIDL_PROGRAM_FILESX86 - maintenance service install " +
"directory path: " + maintSvcDir.path);
}
if (!maintSvcDir || !maintSvcDir.exists()) {
maintSvcDir = getSpecialFolderDir(CSIDL_PROGRAM_FILES);
if (maintSvcDir) {
maintSvcDir.append("Mozilla Maintenance Service");
debugDump("using CSIDL_PROGRAM_FILES - maintenance service install " +
"directory path: " + maintSvcDir.path);
}
}
if (!maintSvcDir) {
do_throw("Unable to find the maintenance service install directory");
}
return maintSvcDir;
}
function getSpecialFolderDir(aCSIDL) {
if (!IS_WIN) {
do_throw("Windows only function called by a different platform!");
@ -1933,26 +1968,7 @@ function copyFileToTestAppDir(aFileRelPath, aInGreDir) {
* a unprivileged location.
*/
function attemptServiceInstall() {
const CSIDL_PROGRAM_FILES = 0x26;
const CSIDL_PROGRAM_FILESX86 = 0x2A;
// This will return an empty string on our Win XP build systems.
let maintSvcDir = getSpecialFolderDir(CSIDL_PROGRAM_FILESX86);
if (maintSvcDir) {
maintSvcDir.append("Mozilla Maintenance Service");
debugDump("using CSIDL_PROGRAM_FILESX86 - maintenance service install " +
"directory path: " + maintSvcDir.path);
}
if (!maintSvcDir || !maintSvcDir.exists()) {
maintSvcDir = getSpecialFolderDir(CSIDL_PROGRAM_FILES);
if (maintSvcDir) {
maintSvcDir.append("Mozilla Maintenance Service");
debugDump("using CSIDL_PROGRAM_FILES - maintenance service install " +
"directory path: " + maintSvcDir.path);
}
}
if (!maintSvcDir) {
do_throw("Unable to find the maintenance service install directory");
}
let maintSvcDir = getMaintSvcDir();
Assert.ok(maintSvcDir.exists(), MSG_SHOULD_EXIST);
let oldMaintSvcBin = maintSvcDir.clone();
oldMaintSvcBin.append(FILE_MAINTENANCE_SERVICE_BIN);
@ -2013,10 +2029,7 @@ function runUpdateUsingService(aInitialStatus, aExpectedStatus, aCheckSvcLog) {
"contain the successful launch string");
}
function readServiceLogFile() {
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("CmAppData", Ci.nsIFile);
file.append("Mozilla");
let file = getMaintSvcDir();
file.append("logs");
file.append("maintenanceservice.log");
return readFile(file);

View File

@ -64,7 +64,12 @@
#define PROGRESS_FINISH_SIZE 5.0f
// Amount of time in ms to wait for the parent process to close
#define PARENT_WAIT 5000
#ifdef DEBUG
// Use a large value for debug builds since the xpcshell tests take a long time.
#define PARENT_WAIT 30000
#else
#define PARENT_WAIT 10000
#endif
#if defined(XP_MACOSX)
// These functions are defined in launchchild_osx.mm
@ -1843,20 +1848,42 @@ LaunchCallbackApp(const NS_tchar *workingDir,
static bool
WriteStatusFile(const char* aStatus)
{
NS_tchar filename[MAXPATHLEN];
NS_tchar filename[MAXPATHLEN] = {NS_T('\0')};
#if defined(XP_WIN)
// The temp file is not removed on failure since there is client code that
// will remove it.
GetTempFileNameW(gPatchDirPath, L"sta", 0, filename);
#else
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
NS_T("%s/update.status"), gPatchDirPath);
#endif
// Make sure that the directory for the update status file exists
if (ensure_parent_dir(filename))
if (ensure_parent_dir(filename)) {
return false;
}
AutoFile file(NS_tfopen(filename, NS_T("wb+")));
if (file == nullptr)
return false;
// This is scoped to make the AutoFile close the file so it is possible to
// move the temp file to the update.status file on Windows.
{
AutoFile file(NS_tfopen(filename, NS_T("wb+")));
if (file == nullptr) {
return false;
}
if (fwrite(aStatus, strlen(aStatus), 1, file) != 1)
if (fwrite(aStatus, strlen(aStatus), 1, file) != 1) {
return false;
}
}
#if defined(XP_WIN)
NS_tchar dstfilename[MAXPATHLEN] = {NS_T('\0')};
NS_tsnprintf(dstfilename, sizeof(dstfilename)/sizeof(dstfilename[0]),
NS_T("%s\\update.status"), gPatchDirPath);
if (MoveFileExW(filename, dstfilename, MOVEFILE_REPLACE_EXISTING) == 0) {
return false;
}
#endif
return true;
}
@ -2777,14 +2804,14 @@ int NS_main(int argc, NS_tchar **argv)
}
}
// If the service can't be used when staging and update, make sure that
// If the service can't be used when staging an update, make sure that
// the UAC prompt is not shown! In this case, just set the status to
// pending and the update will be applied during the next startup.
if (!useService && sStagedUpdate) {
if (updateLockFileHandle != INVALID_HANDLE_VALUE) {
CloseHandle(updateLockFileHandle);
}
WriteStatusPending(gPatchDirPath);
WriteStatusFile("pending");
return 0;
}

View File

@ -101,10 +101,6 @@ BOOL
WinLaunchChild(const wchar_t *exePath, int argc,
char **argv, HANDLE userToken = nullptr,
HANDLE *hProcess = nullptr);
BOOL
WriteStatusPending(LPCWSTR updateDirPath);
BOOL
WriteStatusApplied(LPCWSTR updateDirPath);
#endif
#define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"