2016-11-12 15:38:13 -06:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* 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/.
|
|
|
|
*/
|
|
|
|
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <config.h>
|
2016-11-12 15:38:13 -06:00
|
|
|
|
2017-03-08 10:38:22 -06:00
|
|
|
#include "FileUtil.hpp"
|
|
|
|
|
wsd: faster jail setup via bind-mount
loolmount now works and supports mounting and
unmounting, plus numerous improvements,
refactoring, logging, etc.. When enabled,
binding improves the jail setup time by anywhere
from 2x to orders of magnitude (in docker, f.e.).
A new config entry mount_jail_tree controls
whether mounting is used or the old method of
linking/copying of jail contents. It is set to
true by default and falls back to linking/copying.
A test mount is done when the setting is enabled,
and if mounting fails, it's disabled to avoid noise.
Temporarily disabled for unit-tests until we can
cleanup lingering mounts after Jenkins aborts our
build job. In a future patch we will have mount/jail
cleanup as part of make.
The network/system files in /etc that need frequent
refreshing are now updated in systemplate to make
their most recent version available in the jails.
These files can change during the course of loolwsd
lifetime, and are unlikely to be updated in
systemplate after installation at all. We link to
them in the systemplate/etc directory, and if that
fails, we copy them before forking each kit
instance to have the latest.
This reworks the approach used to bind-mount the
jails and the templates such that the total is
now down to only three mounts: systemplate, lo, tmp.
As now systemplate and lotemplate are shared, they
must be mounted as readonly, this means that user/
must now be moved into tmp/user/ which is writable.
The mount-points must be recursive, because we mount
lo/ within the mount-point of systemplate (which is
the root of the jail). But because we (re)bind
recursively, and because both systemplate and
lotemplate are mounted for each jails, we need to
make them unbindable, so they wouldn't multiply the
mount-points for each jails (an explosive growth!)
Contrarywise, we don't want the mount-points to
be shared, because we don't expect to add/remove
mounts after a jail is created.
The random temp directory is now created and set
correctly, plus many logging and other improvements.
Change-Id: Iae3fda5e876cf47d2cae6669a87b5b826a8748df
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92829
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-04-09 08:02:58 -05:00
|
|
|
#include <dirent.h>
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
#include <exception>
|
2017-01-29 23:04:10 -06:00
|
|
|
#include <ftw.h>
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
#include <stdexcept>
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
#include <sys/time.h>
|
2018-08-29 10:23:22 -05:00
|
|
|
#ifdef __linux
|
2016-11-12 15:38:13 -06:00
|
|
|
#include <sys/vfs.h>
|
2018-09-05 07:11:05 -05:00
|
|
|
#elif defined IOS
|
2018-08-29 10:23:22 -05:00
|
|
|
#import <Foundation/Foundation.h>
|
2020-11-08 09:35:56 -06:00
|
|
|
#elif defined __FreeBSD__
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/mount.h>
|
2018-08-29 10:23:22 -05:00
|
|
|
#endif
|
2016-11-12 15:38:13 -06:00
|
|
|
|
|
|
|
#include <chrono>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <fstream>
|
|
|
|
#include <mutex>
|
|
|
|
#include <string>
|
|
|
|
|
2019-11-08 06:42:59 -06:00
|
|
|
#if HAVE_STD_FILESYSTEM
|
|
|
|
# if HAVE_STD_FILESYSTEM_EXPERIMENTAL
|
|
|
|
# include <experimental/filesystem>
|
|
|
|
namespace filesystem = ::std::experimental::filesystem;
|
|
|
|
# else
|
|
|
|
# include <filesystem>
|
|
|
|
namespace filesystem = ::std::filesystem;
|
|
|
|
# endif
|
|
|
|
#else
|
|
|
|
# include <Poco/TemporaryFile.h>
|
|
|
|
#endif
|
2016-11-12 15:38:13 -06:00
|
|
|
|
wsd: faster jail setup via bind-mount
loolmount now works and supports mounting and
unmounting, plus numerous improvements,
refactoring, logging, etc.. When enabled,
binding improves the jail setup time by anywhere
from 2x to orders of magnitude (in docker, f.e.).
A new config entry mount_jail_tree controls
whether mounting is used or the old method of
linking/copying of jail contents. It is set to
true by default and falls back to linking/copying.
A test mount is done when the setting is enabled,
and if mounting fails, it's disabled to avoid noise.
Temporarily disabled for unit-tests until we can
cleanup lingering mounts after Jenkins aborts our
build job. In a future patch we will have mount/jail
cleanup as part of make.
The network/system files in /etc that need frequent
refreshing are now updated in systemplate to make
their most recent version available in the jails.
These files can change during the course of loolwsd
lifetime, and are unlikely to be updated in
systemplate after installation at all. We link to
them in the systemplate/etc directory, and if that
fails, we copy them before forking each kit
instance to have the latest.
This reworks the approach used to bind-mount the
jails and the templates such that the total is
now down to only three mounts: systemplate, lo, tmp.
As now systemplate and lotemplate are shared, they
must be mounted as readonly, this means that user/
must now be moved into tmp/user/ which is writable.
The mount-points must be recursive, because we mount
lo/ within the mount-point of systemplate (which is
the root of the jail). But because we (re)bind
recursively, and because both systemplate and
lotemplate are mounted for each jails, we need to
make them unbindable, so they wouldn't multiply the
mount-points for each jails (an explosive growth!)
Contrarywise, we don't want the mount-points to
be shared, because we don't expect to add/remove
mounts after a jail is created.
The random temp directory is now created and set
correctly, plus many logging and other improvements.
Change-Id: Iae3fda5e876cf47d2cae6669a87b5b826a8748df
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92829
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-04-09 08:02:58 -05:00
|
|
|
#include <Poco/File.h>
|
|
|
|
#include <Poco/Path.h>
|
|
|
|
|
2016-11-12 15:38:13 -06:00
|
|
|
#include "Log.hpp"
|
|
|
|
#include "Util.hpp"
|
2017-03-31 11:18:41 -05:00
|
|
|
#include "Unit.hpp"
|
2016-11-12 15:38:13 -06:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2019-11-08 06:42:59 -06:00
|
|
|
#if HAVE_STD_FILESYSTEM
|
|
|
|
/// Class to delete files when the process ends.
|
|
|
|
class FileDeleter
|
|
|
|
{
|
|
|
|
std::vector<std::string> _filesToDelete;
|
test: thread-safe common shared test data
This protects against memory corruptions,
and a cascade of issues, such as the following:
Attaching to process 56245
[New LWP 56246]
[New LWP 56252]
[New LWP 56253]
[New LWP 56254]
[New LWP 56362]
[New LWP 56364]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fda228f7d2d in __GI___pthread_timedjoin_ex (threadid=140574279595776, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
89 pthread_join_common.c: No such file or directory.
Thread 7 (Thread 0x7fda197fa700 (LWP 56364)):
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007fda228f9023 in __GI___pthread_mutex_lock (mutex=0x55e9937567e0 <SigHandlerTrap>) at ../nptl/pthread_mutex_lock.c:78
#2 0x000055e9934cd4fe in __gthread_mutex_lock (__mutex=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748
#3 std::mutex::lock (this=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/c++/7/bits/std_mutex.h:103
#4 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:267
#5 std::unique_lock<std::mutex>::unique_lock (__m=..., this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:197
#6 SigUtil::handleFatalSignal (signal=11) at common/SigUtil.cpp:214
#7 <signal handler called>
#8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_capacity (this=<optimized out>, __capacity=0) at /usr/include/c++/7/bits/basic_string.h:200
#9 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=..., this=<optimized out>) at /usr/include/c++/7/bits/basic_string.h:542
#10 std::_Construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (
__p=<optimized out>) at /usr/include/c++/7/bits/stl_construct.h:75
#11 std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=0x7fd9f40017b0, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:83
#12 std::uninitialized_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=<optimized out>, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:134
#13 std::__uninitialized_copy_a<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (__result=<optimized out>, __last=..., __first=...)
at /usr/include/c++/7/bits/stl_uninitialized.h:289
#14 std::__uninitialized_move_if_noexcept_a<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > (__alloc=..., __result=<optimized out>, __last=0x55e995662850,
__first=<optimized out>) at /usr/include/c++/7/bits/stl_uninitialized.h:312
#15 std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_realloc_insert<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (
this=this@entry=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>,
__position=<error: Cannot access memory at address 0x3735003238323a>, __args#0="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp") at /usr/include/c++/7/bits/vector.tcc:424
#16 0x000055e9934aa829 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (__x="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at /usr/include/c++/7/bits/stl_vector.h:948
#17 (anonymous namespace)::FileDeleter::registerForDeletion (file="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at common/FileUtil.cpp:69
#18 FileUtil::getTempFilePath (srcDir=..., srcFilename=..., dstFilenamePrefix=...) at common/FileUtil.cpp:97
#19 0x00007fda216b51c9 in helpers::getDocumentPathAndURL (docFilename="viewcursor.odp", documentPath="", documentURL="", prefix="loadTorture_viewcursor.odp_") at ./helpers.hpp:151
#20 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_viewcursor.odp ", docName="viewcursor.odp", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#21 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994dbc758) at UnitLoadTorture.cpp:186
#22 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#23 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#24 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994dbc758) at /usr/include/c++/7/thread:234
#25 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994dbc758) at /usr/include/c++/7/thread:243
#26 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994dbc750) at /usr/include/c++/7/thread:186
#27 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#28 0x00007fda228f66db in start_thread (arg=0x7fda197fa700) at pthread_create.c:463
#29 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7fd9fffff700 (LWP 56362)):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007fda225952db in __GI___libc_malloc (bytes=bytes@entry=3635) at malloc.c:3063
#2 0x00007fda2262f364 in __backtrace_symbols (array=array@entry=0x7fd9ffffc540, size=size@entry=26) at backtracesyms.c:69
#3 0x000055e9934cc439 in SigUtil::dumpBacktrace () at common/SigUtil.cpp:253
#4 0x000055e9934cd5ae in SigUtil::handleFatalSignal (signal=6) at common/SigUtil.cpp:236
#5 <signal handler called>
#6 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#7 0x00007fda2253e801 in __GI_abort () at abort.c:79
#8 0x00007fda22587897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fda226b4b9a "%s
") at ../sysdeps/posix/libc_fatal.c:181
#9 0x00007fda2258e90a in malloc_printerr (str=str@entry=0x7fda226b2e0e "malloc(): memory corruption") at malloc.c:5350
#10 0x00007fda22592994 in _int_malloc (av=av@entry=0x7fda00000020, bytes=bytes@entry=32) at malloc.c:3738
#11 0x00007fda225952ed in __GI___libc_malloc (bytes=32) at malloc.c:3065
#12 0x00007fda22db9258 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007fda244adaae in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate (this=0x7fd9ffffe740, __n=1)
at /usr/include/c++/5/ext/new_allocator.h:104
#14 0x00007fda244ad300 in __gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate (__a=..., __n=1)
at /usr/include/c++/5/ext/alloc_traits.h:182
#15 0x00007fda244ac858 in std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate (this=0x7fd9ffffe740, __n=1) at /usr/include/c++/5/bits/stl_vector.h:170
#16 0x00007fda244ab7c7 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux (this=0x7fd9ffffe740, __position=non-dereferenceable iterator for std::vector, __x="home") at /usr/include/c++/5/bits/vector.tcc:353
#17 0x00007fda244aada2 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x7fd9ffffe740, __x="home") at /usr/include/c++/5/bits/stl_vector.h:925
#18 0x00007fda2350ddcb in Poco::Path::pushDirectory (this=0x7fd9ffffe6c0, dir="home") at src/Path.cpp:471
#19 0x00007fda2350ea27 in Poco::Path::parseUnix (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:671
#20 0x00007fda2350cd6b in Poco::Path::assign (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:182
#21 0x00007fda2350c1be in Poco::Path::Path (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:54
#22 0x00007fda2350d33a in Poco::Path::makeAbsolute (this=0x7fd9ffffe8f0) at src/Path.cpp:318
#23 0x00007fda216b52ca in helpers::getDocumentPathAndURL (docFilename="setclientpart.ods", documentPath="/tmp/loadTorture_setclientpart.ods_ae70d2e_setclientpart.ods", documentURL="",
prefix="loadTorture_setclientpart.ods_") at ./helpers.hpp:153
#24 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_setclientpart.ods ", docName="setclientpart.ods", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#25 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994cffe18) at UnitLoadTorture.cpp:186
#26 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#27 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#28 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994cffe18) at /usr/include/c++/7/thread:234
#29 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994cffe18) at /usr/include/c++/7/thread:243
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994cffe10) at /usr/include/c++/7/thread:186
#31 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#32 0x00007fda228f66db in start_thread (arg=0x7fd9fffff700) at pthread_create.c:463
#33 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Change-Id: Ib60954e49e692082e686cb3fdc5fc9d5cfbc83c9
Reviewed-on: https://gerrit.libreoffice.org/83047
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2019-11-17 19:32:54 -06:00
|
|
|
std::mutex _lock;
|
2019-11-08 06:42:59 -06:00
|
|
|
public:
|
|
|
|
FileDeleter() {}
|
|
|
|
~FileDeleter()
|
|
|
|
{
|
test: thread-safe common shared test data
This protects against memory corruptions,
and a cascade of issues, such as the following:
Attaching to process 56245
[New LWP 56246]
[New LWP 56252]
[New LWP 56253]
[New LWP 56254]
[New LWP 56362]
[New LWP 56364]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fda228f7d2d in __GI___pthread_timedjoin_ex (threadid=140574279595776, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
89 pthread_join_common.c: No such file or directory.
Thread 7 (Thread 0x7fda197fa700 (LWP 56364)):
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007fda228f9023 in __GI___pthread_mutex_lock (mutex=0x55e9937567e0 <SigHandlerTrap>) at ../nptl/pthread_mutex_lock.c:78
#2 0x000055e9934cd4fe in __gthread_mutex_lock (__mutex=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748
#3 std::mutex::lock (this=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/c++/7/bits/std_mutex.h:103
#4 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:267
#5 std::unique_lock<std::mutex>::unique_lock (__m=..., this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:197
#6 SigUtil::handleFatalSignal (signal=11) at common/SigUtil.cpp:214
#7 <signal handler called>
#8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_capacity (this=<optimized out>, __capacity=0) at /usr/include/c++/7/bits/basic_string.h:200
#9 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=..., this=<optimized out>) at /usr/include/c++/7/bits/basic_string.h:542
#10 std::_Construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (
__p=<optimized out>) at /usr/include/c++/7/bits/stl_construct.h:75
#11 std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=0x7fd9f40017b0, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:83
#12 std::uninitialized_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=<optimized out>, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:134
#13 std::__uninitialized_copy_a<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (__result=<optimized out>, __last=..., __first=...)
at /usr/include/c++/7/bits/stl_uninitialized.h:289
#14 std::__uninitialized_move_if_noexcept_a<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > (__alloc=..., __result=<optimized out>, __last=0x55e995662850,
__first=<optimized out>) at /usr/include/c++/7/bits/stl_uninitialized.h:312
#15 std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_realloc_insert<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (
this=this@entry=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>,
__position=<error: Cannot access memory at address 0x3735003238323a>, __args#0="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp") at /usr/include/c++/7/bits/vector.tcc:424
#16 0x000055e9934aa829 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (__x="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at /usr/include/c++/7/bits/stl_vector.h:948
#17 (anonymous namespace)::FileDeleter::registerForDeletion (file="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at common/FileUtil.cpp:69
#18 FileUtil::getTempFilePath (srcDir=..., srcFilename=..., dstFilenamePrefix=...) at common/FileUtil.cpp:97
#19 0x00007fda216b51c9 in helpers::getDocumentPathAndURL (docFilename="viewcursor.odp", documentPath="", documentURL="", prefix="loadTorture_viewcursor.odp_") at ./helpers.hpp:151
#20 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_viewcursor.odp ", docName="viewcursor.odp", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#21 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994dbc758) at UnitLoadTorture.cpp:186
#22 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#23 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#24 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994dbc758) at /usr/include/c++/7/thread:234
#25 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994dbc758) at /usr/include/c++/7/thread:243
#26 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994dbc750) at /usr/include/c++/7/thread:186
#27 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#28 0x00007fda228f66db in start_thread (arg=0x7fda197fa700) at pthread_create.c:463
#29 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7fd9fffff700 (LWP 56362)):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007fda225952db in __GI___libc_malloc (bytes=bytes@entry=3635) at malloc.c:3063
#2 0x00007fda2262f364 in __backtrace_symbols (array=array@entry=0x7fd9ffffc540, size=size@entry=26) at backtracesyms.c:69
#3 0x000055e9934cc439 in SigUtil::dumpBacktrace () at common/SigUtil.cpp:253
#4 0x000055e9934cd5ae in SigUtil::handleFatalSignal (signal=6) at common/SigUtil.cpp:236
#5 <signal handler called>
#6 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#7 0x00007fda2253e801 in __GI_abort () at abort.c:79
#8 0x00007fda22587897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fda226b4b9a "%s
") at ../sysdeps/posix/libc_fatal.c:181
#9 0x00007fda2258e90a in malloc_printerr (str=str@entry=0x7fda226b2e0e "malloc(): memory corruption") at malloc.c:5350
#10 0x00007fda22592994 in _int_malloc (av=av@entry=0x7fda00000020, bytes=bytes@entry=32) at malloc.c:3738
#11 0x00007fda225952ed in __GI___libc_malloc (bytes=32) at malloc.c:3065
#12 0x00007fda22db9258 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007fda244adaae in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate (this=0x7fd9ffffe740, __n=1)
at /usr/include/c++/5/ext/new_allocator.h:104
#14 0x00007fda244ad300 in __gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate (__a=..., __n=1)
at /usr/include/c++/5/ext/alloc_traits.h:182
#15 0x00007fda244ac858 in std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate (this=0x7fd9ffffe740, __n=1) at /usr/include/c++/5/bits/stl_vector.h:170
#16 0x00007fda244ab7c7 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux (this=0x7fd9ffffe740, __position=non-dereferenceable iterator for std::vector, __x="home") at /usr/include/c++/5/bits/vector.tcc:353
#17 0x00007fda244aada2 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x7fd9ffffe740, __x="home") at /usr/include/c++/5/bits/stl_vector.h:925
#18 0x00007fda2350ddcb in Poco::Path::pushDirectory (this=0x7fd9ffffe6c0, dir="home") at src/Path.cpp:471
#19 0x00007fda2350ea27 in Poco::Path::parseUnix (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:671
#20 0x00007fda2350cd6b in Poco::Path::assign (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:182
#21 0x00007fda2350c1be in Poco::Path::Path (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:54
#22 0x00007fda2350d33a in Poco::Path::makeAbsolute (this=0x7fd9ffffe8f0) at src/Path.cpp:318
#23 0x00007fda216b52ca in helpers::getDocumentPathAndURL (docFilename="setclientpart.ods", documentPath="/tmp/loadTorture_setclientpart.ods_ae70d2e_setclientpart.ods", documentURL="",
prefix="loadTorture_setclientpart.ods_") at ./helpers.hpp:153
#24 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_setclientpart.ods ", docName="setclientpart.ods", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#25 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994cffe18) at UnitLoadTorture.cpp:186
#26 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#27 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#28 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994cffe18) at /usr/include/c++/7/thread:234
#29 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994cffe18) at /usr/include/c++/7/thread:243
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994cffe10) at /usr/include/c++/7/thread:186
#31 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#32 0x00007fda228f66db in start_thread (arg=0x7fd9fffff700) at pthread_create.c:463
#33 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Change-Id: Ib60954e49e692082e686cb3fdc5fc9d5cfbc83c9
Reviewed-on: https://gerrit.libreoffice.org/83047
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2019-11-17 19:32:54 -06:00
|
|
|
std::unique_lock<std::mutex> guard(_lock);
|
|
|
|
for (const std::string& file: _filesToDelete)
|
2019-11-08 06:42:59 -06:00
|
|
|
filesystem::remove(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void registerForDeletion(const std::string& file)
|
|
|
|
{
|
test: thread-safe common shared test data
This protects against memory corruptions,
and a cascade of issues, such as the following:
Attaching to process 56245
[New LWP 56246]
[New LWP 56252]
[New LWP 56253]
[New LWP 56254]
[New LWP 56362]
[New LWP 56364]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fda228f7d2d in __GI___pthread_timedjoin_ex (threadid=140574279595776, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
89 pthread_join_common.c: No such file or directory.
Thread 7 (Thread 0x7fda197fa700 (LWP 56364)):
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007fda228f9023 in __GI___pthread_mutex_lock (mutex=0x55e9937567e0 <SigHandlerTrap>) at ../nptl/pthread_mutex_lock.c:78
#2 0x000055e9934cd4fe in __gthread_mutex_lock (__mutex=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748
#3 std::mutex::lock (this=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/c++/7/bits/std_mutex.h:103
#4 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:267
#5 std::unique_lock<std::mutex>::unique_lock (__m=..., this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:197
#6 SigUtil::handleFatalSignal (signal=11) at common/SigUtil.cpp:214
#7 <signal handler called>
#8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_capacity (this=<optimized out>, __capacity=0) at /usr/include/c++/7/bits/basic_string.h:200
#9 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=..., this=<optimized out>) at /usr/include/c++/7/bits/basic_string.h:542
#10 std::_Construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (
__p=<optimized out>) at /usr/include/c++/7/bits/stl_construct.h:75
#11 std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=0x7fd9f40017b0, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:83
#12 std::uninitialized_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=<optimized out>, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:134
#13 std::__uninitialized_copy_a<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (__result=<optimized out>, __last=..., __first=...)
at /usr/include/c++/7/bits/stl_uninitialized.h:289
#14 std::__uninitialized_move_if_noexcept_a<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > (__alloc=..., __result=<optimized out>, __last=0x55e995662850,
__first=<optimized out>) at /usr/include/c++/7/bits/stl_uninitialized.h:312
#15 std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_realloc_insert<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (
this=this@entry=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>,
__position=<error: Cannot access memory at address 0x3735003238323a>, __args#0="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp") at /usr/include/c++/7/bits/vector.tcc:424
#16 0x000055e9934aa829 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (__x="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at /usr/include/c++/7/bits/stl_vector.h:948
#17 (anonymous namespace)::FileDeleter::registerForDeletion (file="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at common/FileUtil.cpp:69
#18 FileUtil::getTempFilePath (srcDir=..., srcFilename=..., dstFilenamePrefix=...) at common/FileUtil.cpp:97
#19 0x00007fda216b51c9 in helpers::getDocumentPathAndURL (docFilename="viewcursor.odp", documentPath="", documentURL="", prefix="loadTorture_viewcursor.odp_") at ./helpers.hpp:151
#20 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_viewcursor.odp ", docName="viewcursor.odp", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#21 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994dbc758) at UnitLoadTorture.cpp:186
#22 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#23 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#24 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994dbc758) at /usr/include/c++/7/thread:234
#25 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994dbc758) at /usr/include/c++/7/thread:243
#26 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994dbc750) at /usr/include/c++/7/thread:186
#27 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#28 0x00007fda228f66db in start_thread (arg=0x7fda197fa700) at pthread_create.c:463
#29 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7fd9fffff700 (LWP 56362)):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007fda225952db in __GI___libc_malloc (bytes=bytes@entry=3635) at malloc.c:3063
#2 0x00007fda2262f364 in __backtrace_symbols (array=array@entry=0x7fd9ffffc540, size=size@entry=26) at backtracesyms.c:69
#3 0x000055e9934cc439 in SigUtil::dumpBacktrace () at common/SigUtil.cpp:253
#4 0x000055e9934cd5ae in SigUtil::handleFatalSignal (signal=6) at common/SigUtil.cpp:236
#5 <signal handler called>
#6 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#7 0x00007fda2253e801 in __GI_abort () at abort.c:79
#8 0x00007fda22587897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fda226b4b9a "%s
") at ../sysdeps/posix/libc_fatal.c:181
#9 0x00007fda2258e90a in malloc_printerr (str=str@entry=0x7fda226b2e0e "malloc(): memory corruption") at malloc.c:5350
#10 0x00007fda22592994 in _int_malloc (av=av@entry=0x7fda00000020, bytes=bytes@entry=32) at malloc.c:3738
#11 0x00007fda225952ed in __GI___libc_malloc (bytes=32) at malloc.c:3065
#12 0x00007fda22db9258 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007fda244adaae in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate (this=0x7fd9ffffe740, __n=1)
at /usr/include/c++/5/ext/new_allocator.h:104
#14 0x00007fda244ad300 in __gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate (__a=..., __n=1)
at /usr/include/c++/5/ext/alloc_traits.h:182
#15 0x00007fda244ac858 in std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate (this=0x7fd9ffffe740, __n=1) at /usr/include/c++/5/bits/stl_vector.h:170
#16 0x00007fda244ab7c7 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux (this=0x7fd9ffffe740, __position=non-dereferenceable iterator for std::vector, __x="home") at /usr/include/c++/5/bits/vector.tcc:353
#17 0x00007fda244aada2 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x7fd9ffffe740, __x="home") at /usr/include/c++/5/bits/stl_vector.h:925
#18 0x00007fda2350ddcb in Poco::Path::pushDirectory (this=0x7fd9ffffe6c0, dir="home") at src/Path.cpp:471
#19 0x00007fda2350ea27 in Poco::Path::parseUnix (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:671
#20 0x00007fda2350cd6b in Poco::Path::assign (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:182
#21 0x00007fda2350c1be in Poco::Path::Path (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:54
#22 0x00007fda2350d33a in Poco::Path::makeAbsolute (this=0x7fd9ffffe8f0) at src/Path.cpp:318
#23 0x00007fda216b52ca in helpers::getDocumentPathAndURL (docFilename="setclientpart.ods", documentPath="/tmp/loadTorture_setclientpart.ods_ae70d2e_setclientpart.ods", documentURL="",
prefix="loadTorture_setclientpart.ods_") at ./helpers.hpp:153
#24 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_setclientpart.ods ", docName="setclientpart.ods", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#25 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994cffe18) at UnitLoadTorture.cpp:186
#26 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#27 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#28 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994cffe18) at /usr/include/c++/7/thread:234
#29 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994cffe18) at /usr/include/c++/7/thread:243
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994cffe10) at /usr/include/c++/7/thread:186
#31 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#32 0x00007fda228f66db in start_thread (arg=0x7fd9fffff700) at pthread_create.c:463
#33 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Change-Id: Ib60954e49e692082e686cb3fdc5fc9d5cfbc83c9
Reviewed-on: https://gerrit.libreoffice.org/83047
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2019-11-17 19:32:54 -06:00
|
|
|
std::unique_lock<std::mutex> guard(_lock);
|
2019-11-08 06:42:59 -06:00
|
|
|
_filesToDelete.push_back(file);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
2016-11-12 15:38:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace FileUtil
|
|
|
|
{
|
|
|
|
std::string createRandomDir(const std::string& path)
|
|
|
|
{
|
2018-02-07 03:17:19 -06:00
|
|
|
const std::string name = Util::rng::getFilename(64);
|
2019-11-08 06:42:59 -06:00
|
|
|
#if HAVE_STD_FILESYSTEM
|
|
|
|
filesystem::create_directory(path + '/' + name);
|
|
|
|
#else
|
2016-11-12 15:38:13 -06:00
|
|
|
Poco::File(Poco::Path(path, name)).createDirectories();
|
2019-11-08 06:42:59 -06:00
|
|
|
#endif
|
2016-11-12 15:38:13 -06:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
bool copy(const std::string& fromPath, const std::string& toPath, bool log, bool throw_on_error)
|
2020-01-18 09:56:01 -06:00
|
|
|
{
|
|
|
|
int from = -1, to = -1;
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
try
|
|
|
|
{
|
2020-01-18 09:56:01 -06:00
|
|
|
from = open(fromPath.c_str(), O_RDONLY);
|
|
|
|
if (from < 0)
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
throw std::runtime_error("Failed to open src " + anonymizeUrl(fromPath));
|
2020-01-18 09:56:01 -06:00
|
|
|
|
|
|
|
struct stat st;
|
|
|
|
if (fstat(from, &st) != 0)
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
throw std::runtime_error("Failed to fstat src " + anonymizeUrl(fromPath));
|
2020-01-18 09:56:01 -06:00
|
|
|
|
|
|
|
to = open(toPath.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
|
|
|
|
if (to < 0)
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
throw std::runtime_error("Failed to open dest " + anonymizeUrl(toPath));
|
2020-01-18 09:56:01 -06:00
|
|
|
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
// Logging may be redundant and/or noisy.
|
|
|
|
if (log)
|
|
|
|
LOG_INF("Copying " << st.st_size << " bytes from " << anonymizeUrl(fromPath)
|
|
|
|
<< " to " << anonymizeUrl(toPath));
|
2020-01-18 09:56:01 -06:00
|
|
|
|
|
|
|
char buffer[64 * 1024];
|
|
|
|
|
|
|
|
int n;
|
|
|
|
off_t bytesIn = 0;
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
do
|
|
|
|
{
|
2020-01-18 09:56:01 -06:00
|
|
|
while ((n = ::read(from, buffer, sizeof(buffer))) < 0 && errno == EINTR)
|
|
|
|
LOG_TRC("EINTR reading from " << anonymizeUrl(fromPath));
|
|
|
|
if (n < 0)
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
throw std::runtime_error("Failed to read from " + anonymizeUrl(fromPath)
|
|
|
|
+ " at " + std::to_string(bytesIn) + " bytes in");
|
|
|
|
|
2020-01-18 09:56:01 -06:00
|
|
|
bytesIn += n;
|
|
|
|
if (n == 0) // EOF
|
|
|
|
break;
|
|
|
|
assert (off_t(sizeof (buffer)) >= n);
|
|
|
|
// Handle short writes and EINTR
|
|
|
|
for (int j = 0; j < n;)
|
|
|
|
{
|
|
|
|
int written;
|
|
|
|
while ((written = ::write(to, buffer + j, n - j)) < 0 && errno == EINTR)
|
|
|
|
LOG_TRC("EINTR writing to " << anonymizeUrl(toPath));
|
|
|
|
if (written < 0)
|
|
|
|
{
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
throw std::runtime_error("Failed to write " + std::to_string(n)
|
|
|
|
+ " bytes to " + anonymizeUrl(toPath) + " at "
|
|
|
|
+ std::to_string(bytesIn) + " bytes into "
|
|
|
|
+ anonymizeUrl(fromPath));
|
2020-01-18 09:56:01 -06:00
|
|
|
}
|
|
|
|
j += written;
|
|
|
|
}
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
} while (true);
|
2020-01-18 09:56:01 -06:00
|
|
|
if (bytesIn != st.st_size)
|
|
|
|
{
|
|
|
|
LOG_WRN("Unusual: file " << anonymizeUrl(fromPath) << " changed size "
|
|
|
|
"during copy from " << st.st_size << " to " << bytesIn);
|
|
|
|
}
|
2020-06-30 10:40:53 -05:00
|
|
|
close(from);
|
|
|
|
close(to);
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
return true;
|
2020-01-18 09:56:01 -06:00
|
|
|
}
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
catch (const std::exception& ex)
|
2020-01-18 09:56:01 -06:00
|
|
|
{
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
std::ostringstream oss;
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
oss << "Error while copying from " << anonymizeUrl(fromPath) << " to "
|
|
|
|
<< anonymizeUrl(toPath) << ": " << ex.what();
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
const std::string err = oss.str();
|
|
|
|
LOG_SYS(err);
|
2020-01-18 09:56:01 -06:00
|
|
|
close(from);
|
|
|
|
close(to);
|
|
|
|
unlink(toPath.c_str());
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
if (throw_on_error)
|
wsd: support read-only systemplate
For various reasons, systemplate may be read-only
or under a different owner and therefore impossible
to update the dynamic files in it.
To support such a scenario, we first link the
eight dynamic files in /etc when creating systemplate.
If this fails, we copy the files.
When creating jails, we always check that all the
dynamic files are up-to-date. If they are, nothing
further is necessary and we bind-mount, if enabled
and possible.
However, if the dynamic files are not up-to-date,
we disable bind-mounting and force linking
the files in the jails. Failing that, we copy them,
which is not ideal, but allows us to ensure the
dynamic files are up-to-date as we copy them too.
Ideally, the dynamic files in question would be
hard-link (or at least soft-linked) in systemplate
at creation. From then on we would bind-mount
the jails and everything would work perfectly and
no files would need updating. This patch is fallback
for when this scheme fails, which should be exceedingly
rare anyway, but which still ensures correct operation.
Change-Id: I09c6f057c49396579aaddb1b8bf4af0930dd4247
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100834
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2020-08-16 21:46:33 -05:00
|
|
|
throw std::runtime_error(err);
|
2020-01-18 09:56:01 -06:00
|
|
|
}
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
|
|
|
|
return false;
|
2020-01-18 09:56:01 -06:00
|
|
|
}
|
|
|
|
|
2020-11-15 08:04:39 -06:00
|
|
|
std::string getTemporaryDirectoryPath()
|
|
|
|
{
|
|
|
|
#if HAVE_STD_FILESYSTEM
|
|
|
|
return filesystem::temp_directory_path();
|
|
|
|
#else
|
|
|
|
return Poco::Path::temp();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-01-05 21:46:00 -06:00
|
|
|
std::string getTempFilePath(const std::string& srcDir, const std::string& srcFilename, const std::string& dstFilenamePrefix)
|
2016-11-12 15:38:13 -06:00
|
|
|
{
|
|
|
|
const std::string srcPath = srcDir + '/' + srcFilename;
|
2017-01-05 21:46:00 -06:00
|
|
|
const std::string dstFilename = dstFilenamePrefix + Util::encodeId(Util::rng::getNext()) + '_' + srcFilename;
|
2019-11-08 06:42:59 -06:00
|
|
|
#if HAVE_STD_FILESYSTEM
|
|
|
|
const std::string dstPath = filesystem::temp_directory_path() / dstFilename;
|
|
|
|
filesystem::copy(srcPath, dstPath);
|
|
|
|
|
|
|
|
static FileDeleter fileDeleter;
|
|
|
|
fileDeleter.registerForDeletion(dstPath);
|
|
|
|
#else
|
2017-01-05 21:46:00 -06:00
|
|
|
const std::string dstPath = Poco::Path(Poco::Path::temp(), dstFilename).toString();
|
2020-01-18 09:56:01 -06:00
|
|
|
copyFileTo(srcPath, dstPath);
|
2016-11-12 15:38:13 -06:00
|
|
|
Poco::TemporaryFile::registerForDeletion(dstPath);
|
2019-11-08 06:42:59 -06:00
|
|
|
#endif
|
|
|
|
|
2016-11-12 15:38:13 -06:00
|
|
|
return dstPath;
|
|
|
|
}
|
|
|
|
|
2020-03-25 12:43:36 -05:00
|
|
|
#if 1 // !HAVE_STD_FILESYSTEM
|
2017-01-29 23:04:10 -06:00
|
|
|
static int nftw_cb(const char *fpath, const struct stat*, int type, struct FTW*)
|
|
|
|
{
|
|
|
|
if (type == FTW_DP)
|
|
|
|
{
|
|
|
|
rmdir(fpath);
|
|
|
|
}
|
|
|
|
else if (type == FTW_F || type == FTW_SL)
|
|
|
|
{
|
|
|
|
unlink(fpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always continue even when things go wrong.
|
|
|
|
return 0;
|
|
|
|
}
|
2019-11-08 06:42:59 -06:00
|
|
|
#endif
|
2017-01-29 23:04:10 -06:00
|
|
|
|
|
|
|
void removeFile(const std::string& path, const bool recursive)
|
|
|
|
{
|
wsd: faster jail setup via bind-mount
loolmount now works and supports mounting and
unmounting, plus numerous improvements,
refactoring, logging, etc.. When enabled,
binding improves the jail setup time by anywhere
from 2x to orders of magnitude (in docker, f.e.).
A new config entry mount_jail_tree controls
whether mounting is used or the old method of
linking/copying of jail contents. It is set to
true by default and falls back to linking/copying.
A test mount is done when the setting is enabled,
and if mounting fails, it's disabled to avoid noise.
Temporarily disabled for unit-tests until we can
cleanup lingering mounts after Jenkins aborts our
build job. In a future patch we will have mount/jail
cleanup as part of make.
The network/system files in /etc that need frequent
refreshing are now updated in systemplate to make
their most recent version available in the jails.
These files can change during the course of loolwsd
lifetime, and are unlikely to be updated in
systemplate after installation at all. We link to
them in the systemplate/etc directory, and if that
fails, we copy them before forking each kit
instance to have the latest.
This reworks the approach used to bind-mount the
jails and the templates such that the total is
now down to only three mounts: systemplate, lo, tmp.
As now systemplate and lotemplate are shared, they
must be mounted as readonly, this means that user/
must now be moved into tmp/user/ which is writable.
The mount-points must be recursive, because we mount
lo/ within the mount-point of systemplate (which is
the root of the jail). But because we (re)bind
recursively, and because both systemplate and
lotemplate are mounted for each jails, we need to
make them unbindable, so they wouldn't multiply the
mount-points for each jails (an explosive growth!)
Contrarywise, we don't want the mount-points to
be shared, because we don't expect to add/remove
mounts after a jail is created.
The random temp directory is now created and set
correctly, plus many logging and other improvements.
Change-Id: Iae3fda5e876cf47d2cae6669a87b5b826a8748df
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92829
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-04-09 08:02:58 -05:00
|
|
|
LOG_DBG("Removing [" << path << "] " << (recursive ? "recursively." : "only."));
|
|
|
|
|
2020-03-25 12:43:36 -05:00
|
|
|
// Amazingly filesystem::remove_all silently fails to work on some
|
|
|
|
// systems. No real need to be using experimental API here either.
|
|
|
|
#if 0 // HAVE_STD_FILESYSTEM
|
2019-11-08 06:42:59 -06:00
|
|
|
std::error_code ec;
|
|
|
|
if (recursive)
|
|
|
|
filesystem::remove_all(path, ec);
|
|
|
|
else
|
|
|
|
filesystem::remove(path, ec);
|
|
|
|
|
|
|
|
// Already removed or we don't care about failures.
|
|
|
|
(void) ec;
|
|
|
|
#else
|
2017-01-29 23:04:10 -06:00
|
|
|
try
|
|
|
|
{
|
|
|
|
struct stat sb;
|
wsd: faster jail setup via bind-mount
loolmount now works and supports mounting and
unmounting, plus numerous improvements,
refactoring, logging, etc.. When enabled,
binding improves the jail setup time by anywhere
from 2x to orders of magnitude (in docker, f.e.).
A new config entry mount_jail_tree controls
whether mounting is used or the old method of
linking/copying of jail contents. It is set to
true by default and falls back to linking/copying.
A test mount is done when the setting is enabled,
and if mounting fails, it's disabled to avoid noise.
Temporarily disabled for unit-tests until we can
cleanup lingering mounts after Jenkins aborts our
build job. In a future patch we will have mount/jail
cleanup as part of make.
The network/system files in /etc that need frequent
refreshing are now updated in systemplate to make
their most recent version available in the jails.
These files can change during the course of loolwsd
lifetime, and are unlikely to be updated in
systemplate after installation at all. We link to
them in the systemplate/etc directory, and if that
fails, we copy them before forking each kit
instance to have the latest.
This reworks the approach used to bind-mount the
jails and the templates such that the total is
now down to only three mounts: systemplate, lo, tmp.
As now systemplate and lotemplate are shared, they
must be mounted as readonly, this means that user/
must now be moved into tmp/user/ which is writable.
The mount-points must be recursive, because we mount
lo/ within the mount-point of systemplate (which is
the root of the jail). But because we (re)bind
recursively, and because both systemplate and
lotemplate are mounted for each jails, we need to
make them unbindable, so they wouldn't multiply the
mount-points for each jails (an explosive growth!)
Contrarywise, we don't want the mount-points to
be shared, because we don't expect to add/remove
mounts after a jail is created.
The random temp directory is now created and set
correctly, plus many logging and other improvements.
Change-Id: Iae3fda5e876cf47d2cae6669a87b5b826a8748df
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92829
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-04-09 08:02:58 -05:00
|
|
|
errno = 0;
|
2017-01-29 23:04:10 -06:00
|
|
|
if (!recursive || stat(path.c_str(), &sb) == -1 || S_ISREG(sb.st_mode))
|
|
|
|
{
|
wsd: faster jail setup via bind-mount
loolmount now works and supports mounting and
unmounting, plus numerous improvements,
refactoring, logging, etc.. When enabled,
binding improves the jail setup time by anywhere
from 2x to orders of magnitude (in docker, f.e.).
A new config entry mount_jail_tree controls
whether mounting is used or the old method of
linking/copying of jail contents. It is set to
true by default and falls back to linking/copying.
A test mount is done when the setting is enabled,
and if mounting fails, it's disabled to avoid noise.
Temporarily disabled for unit-tests until we can
cleanup lingering mounts after Jenkins aborts our
build job. In a future patch we will have mount/jail
cleanup as part of make.
The network/system files in /etc that need frequent
refreshing are now updated in systemplate to make
their most recent version available in the jails.
These files can change during the course of loolwsd
lifetime, and are unlikely to be updated in
systemplate after installation at all. We link to
them in the systemplate/etc directory, and if that
fails, we copy them before forking each kit
instance to have the latest.
This reworks the approach used to bind-mount the
jails and the templates such that the total is
now down to only three mounts: systemplate, lo, tmp.
As now systemplate and lotemplate are shared, they
must be mounted as readonly, this means that user/
must now be moved into tmp/user/ which is writable.
The mount-points must be recursive, because we mount
lo/ within the mount-point of systemplate (which is
the root of the jail). But because we (re)bind
recursively, and because both systemplate and
lotemplate are mounted for each jails, we need to
make them unbindable, so they wouldn't multiply the
mount-points for each jails (an explosive growth!)
Contrarywise, we don't want the mount-points to
be shared, because we don't expect to add/remove
mounts after a jail is created.
The random temp directory is now created and set
correctly, plus many logging and other improvements.
Change-Id: Iae3fda5e876cf47d2cae6669a87b5b826a8748df
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92829
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-04-09 08:02:58 -05:00
|
|
|
// Non-recursive directories and files that exist.
|
|
|
|
if (errno != ENOENT)
|
|
|
|
Poco::File(path).remove(recursive);
|
2017-01-29 23:04:10 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Directories only.
|
|
|
|
nftw(path.c_str(), nftw_cb, 128, FTW_DEPTH | FTW_PHYS);
|
|
|
|
}
|
|
|
|
}
|
2020-04-14 16:09:54 -05:00
|
|
|
catch (const std::exception&e)
|
2017-01-29 23:04:10 -06:00
|
|
|
{
|
|
|
|
// Already removed or we don't care about failures.
|
wsd: faster jail setup via bind-mount
loolmount now works and supports mounting and
unmounting, plus numerous improvements,
refactoring, logging, etc.. When enabled,
binding improves the jail setup time by anywhere
from 2x to orders of magnitude (in docker, f.e.).
A new config entry mount_jail_tree controls
whether mounting is used or the old method of
linking/copying of jail contents. It is set to
true by default and falls back to linking/copying.
A test mount is done when the setting is enabled,
and if mounting fails, it's disabled to avoid noise.
Temporarily disabled for unit-tests until we can
cleanup lingering mounts after Jenkins aborts our
build job. In a future patch we will have mount/jail
cleanup as part of make.
The network/system files in /etc that need frequent
refreshing are now updated in systemplate to make
their most recent version available in the jails.
These files can change during the course of loolwsd
lifetime, and are unlikely to be updated in
systemplate after installation at all. We link to
them in the systemplate/etc directory, and if that
fails, we copy them before forking each kit
instance to have the latest.
This reworks the approach used to bind-mount the
jails and the templates such that the total is
now down to only three mounts: systemplate, lo, tmp.
As now systemplate and lotemplate are shared, they
must be mounted as readonly, this means that user/
must now be moved into tmp/user/ which is writable.
The mount-points must be recursive, because we mount
lo/ within the mount-point of systemplate (which is
the root of the jail). But because we (re)bind
recursively, and because both systemplate and
lotemplate are mounted for each jails, we need to
make them unbindable, so they wouldn't multiply the
mount-points for each jails (an explosive growth!)
Contrarywise, we don't want the mount-points to
be shared, because we don't expect to add/remove
mounts after a jail is created.
The random temp directory is now created and set
correctly, plus many logging and other improvements.
Change-Id: Iae3fda5e876cf47d2cae6669a87b5b826a8748df
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92829
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-04-09 08:02:58 -05:00
|
|
|
LOG_DBG("Failed to remove [" << path << "] " << (recursive ? "recursively: " : "only: ")
|
|
|
|
<< e.what());
|
2017-01-29 23:04:10 -06:00
|
|
|
}
|
2019-11-08 06:42:59 -06:00
|
|
|
#endif
|
2017-01-29 23:04:10 -06:00
|
|
|
}
|
|
|
|
|
2020-07-05 16:51:02 -05:00
|
|
|
std::string realpath(const char* path)
|
|
|
|
{
|
|
|
|
char* resolved = ::realpath(path, nullptr);
|
|
|
|
if (resolved)
|
|
|
|
{
|
|
|
|
std::string real = resolved;
|
|
|
|
free(resolved);
|
|
|
|
return real;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_SYS("Failed to get the realpath of [" << path << "]");
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
bool isEmptyDirectory(const char* path)
|
|
|
|
{
|
|
|
|
DIR* dir = opendir(path);
|
|
|
|
if (dir == nullptr)
|
|
|
|
return errno != EACCES; // Assume it's not empty when EACCES.
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
while (readdir(dir) && ++count < 3)
|
|
|
|
;
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
return count <= 2; // Discounting . and ..
|
|
|
|
}
|
|
|
|
|
mount: handle symlinks and improve updating systemplate
We should have no symlinks in the jail whatsoever, except
those we create to files known to exist in the jail.
Unfortunately, some systems have some of the /etc files
as symlinks. When we create hard-links to these files,
they can't be accessed from the jail, since the path
they point to isn't replicated in systemplate and jails.
First change here is to always link to the source file or,
when copying, to copy the source rather than a symlink.
Next, to detect modifications, we compare not just the
size and timestamp, but also the contents. This way we
can be certain that any modification will be detected.
Finally, when we copy at least one file in the
systemplate/etc directory, we flag it by creating the
'copied' file. This way we have a reliable indicator
and don't need to second guess if the files are
hard-linked or copied.
We also avoid some noisy errors when we fail to update
systemplate when it's read-only by first checking
if systemplate is writable or not and insue a friendly
log instead.
Change-Id: Ie8c3e70ea4ec19ee098309f8666c00639fa7319b
2020-10-18 20:56:40 -05:00
|
|
|
bool isWritable(const char* path)
|
|
|
|
{
|
|
|
|
if (access(path, W_OK) == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
LOG_DBG("Cannot access path [" << path << "]: " << strerror(errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
bool updateTimestamps(const std::string& filename, timespec tsAccess, timespec tsModified)
|
|
|
|
{
|
|
|
|
// The timestamp is in seconds and microseconds.
|
2020-07-08 06:27:19 -05:00
|
|
|
timeval timestamps[2]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tsAccess.tv_sec,
|
|
|
|
#ifdef IOS
|
|
|
|
(__darwin_suseconds_t)
|
|
|
|
#endif
|
|
|
|
(tsAccess.tv_nsec / 1000)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tsModified.tv_sec,
|
|
|
|
#ifdef IOS
|
|
|
|
(__darwin_suseconds_t)
|
|
|
|
#endif
|
|
|
|
(tsModified.tv_nsec / 1000)
|
|
|
|
}
|
|
|
|
};
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
if (utimes(filename.c_str(), timestamps) != 0)
|
|
|
|
{
|
|
|
|
LOG_SYS("Failed to update the timestamp of [" << filename << "]");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool copyAtomic(const std::string& fromPath, const std::string& toPath, bool preserveTimestamps)
|
|
|
|
{
|
|
|
|
const std::string randFilename = toPath + Util::rng::getFilename(12);
|
|
|
|
if (copy(fromPath, randFilename, /*log=*/false, /*throw_on_error=*/false))
|
|
|
|
{
|
|
|
|
if (preserveTimestamps)
|
|
|
|
{
|
|
|
|
const Stat st(fromPath);
|
2020-07-08 06:27:19 -05:00
|
|
|
updateTimestamps(randFilename,
|
|
|
|
#ifdef IOS
|
|
|
|
st.sb().st_atimespec, st.sb().st_mtimespec
|
|
|
|
#else
|
|
|
|
st.sb().st_atim, st.sb().st_mtim
|
|
|
|
#endif
|
|
|
|
);
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now rename atomically, replacing any existing files with the same name.
|
|
|
|
if (rename(randFilename.c_str(), toPath.c_str()) == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
LOG_SYS("Failed to copy [" << fromPath << "] -> [" << toPath
|
|
|
|
<< "] while atomically renaming:");
|
|
|
|
removeFile(randFilename, false); // Cleanup.
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool linkOrCopyFile(const char* source, const char* target)
|
|
|
|
{
|
|
|
|
if (link(source, target) == -1)
|
|
|
|
{
|
mount: handle symlinks and improve updating systemplate
We should have no symlinks in the jail whatsoever, except
those we create to files known to exist in the jail.
Unfortunately, some systems have some of the /etc files
as symlinks. When we create hard-links to these files,
they can't be accessed from the jail, since the path
they point to isn't replicated in systemplate and jails.
First change here is to always link to the source file or,
when copying, to copy the source rather than a symlink.
Next, to detect modifications, we compare not just the
size and timestamp, but also the contents. This way we
can be certain that any modification will be detected.
Finally, when we copy at least one file in the
systemplate/etc directory, we flag it by creating the
'copied' file. This way we have a reliable indicator
and don't need to second guess if the files are
hard-linked or copied.
We also avoid some noisy errors when we fail to update
systemplate when it's read-only by first checking
if systemplate is writable or not and insue a friendly
log instead.
Change-Id: Ie8c3e70ea4ec19ee098309f8666c00639fa7319b
2020-10-18 20:56:40 -05:00
|
|
|
LOG_DBG("link(\"" << source << "\", \"" << target << "\") failed: " << strerror(errno)
|
wsd: support parallel systemplate setup
When tests are run in parallel, they will all
compete to update and set up the systemplate
directory, which has a handful of files that
need to be up-to-date. This is a source of errors.
Normally, these files are linked (hard- or soft-
link, whichever succeeds). With linking, we
only need to worry about the initial setup,
as the files will never be out-of-date from
then on. However, when linking fails, we need
to copy the files, and update them (by copying
over fresh versions of the files, if necessary)
every time a new kit is forked. Copying over
is tricky, as it's not atomic. To make it
atomic, we copy the files to the destination
directory under a temporary (random) name,
and then rename to the final name (which is
atomic, including replacing the target file,
if it exists).
No such race exists in production, where there
is (or should be) but one instance of loolwsd
(which does the initial setup) and forkit
(which updates systemplate before forking
new kit instances).
This is an issue with parallel tests only.
Change-Id: I6ba1514d00a84da7397d28efeb6378619711d52f
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97785
Tested-by: Jenkins
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
2020-07-02 16:54:28 -05:00
|
|
|
<< ". Will copy.");
|
|
|
|
return copy(source, target, /*log=*/false, /*throw_on_error=*/false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
mount: handle symlinks and improve updating systemplate
We should have no symlinks in the jail whatsoever, except
those we create to files known to exist in the jail.
Unfortunately, some systems have some of the /etc files
as symlinks. When we create hard-links to these files,
they can't be accessed from the jail, since the path
they point to isn't replicated in systemplate and jails.
First change here is to always link to the source file or,
when copying, to copy the source rather than a symlink.
Next, to detect modifications, we compare not just the
size and timestamp, but also the contents. This way we
can be certain that any modification will be detected.
Finally, when we copy at least one file in the
systemplate/etc directory, we flag it by creating the
'copied' file. This way we have a reliable indicator
and don't need to second guess if the files are
hard-linked or copied.
We also avoid some noisy errors when we fail to update
systemplate when it's read-only by first checking
if systemplate is writable or not and insue a friendly
log instead.
Change-Id: Ie8c3e70ea4ec19ee098309f8666c00639fa7319b
2020-10-18 20:56:40 -05:00
|
|
|
bool compareFileContents(const std::string& rhsPath, const std::string& lhsPath)
|
|
|
|
{
|
|
|
|
std::ifstream rhs(rhsPath, std::ifstream::binary | std::ifstream::ate);
|
|
|
|
if (rhs.fail())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::ifstream lhs(lhsPath, std::ifstream::binary | std::ifstream::ate);
|
|
|
|
if (lhs.fail())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (rhs.tellg() != lhs.tellg())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
rhs.seekg(0, std::ifstream::beg);
|
|
|
|
lhs.seekg(0, std::ifstream::beg);
|
|
|
|
return std::equal(std::istreambuf_iterator<char>(rhs.rdbuf()),
|
|
|
|
std::istreambuf_iterator<char>(),
|
|
|
|
std::istreambuf_iterator<char>(lhs.rdbuf()));
|
|
|
|
}
|
|
|
|
|
2016-11-12 15:38:13 -06:00
|
|
|
} // namespace FileUtil
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
struct fs
|
|
|
|
{
|
2018-12-10 01:55:24 -06:00
|
|
|
fs(const std::string& path, dev_t dev)
|
|
|
|
: _path(path), _dev(dev)
|
2016-11-12 15:38:13 -06:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-12-10 01:55:24 -06:00
|
|
|
const std::string& getPath() const { return _path; }
|
|
|
|
|
|
|
|
dev_t getDev() const { return _dev; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string _path;
|
|
|
|
dev_t _dev;
|
2016-11-12 15:38:13 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
struct fsComparator
|
|
|
|
{
|
|
|
|
bool operator() (const fs& lhs, const fs& rhs) const
|
|
|
|
{
|
2018-12-10 01:55:24 -06:00
|
|
|
return (lhs.getDev() < rhs.getDev());
|
2016-11-12 15:38:13 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::mutex fsmutex;
|
|
|
|
static std::set<fs, fsComparator> filesystems;
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
namespace FileUtil
|
|
|
|
{
|
2019-02-12 05:16:40 -06:00
|
|
|
#if !MOBILEAPP
|
2016-11-12 15:38:13 -06:00
|
|
|
void registerFileSystemForDiskSpaceChecks(const std::string& path)
|
|
|
|
{
|
2018-02-23 18:14:49 -06:00
|
|
|
const std::string::size_type lastSlash = path.rfind('/');
|
|
|
|
assert(path.empty() || lastSlash != std::string::npos);
|
|
|
|
if (lastSlash != std::string::npos)
|
2016-11-12 15:38:13 -06:00
|
|
|
{
|
2018-02-23 18:14:49 -06:00
|
|
|
const std::string dirPath = path.substr(0, lastSlash + 1) + '.';
|
2020-05-24 08:10:18 -05:00
|
|
|
LOG_INF("Registering filesystem for space checks: [" << dirPath << ']');
|
2018-02-23 18:14:49 -06:00
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(fsmutex);
|
2016-11-12 15:38:13 -06:00
|
|
|
|
|
|
|
struct stat s;
|
2016-11-22 21:06:05 -06:00
|
|
|
if (stat(dirPath.c_str(), &s) == 0)
|
|
|
|
{
|
|
|
|
filesystems.insert(fs(dirPath, s.st_dev));
|
|
|
|
}
|
2016-11-12 15:38:13 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-04 00:29:45 -06:00
|
|
|
std::string checkDiskSpaceOnRegisteredFileSystems(const bool cacheLastCheck)
|
2016-11-12 15:38:13 -06:00
|
|
|
{
|
|
|
|
static std::chrono::steady_clock::time_point lastCheck;
|
|
|
|
std::chrono::steady_clock::time_point now(std::chrono::steady_clock::now());
|
|
|
|
|
2018-02-23 18:14:49 -06:00
|
|
|
std::lock_guard<std::mutex> lock(fsmutex);
|
|
|
|
|
|
|
|
// Don't check more often than once a minute
|
2016-11-12 15:38:13 -06:00
|
|
|
if (std::chrono::duration_cast<std::chrono::seconds>(now - lastCheck).count() < 60)
|
2016-11-22 21:06:50 -06:00
|
|
|
return std::string();
|
2016-11-12 15:38:13 -06:00
|
|
|
|
2017-01-04 00:29:45 -06:00
|
|
|
if (cacheLastCheck)
|
|
|
|
lastCheck = now;
|
2016-11-12 15:38:13 -06:00
|
|
|
|
2018-02-23 18:14:49 -06:00
|
|
|
for (const auto& i: filesystems)
|
2016-11-12 15:38:13 -06:00
|
|
|
{
|
2018-12-10 01:55:24 -06:00
|
|
|
if (!checkDiskSpace(i.getPath()))
|
2016-11-12 15:38:13 -06:00
|
|
|
{
|
2018-12-10 01:55:24 -06:00
|
|
|
return i.getPath();
|
2016-11-12 15:38:13 -06:00
|
|
|
}
|
|
|
|
}
|
2016-11-22 21:06:50 -06:00
|
|
|
|
|
|
|
return std::string();
|
2016-11-12 15:38:13 -06:00
|
|
|
}
|
2018-09-13 11:16:00 -05:00
|
|
|
#endif
|
2016-11-12 15:38:13 -06:00
|
|
|
|
|
|
|
bool checkDiskSpace(const std::string& path)
|
|
|
|
{
|
2016-11-22 21:06:05 -06:00
|
|
|
assert(!path.empty());
|
|
|
|
|
2019-02-12 05:16:40 -06:00
|
|
|
#if !MOBILEAPP
|
2017-03-31 11:18:41 -05:00
|
|
|
bool hookResult;
|
|
|
|
if (UnitBase::get().filterCheckDiskSpace(path, hookResult))
|
|
|
|
return hookResult;
|
2018-09-05 07:11:05 -05:00
|
|
|
#endif
|
2017-03-31 11:18:41 -05:00
|
|
|
|
2019-05-23 04:28:37 -05:00
|
|
|
// we should be able to run just OK with 5GB for production or 1GB for development
|
|
|
|
#if ENABLE_DEBUG
|
|
|
|
const int64_t gb(1);
|
|
|
|
#else
|
|
|
|
const int64_t gb(5);
|
|
|
|
#endif
|
|
|
|
constexpr int64_t ENOUGH_SPACE = gb*1024*1024*1024;
|
2018-08-29 10:23:22 -05:00
|
|
|
|
2020-11-08 09:35:56 -06:00
|
|
|
#if defined(__linux ) || defined(__FreeBSD__)
|
2016-11-12 15:38:13 -06:00
|
|
|
struct statfs sfs;
|
|
|
|
if (statfs(path.c_str(), &sfs) == -1)
|
|
|
|
return true;
|
|
|
|
|
2018-02-23 18:14:49 -06:00
|
|
|
const int64_t freeBytes = static_cast<int64_t>(sfs.f_bavail) * sfs.f_bsize;
|
|
|
|
|
|
|
|
LOG_INF("Filesystem [" << path << "] has " << (freeBytes / 1024 / 1024) <<
|
|
|
|
" MB free (" << (sfs.f_bavail * 100. / sfs.f_blocks) << "%).");
|
|
|
|
|
|
|
|
if (freeBytes > ENOUGH_SPACE)
|
2017-02-21 12:55:04 -06:00
|
|
|
return true;
|
|
|
|
|
2016-11-12 15:38:13 -06:00
|
|
|
if (static_cast<double>(sfs.f_bavail) / sfs.f_blocks <= 0.05)
|
|
|
|
return false;
|
2018-09-05 07:11:05 -05:00
|
|
|
#elif defined IOS
|
2018-08-29 10:23:22 -05:00
|
|
|
NSDictionary *atDict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/" error:NULL];
|
|
|
|
long long freeSpace = [[atDict objectForKey:NSFileSystemFreeSize] longLongValue];
|
|
|
|
long long totalSpace = [[atDict objectForKey:NSFileSystemSize] longLongValue];
|
|
|
|
|
|
|
|
if (freeSpace > ENOUGH_SPACE)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (static_cast<double>(freeSpace) / totalSpace <= 0.05)
|
|
|
|
return false;
|
|
|
|
#endif
|
2017-02-21 12:55:04 -06:00
|
|
|
|
2016-11-12 15:38:13 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-17 16:31:41 -06:00
|
|
|
namespace {
|
|
|
|
bool AnonymizeUserData = false;
|
|
|
|
std::uint64_t AnonymizationSalt = 82589933;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setUrlAnonymization(bool anonymize, const std::uint64_t salt)
|
|
|
|
{
|
|
|
|
AnonymizeUserData = anonymize;
|
|
|
|
AnonymizationSalt = salt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Anonymize the basename of filenames, preserving the path and extension.
|
|
|
|
std::string anonymizeUrl(const std::string& url)
|
|
|
|
{
|
|
|
|
return AnonymizeUserData ? Util::anonymizeUrl(url, AnonymizationSalt) : url;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Anonymize user names and IDs.
|
2020-04-26 15:55:16 -05:00
|
|
|
/// Will use the Obfuscated User ID if one is provided via WOPI.
|
2020-01-17 16:31:41 -06:00
|
|
|
std::string anonymizeUsername(const std::string& username)
|
|
|
|
{
|
|
|
|
return AnonymizeUserData ? Util::anonymize(username, AnonymizationSalt) : username;
|
|
|
|
}
|
|
|
|
|
2016-11-12 15:38:13 -06:00
|
|
|
} // namespace FileUtil
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|