gittup/tup

Hard hang on Linux. Becomes unkillable. Leaves some directories unreadable. Requires a reboot to fix.

rheasman opened this issue · 4 comments

This has happened to me on two machines. In both cases I compiled tup from source.

This occurs with "tup 0.7.11", and with git master, "tup v0.7.11-46-ge8b8ce72".

It happens within 2 invocations on the attached directory structure, and once it happens, it happens 100% of the time after that. I have replicated this once on one machine and 4 times on the other. Funnily enough, it never happened when I tried tup --debug-fuse -d. It occurs on:

Ubuntu 22.04.2 LTS
Linux kernel: 5.15.0-73-generic #80-Ubuntu SMP Mon May 15 15:18:26 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

and

Ubuntu 18.04.6 LTS
Linux kernel: 4.15.0-211-generic #222-Ubuntu SMP Tue Apr 18 18:55:06 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Tup will hang and CTRL-C doesn't work. Attempting a kill -9 doesn't work.

image

If I open a new shell and poke around, the .tup directory hangs any command that attempts to show its contents.

Looking in my kernel messages, I see:

[1525624.738982] tup[88192]: segfault at 7fe2a13c9fb0 ip 0000556d588c024a sp 00007fe2a13c9fb0 error 6 in tup[556d588ad000+ba000]
[1525624.738991] Code: 2b 14 25 28 00 00 00 74 05 e8 92 e3 fe ff 48 83 c4 40 5b 5d 41 5c 41 5d 41 5e c3 41 56 41 55 41 54 55 53 48 81 ec 00 10 00 00 <48> 83 0c 24 00 48 83 ec 10 64 48 8b 04 25 28 00 00 00 48 89 84 24

This is my first time using tup, and I was trying to make a script that generates reasonable "-I" include directories for C compilation.

The tup files I created expect arm-none-eabi-gcc to be in your path. You can probably just create a symlink to a script that creates the .o or something, as I don't think this has anything to do with the compiler. If you do need the compiler, I am using arm-gnu-toolchain-12.2.mpacbti-rel1-x86_64-arm-none-eabi from https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

I was seeing this problem with a single Tuprules.tup and Tupfile file in src/hal/src, but I have included the most recent directory layout as that is what caused the crash last time, and I lost my original directory structure.

To replicate, it should be good enough to run tup inside the attached directory structure:
RJDongle.tar.gz

The attached tar is a basic "getting started" example project for some new hardware I am working on; please feel free to use it as you please.

I am happy to run any test code or whatever you would like, to track this down. I really dislike rebooting my machine, so perhaps a nice first step would be to make tup not require a reboot after crashing.

Ah. I see I can force unmount the offending fuse mount as root, and when I do, a segfault occurs. I set things up to get a core file, which I have attached. This is with release 0.7.11.

Core file:
core.zip

Oof, sorry you ran into this! FWIW you can try to unstick tup by force unmounting the .tup/mnt folder in another terminal. Eg:

$ sudo umount -f .tup/mnt
umount: /home/marf/test-rheasman-hang/RJDongle/.tup/mnt: target is busy.
 18) [0.001s] [build-debug] src/hal/documentation                                                                                                            
 [                  ETA~=<1s Remaining=18                   ]  68%^C^C^C^C^CSegmentation fault (core dumped)
$

The issue seems to be that tup doesn't handle an 'include_rules' directive from within a Tuprules.tup properly. The 'include_rules' should only go in a Tupfile. Within Tuprules.tup, I think it is just causing an infinite loop of re-including Tuprules.tup over and over until the stack blows out. I'll try to add a patch to protect that. In the meantime, simply removing 'include_rules' from all your Tuprules.tup files gets me past the parsing stage (and then failing because I don't have the arm compiler installed :)

Also I realize that this is purely stylistic, but a method of including headers that I enjoy is to pick a root for headers, which could be the src/ directory or whatever, and only add a -I for this directory (something like -I$(TUP_CWD) in src/Tuprules.tup there would work). Then all source files can include headers relative to that directory eg:

#include "hal/adc/hpl_adc_base.h"

instead of:

#include "hpl_adc_base.h"

and needing to put -I../../hal/adc in the compiler path. In my experience this makes it easier to find header files after looking at the source, and you need to edit the build description (Tupfiles) much more infrequently. The downside of course is slightly longer paths in the source file, but IMO the tradeoff is worth it.

Wow. Thanks for the fast response.

I agree with your suggestions about how include files should work. Sadly, over 99% the example project I uploaded is autogenerated by CPU vendor tools I use, and modifying any of the autogenerated files causes lots of other problems for me.

So, as usual, there are better ways to do it, but I have external dependencies that limit what I can do. Also, I have a large pile of other projects based on similar frameworks, and they are all using make at the moment, and the makefiles are just awful. I'm really hoping I can clean things up a bit by using tup.

I wanted to use -I flags relative to the project root, but that seemed a bit advanced for me right now, so all of my -I flags are relative to CWD. I haven't decided yet whether this will annoy me.

Thanks for the fast response, and a nifty program. I hope to use it a lot.