-
-
Notifications
You must be signed in to change notification settings - Fork 644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wickman's proposal for pants reorg #5
Comments
@jsirois What's our plan here? I'm writing because I'm hitting an issue to bootstrap pants in twitter pants_internal [1]. Seems we have 3 different type of pants related repos:
My problem came from 2. above. When we want to execute tests for pants_internal repo, meaning we want to run pants goal test against test code we written in that repo, the bootstrap script would try to clone OS pants and then execute, which isn't allowed in our CI environment. So I tried with using OS_PANTS_ORIGIN to point to our internal mirror of OS pants. Still not working, because the OS pants bootstrap will get virtualenv and other requirements from pypi. Two options, 1) I could've amend OS pants bootstrap scripts somehow to let them be aware of caching locations, but seems a bit more involved so I opted for 2) I simply using a pre-built pants.pex to run goal tests which bypass all these external accesses. However, this only goes so for running simple tests. When I run a test case derived from pants_run_integration_test.py which shells out and call pants_internal repo root's pants bootstrap script, since it doesn't check for local pants.pex, it again starts to clone OS pants. So my questions are (sorry for typing so much, it took me a while to unravel these different code paths during bootstrapping):
[1] For non current/former twitter pants devs: this pants_internal repo isn't an end product git repo that uses pants to build, but it's a repo inside twitter where we develop pants plugins/backends and wrap the open source pants in (or rather more precisely, insert our plugins/backends into open sources pants). |
I think this is complete. Close? |
We haven't achieved the stuff in the "bootstrapping" section. But I ?think? we have achieved the code-layout parts of working towards that "boostrapping" section. |
We do need a bootsrap script much like gradlew that can bootsrap a virtualenv for pantsbuild.pants to be pip installed into. But we also are still short in the 'repository BUILD' section. Namely we cannot bootstrap 3rdparty deps - including plugins - for you today and we need to. |
All issues mentioned in John's most recent comment have been addressed, and the packaging concerns have all been invalidated (if not fixed). |
…n test. (#4407) ### Problem Currently, on Linux the first thin client call to the daemon can deadlock just after the pantsd->fork->pantsd-runner workflow. Connecting to the process with `gdb` reveals a deadlock in the following stack in the `post_fork` `drop` of the `CpuPool`: ``` #0 0x00007f63f04c31bd in __lll_lock_wait () from /lib64/libpthread.so.0 No symbol table info available. #1 0x00007f63f04c0ded in pthread_cond_signal@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 No symbol table info available. #2 0x00007f63d3cfa438 in notify_one () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/condvar.rs:52 No locals. #3 notify_one () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys_common/condvar.rs:39 No locals. #4 notify_one () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sync/condvar.rs:208 No locals. #5 std::thread::{{impl}}::unpark () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/thread/mod.rs:633 No locals. #6 0x00007f63d3c583d1 in crossbeam::sync::ms_queue::{{impl}}::push<futures_cpupool::Message> (self=<optimized out>, t=...) at /home/kwilson/.cache/pants/rust-toolchain/registry/src/jackfan.us.kg-1ecc6299db9ec823/crossbeam-0.2.10/src/sync/ms_queue.rs:178 guard = <optimized out> self = <optimized out> #7 0x00007f63d3c588ed in futures_cpupool::{{impl}}::drop (self=<optimized out>) at /home/kwilson/.cache/pants/rust-toolchain/git/checkouts/futures-rs-a4f11d094efefb0a/f7e6bc8/futures-cpupool/src/lib.rs:236 self = 0x37547a0 #8 0x00007f63d3be871c in engine::fs::{{impl}}::post_fork (self=0x3754778) at /home/kwilson/dev/pants/src/rust/engine/src/fs.rs:355 self = 0x3754778 #9 0x00007f63d3be10e4 in engine::context::{{impl}}::post_fork (self=0x37545b0) at /home/kwilson/dev/pants/src/rust/engine/src/context.rs:93 self = 0x37545b0 #10 0x00007f63d3c0de5a in {{closure}} (scheduler=<optimized out>) at /home/kwilson/dev/pants/src/rust/engine/src/lib.rs:275 scheduler = 0x3740580 #11 with_scheduler<closure,()> (scheduler_ptr=<optimized out>, f=...) at /home/kwilson/dev/pants/src/rust/engine/src/lib.rs:584 scheduler = 0x3740580 scheduler_ptr = 0x3740580 #12 engine::scheduler_post_fork (scheduler_ptr=0x3740580) at /home/kwilson/dev/pants/src/rust/engine/src/lib.rs:274 scheduler_ptr = 0x3740580 #13 0x00007f63d3c1be8c in _cffi_f_scheduler_post_fork (self=<optimized out>, arg0=0x35798f0) at src/cffi/native_engine.c:2234 _save = 0x34a65a0 x0 = 0x3740580 datasize = <optimized out> #14 0x00007f63f07b5a62 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0 ``` This presents as a hang in the thin client, because the pailgun socket is left open in the pantsd-runner. ### Solution Add pre-fork hooks and tear down the `CpuPool` instances prior to forking and rebuilding them. ### Result Can no longer reproduce the hang.
…n test. (pantsbuild#4407) ### Problem Currently, on Linux the first thin client call to the daemon can deadlock just after the pantsd->fork->pantsd-runner workflow. Connecting to the process with `gdb` reveals a deadlock in the following stack in the `post_fork` `drop` of the `CpuPool`: ``` #0 0x00007f63f04c31bd in __lll_lock_wait () from /lib64/libpthread.so.0 No symbol table info available. pantsbuild#1 0x00007f63f04c0ded in pthread_cond_signal@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 No symbol table info available. pantsbuild#2 0x00007f63d3cfa438 in notify_one () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/condvar.rs:52 No locals. pantsbuild#3 notify_one () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys_common/condvar.rs:39 No locals. pantsbuild#4 notify_one () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sync/condvar.rs:208 No locals. pantsbuild#5 std::thread::{{impl}}::unpark () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/thread/mod.rs:633 No locals. pantsbuild#6 0x00007f63d3c583d1 in crossbeam::sync::ms_queue::{{impl}}::push<futures_cpupool::Message> (self=<optimized out>, t=...) at /home/kwilson/.cache/pants/rust-toolchain/registry/src/jackfan.us.kg-1ecc6299db9ec823/crossbeam-0.2.10/src/sync/ms_queue.rs:178 guard = <optimized out> self = <optimized out> pantsbuild#7 0x00007f63d3c588ed in futures_cpupool::{{impl}}::drop (self=<optimized out>) at /home/kwilson/.cache/pants/rust-toolchain/git/checkouts/futures-rs-a4f11d094efefb0a/f7e6bc8/futures-cpupool/src/lib.rs:236 self = 0x37547a0 pantsbuild#8 0x00007f63d3be871c in engine::fs::{{impl}}::post_fork (self=0x3754778) at /home/kwilson/dev/pants/src/rust/engine/src/fs.rs:355 self = 0x3754778 pantsbuild#9 0x00007f63d3be10e4 in engine::context::{{impl}}::post_fork (self=0x37545b0) at /home/kwilson/dev/pants/src/rust/engine/src/context.rs:93 self = 0x37545b0 pantsbuild#10 0x00007f63d3c0de5a in {{closure}} (scheduler=<optimized out>) at /home/kwilson/dev/pants/src/rust/engine/src/lib.rs:275 scheduler = 0x3740580 pantsbuild#11 with_scheduler<closure,()> (scheduler_ptr=<optimized out>, f=...) at /home/kwilson/dev/pants/src/rust/engine/src/lib.rs:584 scheduler = 0x3740580 scheduler_ptr = 0x3740580 pantsbuild#12 engine::scheduler_post_fork (scheduler_ptr=0x3740580) at /home/kwilson/dev/pants/src/rust/engine/src/lib.rs:274 scheduler_ptr = 0x3740580 pantsbuild#13 0x00007f63d3c1be8c in _cffi_f_scheduler_post_fork (self=<optimized out>, arg0=0x35798f0) at src/cffi/native_engine.c:2234 _save = 0x34a65a0 x0 = 0x3740580 datasize = <optimized out> pantsbuild#14 0x00007f63f07b5a62 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0 ``` This presents as a hang in the thin client, because the pailgun socket is left open in the pantsd-runner. ### Solution Add pre-fork hooks and tear down the `CpuPool` instances prior to forking and rebuilding them. ### Result Can no longer reproduce the hang.
This was originally filed here
When pants moves to its own repository, I'd like to take the opportunity to do a code reorg in order to make it easier for other projects / repositories / organizations to use pants.
current layout
Backends (java, scala, python, etc) consist of tasks and targets, and basic wiring into phases. Right now the code org is something like this:
Bolded is what I consider to be "pants core" – as in pants simply can't operate without code in there. Specifically this is the execution engine and ancillary stuff like base classes for everything else (Task, Goal, Target.) Currently the Task/TaskError base classes are in pants.tasks.init but should be moved into pants.base.
While pants/init.py contains some code necessary for pants to run (get_buildroot), most of it should be moved out to the leaves (is_* e.g. is_java, is_scala) and 'from twitter.pants.targets import *' should go away entirely.
new backend layout
I propose that everything in pants.java, pants.python, pants.targets and pants.tasks be reorganized (temporarily) into a new toplevel directory:
With the following layout:
Each backend is treated as a namespace package so that they can more easily be developed by third parties. This model works naturally with the python.new backend, and for the most part with the Java and Scala backends.
One case where this is more challenging is IDL backends. My proposal for handling this is by making the CodeGen(Task) base class in pants.base the canonical base class for code generation, and specific pants.backend.thrift and pants.backend.protobuf IDL backends that other backends can then depend upon. For example, pants.backend.python would depend upon pants.backend.thrift, and subclass the ThriftGen base from pants.backend.thrift.base to create a Python-specific codegen target. (I've already done the refactor in the python.new branch to make this more straightforward through language-specific createtarget abstract base classes.) So rather than the 'gen' phase with 'gen:thrift' and 'gen:protobuf' goals, you'd have the 'gen' phase with 'gen:thrift-python', 'gen:thrift-java', 'gen:protobuf-go' etc.
bootstrapping
To bootstrap a repository to use pants, you would do the following:
The pants bootstrap script currently bootstraps itself from PyPI, though some of the dependent source dists have not yet been published (specifically twitter.pants, twitter.common-core, twitter.common.python) but we can do that when we're ready – especially since twitter.pants could be 'pb' or 'pantsbuild' or something else. If you don't have external network access, you'd add a field in pants.ini that specifies where the bootstrapper should be looking for artifacts and you'd cache them locally. Similarly, by default the bootstrap script bootstraps the latest version of pants, but you could address specific versions in the pants.ini using the existing Requirement format (e.g. 'pb==0.3.2' or 'pb>0.3,<1').
The bootstrapper script would write pants.pex and on subsequent runs 1) check the pants.pex version to make sure it's compatible with the one defined in pants.ini and if so 2) os.execv.
repository BUILD
The root BUILD would look like:
Each backend would be a PythonLibrary with a corresponding SetupPy artifact, which can have install_requires in order to dictate dependencies (e.g. pystache, boto, pants.backend.thrift, whatever.) The upside being that 1) this is all already implemented and 2) they could write a backend as a standard setup.py project outside of pants.
require_path would simply look for an init.py in that directory and install everything there into the root namespace.
Currently for BUILD files to be usable, we autoinject 'from pants.targets import *' and 'from twitter.common.quantity import Amount, Time' in every single one. Instead, we'd deposit the union of the namespaces created by the buildroot BUILD, and the init.py of each registered backend into all down-tree BUILDs. The backend _init_s would also be responsible for wiring tasks into phases.
The text was updated successfully, but these errors were encountered: