24e1d6dbd2
Change-Id: Ie41ca6c56bf44b04bd2d65b6cb64594d66295f24 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158951 Tested-by: Jenkins Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
116 lines
4.6 KiB
C++
116 lines
4.6 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
// Helper to reduce parallelism, specifically for msi installset packaging
|
|
//
|
|
// Ideally it would hook into make's jobserver, but it is too easy to deadlock the build at the
|
|
// packaging stage (all jobs are started at once, consuming all available slots as part of general
|
|
// parallelism, and then each job waiting for an additional job token but since all jobs are in
|
|
// waiting stage: you have a deadlock).
|
|
// That in turn is an advantage for a simple approach with separate lock and release commands, since
|
|
// everything is started at once, and all jobs that will be queued are all jobs that use the helper,
|
|
// there will be jobs in waiting state and keeping the semaphore active as long as it matters.
|
|
|
|
#include <iostream>
|
|
#include <windows.h>
|
|
|
|
using namespace std;
|
|
|
|
int grab(HANDLE& semaphore_handle)
|
|
{
|
|
DWORD waitresult = WaitForSingleObject(semaphore_handle, INFINITE);
|
|
|
|
switch (waitresult)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
return 0;
|
|
case WAIT_TIMEOUT:
|
|
fprintf(stderr, "grabbing a slot failed with timeout despite waiting for INFINITE?\n");
|
|
break;
|
|
case WAIT_FAILED:
|
|
fprintf(stderr, "grabbing a slot failed with error: %d\n", GetLastError());
|
|
break;
|
|
default:
|
|
fprintf(stderr, "grabbing a slot failed with status %d - error %d", waitresult,
|
|
GetLastError());
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int release(HANDLE& semaphore_handle)
|
|
{
|
|
if (ReleaseSemaphore(semaphore_handle, 1, NULL))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "something went wrong trying to release a slot: %d\n", GetLastError());
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int wmain(int argc, wchar_t* argv[])
|
|
{
|
|
if (argc != 2)
|
|
{
|
|
fprintf(stderr, "Invalid number of arguments!\n");
|
|
fprintf(stderr, "call with 'grab' or 'release'\n");
|
|
exit(1);
|
|
}
|
|
// since the reason for limiting the parallelism is the instability with cscript/WiLangId.vbs
|
|
// calls and high parallelism, not having that unique/potentially sharing the limit semaphore
|
|
// with another build is not a problem but considered a feature...
|
|
LPCWSTR semaphorename = L"lo_installset_limiter";
|
|
HANDLE semaphore_handle
|
|
= OpenSemaphoreW(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, false, semaphorename);
|
|
if (semaphore_handle == NULL)
|
|
{
|
|
fprintf(stdout, "no existing semaphore, creating new one\n");
|
|
// Need to have a buffer slot, since the helper isn't persistent.
|
|
// When it is called to release a slot it might be that all holders of the semaphore
|
|
// are gone already and thus the semaphore also gets closed and is no longer present on the
|
|
// system. So when it creates a new one to use, and then releases one it would hit the max
|
|
// limit otherwise. This only happens when nothing else is waiting for a slot anymore,
|
|
// i.e. when there are already fewer jobs than imposed by the limiter.
|
|
// A limit of four (main installer and 3 controlled by this limiter) was chosen because that
|
|
// won't affect overall build time (creating the main installer with multiple languages
|
|
// takes much longer than all the helppackages and the single sdk package combined, even
|
|
// when those are limited to three jobs), and seems to be low enough to avoid the random
|
|
// cscript/WiLangId.vbs failures.
|
|
semaphore_handle = CreateSemaphoreW(NULL, 3, 4, semaphorename);
|
|
// keep this process alive for other jobs to grab the semaphore, otherwise it is gone too
|
|
// quickly and everything creates their own semaphore that immediately has enough slots,
|
|
// completely bypassing the point of having a limiter...
|
|
Sleep(500);
|
|
}
|
|
if (semaphore_handle == NULL)
|
|
{
|
|
fprintf(stderr, "Error creating/opening the semaphore - bailing out (%d)\n",
|
|
GetLastError());
|
|
exit(1);
|
|
}
|
|
|
|
if (wcscmp(argv[1], L"grab") == 0)
|
|
{
|
|
exit(grab(semaphore_handle));
|
|
}
|
|
else if (wcscmp(argv[1], L"release") == 0)
|
|
{
|
|
exit(release(semaphore_handle));
|
|
}
|
|
else
|
|
{
|
|
fwprintf(stderr, L"invalid action '%s'\nSupported actions are 'grab' or 'release'\n",
|
|
argv[1]);
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|