IRC logs for #buildstream for Wednesday, 2020-06-17

*** hasebastian has joined #buildstream03:35
*** tristan has quit IRC03:38
*** tristan has joined #buildstream04:24
*** ChanServ sets mode: +o tristan04:24
tristanIs it possible for a subproject to be overridden more than once in the ancestry ?05:59
tristanOr should it ?05:59
tristanLets say project overrides subproject's junction to subsubproject with a different definition of subsubproject, which in turn has a subsubsubproject... and then project overrides that subsubsubproject in the same junction06:02
tristanhmm06:02
juergbitristan: hm, you override junctions, not subprojects06:02
juergbionce a junction is overridden, the original one is irrelevant06:02
tristanjuergbi, that is exactly what is untrue06:05
tristanjuergbi, because duplicates and internal are project <--> junction relationships which are supposed to be preserved regardless of overrides06:06
tristanSo I need to preserve what the original parents were at the time of override06:06
juergbiwe need to formulate this more precisely06:07
tristanAnd I need to consider every plausible parent (not only the active parent) when constructing paths to search for duplicates06:07
juergbii.e. distinguish between a junction name and a junction config06:07
juergbior contents, whatever we call it06:07
tristanA junction config never enters into any equation06:07
juergbijunction config/contents are replaced when overridden06:07
juergbionly the junction name is still relevant06:07
juergbiand internal is about project to junction name06:08
tristanjuergbi, https://bpa.st/7FKA06:11
tristanjuergbi, I'm not sure if I've formulated it exactly correctly but maybe you can get what I'm getting at in that paste ?06:11
tristanMaybe my example needs one extra level of depth to be exactly realistic06:13
tristansubsubsubsubsubproject.bst could be overridden by subsubsubproject.bst's junction to subsubsubsubproject.bst06:14
tristanAnd the toplevel can *also* override subsubsubsubsubproject.bst directly from the toplevel06:14
tristanTwo questions stand: (A) Which override wins ? (answer should be the toplevel, but I think my code has a bug there)... (B) Are both junctioning projects allowed to specify duplicate/internal for that same project, and should they *both* be taken into consideration ?06:15
juergbiah, that's definitely an interesting aspect06:19
juergbiintuitively I'd be tempted to not allow overriding junctions via a path where the parent was already overridden06:19
juergbii.e., require those overrides to be configured for the overriding, not the overridden path06:20
juergbii.e., in your paste I'd forbid the second override line06:21
juergbiand require it to be specified as override in localsubsubsubproject.bst06:21
juergbiI haven't thought through this aspect, though, I might be missing something06:21
tristanI think it must be supported, not denied06:23
tristanAlthough your idea of denying it did immediately spring to mind06:23
tristanRationale is mostly that, I should be able to freely override things in my subproject hierarchy without needing to fork things06:24
tristanSo I should be able to override my subproject middleware with a different specialized/optimized middleware, which in turn also overrides some bsb or kernel or smth06:25
tristanBut from my toplevel project, I should *also* be able to override that kernel06:25
tristanwithout forking the middleware06:25
juergbitristan: I'm not saying to deny nested overrides in general06:26
tristanI mean, real world plausible usecases aside, the whole reason for supporting fullpaths in the keys (and values) of the overrides dictionary is to have this freedom to not force forking where it's not strictly needed06:26
juergbionly deny those where the parent (or generally, an ancestor) is already overridden06:27
juergbiand then you should still be able to override those via a non-overridden path without having to fork06:27
tristanYes, but if I have a hierarchy where I override deeply nested things, it stands to reason that a project might want to also include me as a junction, and also have the freedom to override the things I override06:27
tristanIn that top-toplevel view, I want to say override this shallow thing (which may have overridden a deeper thing), and also override that deep-deep-deep thing inside06:28
juergbiright, that's starting to get complex06:28
tristanWell, it's complex once06:28
tristanprojects can stack hundreds of layers high06:29
tristanaddressing a few layers vs hundreds has the same complexity (implementation-wise)06:29
juergbisure, I meant to think about :)06:30
tristanYes :)06:30
tristanSo I came to IRC to share the load :)06:30
tristanSo for implementing the overrides correctly, I am cooking up a test case and it's easy enough to solve06:30
tristanInstead of searching the closest parent for an override, I need to collect all overrides in the ancestry and choose the highest level one06:31
tristanThat's the easy part06:31
juergbiI fear that it can get very confusing to the user to see which overrides are actually in place06:32
tristanFor the duplicates/internal markers, I need to record *all* overrides in the walk, and say "The original parent, and all unchosen parents in the ancestry walk, are considered *alternative parents*"06:32
tristanThen, when I go ahead and check for duplicates/internal markers, I need to search every alternative parent for override markers06:32
juergbiwhen it gets complex to implement it often also gets complex for users to fully understand06:33
tristanfor it's specific pathing to that project06:33
tristanFor the user, absolute paths will always be displayed in the UI06:33
tristanAnd if there is a junction conflict error, we list every instance of projects, and every duplicate marking, including a lot of context06:34
tristanjuergbi, currently I have this: https://bpa.st/ZRTA06:35
tristanbut it could use a bit of polish06:35
tristanjuergbi, the (duplicated from 'project-name', loaded via 'full-junction-path') is in a loop06:35
tristanShowing every place a project was duplicated from06:35
juergbisuch provenance in error messages will definitely be very useful06:36
tristanFor the provenances shown, we should ensure that they always contain the full junction paths06:36
juergbihowever, I'm also worried about the case without errors06:37
tristanShould we also have something in the summary at the beginning of a build ?06:37
juergbimaybe allow showing the whole effective subproject structure of a pipeline06:38
tristanThe summary is currently *horribly broken*06:38
tristanit gets printed for every project we load, showing a lot of redundant information, revealing that we don't care at all about logging properly06:38
tristanIt's very embarrassing anyway06:39
tristanFrom the same test run, I have the following full stderr: https://bpa.st/NA7Q06:41
tristanjuergbi, Anyway, I would prefer to change the summary separately, I would suggest that we revert to only printing a single summary, and modify it to have a loop for all loaded projects06:44
juergbiwhat? that's a single bst invocation?06:44
tristanYes06:44
juergbithat's horrible06:45
tristanIt appears as if at some point, the loading of a project became some kind of callback that causes the frontend to print a summary06:45
juergbiseems that way06:45
tristanYes, it's disgusting, I can't believe we landed it to do that06:45
tristanAnyway, I would revert that but separately from the branch, give it a session of loving06:46
juergbireal testing probably mostly without junctions and in test cases you normally don't notice this06:46
tristanShow the active options for each project, and show the provenance of their junctions, and show any duplicate/override status, for each project loaded06:46
juergbiyes, I think that might be really helpful06:47
juergbinot sure whether provenance should be opt-in. might be too verbose06:47
tristanIn test cases you notice because, you are implementing a test case and probably asserting expected provenance of errors etc06:47
tristanOr seeing the test case fail06:47
tristanWell06:47
tristanMaybe we have a lot of tests which dont exercise junctions :)06:48
tristanWe only exercise them where we implement/test them (which makes sense)06:48
tristanjuergbi, I think provenance of each loaded project is important, and goes hand in hand with it's junction on the same line06:48
tristanIt's not all that much, unless you really do have hundreds of projects in depth06:49
tristanBut then you will have a huge summary anyway if you want to show them06:49
juergbifair enough06:49
juergbiwe also normally show the status of every element in the pipeline, right?06:49
tristanIn this sample, we don't get that far06:50
juergbithe number of junctions/subprojects should typically be way less than that06:50
tristanbecause this is a test of a load error06:50
juergbiright06:50
juergbiso as long as it's ok to print a line for every element, we sure can print a line for every subproject06:50
juergbi*surely06:50
tristanYes, definitely06:50
tristanI would have the pipeline completely at the end of the summary as originally implemented06:51
tristanSo it would flow { BuildStream version information, Invocation information and settings, Loaded projects (junctions), Pipeline of elements }06:52
tristanI think while being clear about all of this (showing duplicate/internal statuses as well), yes it may be complex for large projects but good enough for users to understand06:53
*** benschubert has joined #buildstream07:17
benschuberttristan: juergbi : I had an initial quick look yesterday around using threads for the jobs:07:22
benschubert- We can't do 'fine grained' async, as in we must run the entire job in a separate thread for now, as doing differently would require huge changes in the Messenger.07:22
benschubert- Apart from signal handling (I can't handle pause/terminate for now), it seems to work on a manual build, still need to look at the tests07:22
juergbisounds like a good start :)07:23
juergbiI assume proper signal handling is not impossible even though it may be non-trivial07:24
juergbiso I think it's really a better direction to explore than (extensive) pickling07:24
benschubertFor proper signal handling:07:29
benschubert- we have a helper for all subprocesses spawned, we "just" need to call it from the main process instead of the threads07:29
benschubert- For the threads themselves, it's trickier: We can't 'terminate' anymore, but we can cancel the job, which would raise a CancelledException, which unless caught will kill the thread. So as long as it's not caught we should be fine. And for pausing, I'm thinking if there is a way we could forcefully keep the gil or something like this (otherwise well... )07:29
benschubertand now the messenger needs to have thread-local variables07:29
benschubertbut yeah seems promising07:30
benschubertthe MR will be hard to make nice though07:30
juergbiOnly the frontend in the main process might actually make this easier07:30
juergbiBut that separation itself may not be trivial without fork07:31
juergbiAlthough, spawn might not be too bad for that when done at the right place07:32
juergbi(performance is still a question, though)07:32
juergbiWith the separation we could send SIGTSTP from the frontend to the core. handle SIGTSTP in the core to suspend all subprocesses and then suspend the core process itself (all threads)07:34
benschubertyep, that would be the ideal solution07:34
benschubertand I'm not too concerned about performance there as long as it's the backend that has all the state, the spawn would be once07:34
benschubertWe'll see what tristan can come up with on that one :)07:35
juergbimy performance comment was more about the separation of frontend and core into two processes in general07:35
juergbii.e., the messaging performance bottleneck that we saw with the separation experiment07:35
benschubertah true07:36
juergbior did rate limiting also solve it when the two parts are separated?07:36
benschubertif we rate limit from the backend it might work?07:36
juergbiwe just didn't need it anymore?07:36
juergbiit's possible07:36
benschubertnot sure I get you? The rate limiting is here, but it only limits the number of time we refresh the screen07:38
juergbiah, right07:39
juergbiI didn't remember where we rate limited07:39
juergbialso don't remember whether interactive shell still had some issues with separated frontend07:40
juergbiit's a somewhat tricky aspect07:40
juergbior at least might be07:40
tristanHmmm07:41
* tristan gets back from sandwich07:41
tristanbenschubert, I think that most of what we currently manually do for subprocesses from the main process can also be done at API entrypoints from plugins running in the main process07:42
tristanbenschubert, i.e. the context managers in _signals.py07:42
tristanIt does sound like you've made some good progress though :)07:42
benschubertyeah it's ugly though :'D07:43
tristanFor SIGTERM, could we not handle it from the main process and send SIGTERM to child processes ?07:43
tristani.e. whenever the plugin calls something that creates a child process, we certainly have the right to know about it07:43
benschuberttristan: child processes would be buildbox-run/casd/git/ssh etc, we do have them pauseable and that should not cause troubles07:43
benschubert(I have a bug in what I did that I need to fix in order for it to really work)07:44
benschubertbut yeah that  is fine07:44
benschubertwhat's more complex is for SIGTSTP, which means we want to pause the threads07:44
benschubertwhich we might force by keeping the GIL07:44
benschubertbut that's less than ideal07:44
tristanHmmm07:45
tristanbenschubert, I don't think it's important to pause the threads07:45
benschubertoh that simplifies a ton of things then :) If we are happy only pausing the sub processes then it is definitely doable07:46
tristanThis entire approach of running client code in the main process is hinged on the assumption that long standing work never happens in the main process07:46
benschuberttrue07:46
benschubertlet's hope no plugin will ever want to run a multiprocess in their plugin, otherwise it will be funky07:47
tristanIf that's true, the time from which a plugin should be paused until it reaches a function that would otherwise launch something and block should be negligible07:47
benschuberttrue07:47
tristanWe'll have to ensure that we block plugins from launching anything if they should be paused, of course07:47
benschubertthough if you _start_ a subprocess after being paused, the subprocess will not receive the message07:47
benschubertso we'd need a barrier07:47
benschubertah yep07:47
benschubertyeah we can easily add a barrier somewhere07:48
benschubertok ! I'll go back to it tonight probably and will see how far I can go07:48
tristanYeah but code which runs a subprocess in a plugin which does not pass though BuildStream API to do so, is just invalid plugin code07:48
tristanThen of course we get back into the can of worms which says "Hey, my plugin is written in Python, So I should be allowed to have python library dependencies... Right ?!?!?"07:48
* tristan doesnt like this argument07:49
tristanIf people are allowed to have third party python library dependencies, then we don't retain control over what plugins do, and they might launch unexpected subprocesses07:49
tristanalong with all the other problems third party library dependencies bring in07:49
benschubertyep07:49
benschubertwhich is acceptable if people understand what that implies07:50
tristanbenschubert, fwiw, we had an interesting conversation before you arrived... https://irclogs.baserock.org/buildstream/%23buildstream.2020-06-17.log.html#t2020-06-17T05:59:5107:54
tristanI think I have it under control... but e.g. consider: https://bpa.st/7FKA07:54
tristanbenschubert, this is regarding overriding subsubsubsubsubsubsubprojects inside subsubsubsubprojects, which already did override that subsubsubsubsubsubsubsubproject07:55
benschubertoh gosh07:55
tristanwho wins, and how to determine internal/duplicates regarding those, which references to count, etc07:56
tristanYeah :)07:56
tristanThought you'd enjoy that :)07:56
benschubert> i.e., require those overrides to be configured for the overriding, not the overridden path07:57
benschubertI think that is the most important point, junctions overrides should be applied recursively, so you'd be overriding the override instead of the junction directly07:57
benschubertfor the rest I'll have to read it with a bit more thoroughness to understand the output of it :)07:58
tristanyes you'd be overriding the overridden branch, but the tricky thing is that you can be overriding something which was already overridden by an intermediate project08:05
tristanon your way to reaching that project08:05
tristanSo when you search your ancestry for a junction which overrides you, you cannot stop at the nearest ancestor, there can be a greater grandparent which also overrides you08:06
tristanWhich also means that there can be multiple active override points which declare you to be 'internal' or 'duplicate'08:07
tristanIn fact, this situation can even arise without the double declaration described in https://bpa.st/7FKA08:07
benschubertyep, which means the loader code will take a hit and be quite complex :/08:09
tristanWell08:09
tristanIt's actually not that much08:09
tristanbenschubert, https://gitlab.com/BuildStream/buildstream/-/blob/tristan/junction-jungle/src/buildstream/_loader/loader.py#L59608:10
tristanbenschubert, That code has a bug as it currently is satisfied by the nearest ancestor08:11
benschuberttristan: and we only do that once per junction correct? Not everytime we reach one of their elements08:11
tristanIt needs to keep crawling the ancestry and find all override declarations, and use the highest level one08:11
tristanOnce per junction yes08:11
tristanOnly to resolve which junction to ultimately load08:11
benschubertah right, ok :)08:12
tristanThe other half is yet unimplemented, which is to preserve the relationship of alternative parents08:12
tristanSo that I can preserve the "duplicate" relationships of projects and junctions, when those "duplicate" junctions get overridden by some ancestor08:13
tristanThat has to be a list, not a single duplicate08:13
tristanWhen asserting duplicates, the more overrides you have, the more expensive that operation becomes indeed08:13
tristanYou need to collect duplicate-ness for any alternative parent (or 'overridden parent')08:13
benschubertbut that's once per junction so I'd expect this to be pretty cheap right?08:15
benschubertI mean compared to the rest of the loading08:15
tristanSo the resolution of "is this junction duplicated" needs to be done once per loaded instance of a given project08:16
tristanAnd the resolution of "is this junction duplicated" is then multiplied by the number of times that junction was overridden08:16
tristanAFAICS08:17
tristanI have been struggling to even get an algorithm which determines whether an overridden junction was duplicated working, but figuring out that I need to store the alternative parents is what lead me to realize this shortcoming and multi-override situation08:18
tristanThe resolution of "is this junction duplicated" itself, requires a Loader.get_loader() walk from the project which declares duplicates, too08:18
tristanbenschubert, https://gitlab.com/BuildStream/buildstream/-/blob/tristan/junction-jungle/src/buildstream/_project.py#L57208:19
benschuberttristan: yeah, that seems unfortunate, I don't have a better idea though, not sure how I can help, unless you have more specifics :)08:37
tristanLet me get working code out and revisit then08:43
tristanI'm personally very happy with the support for links08:44
tristanAnd I don't have better ideas at this point to optimize, but maybe there are caching possibilities I've missed08:44
tristanI also don't really expect this to be a hot codepath realistically08:44
*** santi has joined #buildstream08:48
benschubertyeah definitely08:49
benschubertlet's not optimize too early08:49
tristanFirst issue of overrides now has a test case and fixed... now on to preserving the relationship of duplicates for any overridden junctions09:01
*** hasebastian has quit IRC09:42
*** tristan has quit IRC10:15
WSalmonWe manged to find one of these odd failure in CI, douglaswinship traveltissues benschubert10:41
WSalmonhttps://gitlab.com/BuildStream/buildstream/-/issues/1341#note_36278512010:41
WSalmonbenschubert, my current gues as to the above is that a plugin is returning something from get_unique_key that is then making the cache key calculation go pop, dose that seem sensible?11:12
WSalmonim guessing there is a bug in the plugin and a bug in bst were it is not parsing the values from get_unique_key safely11:13
WSalmon?11:13
WSalmonit would be great if bst could at least say which plugins get_unique_key was causing the issue11:14
douglaswinshipAgreed, that would be _really_ useful for debugging.11:18
coldtomflatpak_image or flatpak_repo11:19
* coldtom hit this before11:19
douglaswinshipi think this one is a snap_image11:19
douglaswinshipsidebar: is there not a 1.93.4 tag for bst-plugins-experimental yet? Are we treating the 1.93.3 tag as being compatible with 1.93.4?11:20
douglaswinship*compatible with bst 1.93.411:21
douglaswinshipBack to the bug: I didn't look closely at the link. The one is clearly a flatpak thing, yes. I had the same issue on CI though, (the link that will posted in the comments). That's the one I think was a snap_image problem.11:23
WSalmonnarrowing it down two two plugins should give you a good start, but see if you can use bst show to be sure11:25
WSalmonwhich one11:25
WSalmonit could be both11:25
douglaswinshipI will :) just wrestling with venvs at the moment.11:25
WSalmon:)11:25
douglaswinshipwill DM you a question about the docker image11:25
coldtomit's flatpak_image11:26
WSalmonthere worth mastering11:26
*** hasebastian has joined #buildstream11:28
*** tristan has joined #buildstream11:44
*** ChanServ sets mode: +o tristan11:44
douglaswinshipHas anyone else had trouble with tab completion in 1.93.4? I had the same issue in 1.93.3. I get some python code crashing and throwing up a traceback any time I try to tab complete a bst command.11:51
douglaswinship"Cannot import name '__version__' from 'buildstream'"11:52
tristanHmmm, I've been reproducing this in `tox -e venv /bin/bash` but wasn't sure to blame buildstream or tox setup11:59
coldtomI've had that issue too12:03
douglaswinshipPretty sure it's caused by "6ef6be52 Replace format-version with min-version"12:17
tristanshould be easy to fix12:18
douglaswinshipFor me, the bug happens every time, after that commit. And never before that commit.12:18
douglaswinshipOr looks like, anyway)12:18
* tristan wonders which... douglaswinship or coldtom... will fix it first12:20
tristanready... set...12:20
tristanGo !12:20
douglaswinshipum.... I cheated. I've already started.12:21
douglaswinshipsorry coldtom :)12:21
douglaswinshipOkay, I don't really know enough to be confident yet, but src/buildsteam/_versions.py had two lines deleted: "BST_FORMAT_VERSION = 25" & "BST_FORMAT_VERSION_MIN = 18". That makes sense, if the whole commit was about removing the "BST_FORMAT_VERSION" variable from buildstream. But shouldn't they have been replaced with something relating to the "MIN_VERSION" variable?12:26
WSalmonthat dose look a lot like stuff tristan did..12:28
tristandouglaswinship, just not in the same commit, why, does autocompletion require knowledge of a min version or smth ?12:33
tristandouglaswinship, I'm thinking, either the import is unneeded, or it's changed location12:33
douglaswinshipyeah, i'm guessing i was wrong about '_versions.py'.12:34
douglaswinshipBut either way, i can't investigate any further for now. I've got to prioritize some other things, and I don't think I know enough to figure this out on my own anyway.12:35
tristanSweeeeeeeet12:44
tristanOverrides + Duplicate markings = Magic12:44
tristandouglaswinship, utils.py:get_bst_version() explains that __version__ is not resolved at bash complete time apparently12:48
tristandouglaswinship, I seem to have overlooked this when I wanted to make the default argument for `bst init` be the current version: https://gitlab.com/BuildStream/buildstream/-/blob/master/src/buildstream/_frontend/cli.py#L37412:50
tristanRemoving that function and perhaps defaulting to "2.0" or such could be a reasonable couple-line fix12:50
douglaswinshipSeems to work!12:52
douglaswinshipI assume you're suggesting that as a local fix? Not as something to actually merge into master?12:52
tristanI'm suggesting that as a fix for master yeah12:52
douglaswinshipAh, awesome.12:53
tristanIt's not really immensely important that the default be the current version12:53
tristanWould have been a bit prettier12:53
douglaswinshipStill, it's a shame to hard code a version number in, that people will have to remembe to update in future.12:53
tristanWell, its a function that has questionable value in the first place (`bst init`)12:54
tristanI expect most people who actually author projects will compose a project.conf12:54
tristanAnd maintaining a min-version is necessary12:54
tristan`min-version: 2.0` just means that you do not use any feature from BuildStream 2 that was introduced after 2.012:55
tristandouglaswinship, for the BuildStream side, we'll only really have to update it when BuildStream 3 comes out (unless people feel picky about that minute detail of a feature I guess)12:56
tristanBuildStream 3 I guess will ideally come out... never12:57
*** toscalix has joined #buildstream14:25
*** toscalix has quit IRC15:40
*** toscalix has joined #buildstream15:42
*** hasebastian has quit IRC16:33
*** toscalix has quit IRC17:01
*** santi has quit IRC17:02
douglaswinshipIs anyone familiar with the virtual directory code? I was taking a look and trying to figure out what kind of inputs "descend" will accept.17:03
douglaswinshipIt looks like you're expected to do "foo.descend(['bar', 'baz'])" (separating out the components of the path). So is the path is a variable, you have to do "path.split(os.sep)" first.17:03
douglaswinshipBut I was wondering if you can do "foo.descend(['bar/baz']). (Without splitting the string).17:03
douglaswinshipI took a look at the code in src/buildstream/storage/_filebaseddirectory.py, and it looks like it would actually accept 'bar/baz' as an input, but I don't think it would handle it properly.17:03
douglaswinshipI think the code would jump from the foo directory, straight to the foo/bar/baz directory in a single step. You'd end up with a directory object representing the 'foo/bar/baz' folder, but it would incorrectly list 'foo' as the parent directory, and skip over the 'foo/bar' directory completely.17:03
douglaswinshipMaybe there's a sanitizing step that i've overlooked? But if not, then I think there's a bug there.17:04
*** douglaswinship has quit IRC17:28
*** bethw has quit IRC17:31
*** traveltissues has quit IRC17:31
*** robjh has quit IRC17:31
*** WSalmon has quit IRC17:32
*** valentind has quit IRC17:32
*** robjh has joined #buildstream17:33
*** bethw has joined #buildstream17:34
jjardonsome good words for buildstream here: https://github.com/winepak/winepak-sdk-images/issues/45 :)17:36
*** valentind has joined #buildstream17:37
*** WSalmon has joined #buildstream17:37
*** xjuan has joined #buildstream18:19
*** xjuan has quit IRC23:00

Generated by irclog2html.py 2.15.3 by Marius Gedminas - find it at mg.pov.lt!