Weird code crash

Sep 14, 2023 Last reply: 2 years ago 70 Replies

I don't expect people to know the answer, but I could use some help in puzzling out where to look.



I had a power cut that did leave my network a bit sketchy and it took two reboots on this desktop to get back to normal. This may or may not be relevant.



But my question refers to my Pi Zero W server I am developing.



It came up, ok, but then after a while my relay daemon crashed...



Sep 13 11:26:36 heating-controller systemd[1]: relayd.service: Main process exit ed, code=killed, status=6/ABRT Sep 13 11:26:36 heating-controller systemd[1]: relayd.service: Failed with resul t 'signal'. Sep 13 11:26:36 heating-controller systemd[1]: relayd.service: Consumed



15.074s CPU time.

I rebooted it, and after awhile - about ten minutes, it happened again - that is the above trace.



I restarted it manually, and it hasn't crashed since.



The web is flooded with instances of this messaqe all on different platforms and applications, and it would appear this is a very generic message possibly to do with memory issues.



One person 'fixed' it by changing CPUs... Now *as far as I know* there was nothing special about the data the daemon would be operating on it this point to cause it to crash. I am fairly sure I have no memory leaks in it - in normal operation it strdups() and frees() and opens and closes files... and 'top' shows memory usage is rock steady.



One possibility is that it is opening and reading a file at the precise time another process is writing it...in both cases the read and write operations are atomic and done with C code.



READ ==== fp=fopen(fullname, "r"); len=fread(filbuf,1,255,fp); // read entire file



WRITE ===== fp=fopen(filename, "w"); if (fp) { fprintf(fp,"%s%s\n",filedata,timestamp); fclose(fp); }



Could this cause a problem?



I tend to suspect some sort of asynchronous timing issue because it is such a rare occurrence. I have been utterly unable to make it happen on demand...



Anything opened with fopen is a buffered stream operations on it are not atomic so yes it is very possible for the read to see a partially written file. To avoid the race you need to use some kind of locking.

Hmm.

Howver I think that for small operations one would have to posit a time between fopen() and fread() in which the file 'disappears' in some sense. Burt I 8thought* that a file handle once issued would not point to empty data, and that in fact fopen('w") would in fact create a new file and the old would not get unlinked until it was 'fclosed'

You're getting SIGABRT which is typically something bailing due to memory corruption, eg corrupting metadata so that malloc can't work, or a double-free.

I would compile it with debugging enabled: '-g' or '-ggdb' flag to your compiler. Then run it under gdb:

$ gdb ./myprog (gdb) run

and see if it dies. If it does you can get a backtrace to indicate where the fault occurred:

(gdb) bt

It may be that starting it under systemd is different in some way that it doesn't show up when running it by hand. You could try setting as your systemd command:

gdb -ex run -ex bt --args /usr/local/bin/myprog arg1 arg2

which will run it and then dump a backtrace when it's finished. You may get 'no stack' if it succeeded and didn't record one.

Theo

There’s no error checking on the call to fopen, so fp could be a null pointer when you call fread. So crashes are to be expected, although in this code fragment a SIGSEGV would be expected rather than SIGABRT.

Investigate properly first (see Theo’s post), guess about the cause later.

Nope - from man fopen

“w” Open for writing. The stream is positioned at the beginning of the file. Truncate the file to zero length if it exists or create the file if it does not exist.

The first try should be to check if the system runs fine from a backup memory card (you have it?).

It is fairly possible that the memory card has some flipped bits, and the effects are hard to predict.

--

-TV

Also:

  • I would also have a look at the kernel log; if it’s a kernel-generated signal then there’s usually a log message about it.

  • Run the application under valgrind; depending what the issue is, that will provide a backtrace and perhaps more detailed information. If it is a memory corruption issue then it may identify where the corruption happens, rather than the later point where malloc failed a consistency check (or whatever it is).

Using valgrind (and/or compiler sanitizer features) is a good idea even before running into trouble, really.

Ok, so there is a finite choice that an empty (zero length) file might be read. That is worth checking .

Nothing in kern.log after the boot process finishes.

The strange thing is that it failed once after a minute, then I rebooted and it failed after 20 minutes, and its been running several days now with no issues at all.

I am not sure valgrind would actually help unless it failed.

If you have coredumps enabled, you could also do coredumpctl debug to enter a gdb session of the last coredump that happened.

valgrind will tell you if it spots memory corruption, even if the corruption is not yet enough to cause it to crash. It may help in making the problem clearer and deterministic where the corruption makes it unpredictable.

Theo

I am wondering if the real reason is, that I trod on it. It is so utterly random that I am thinking that there may be a hardware issue like a cracked board. I wrecked the USB power socket for sure.

Well a new untrodden on Pi is not the bank breaker that it might be....

Thanks for all the helpful comments, but I am not ready to delve into reams of stack traces just yet.

I think watch and see and then maybe try another board.

  • The Natural Philosopher snipped-for-privacy@invalid.invalid | One possibility is that it is opening and reading a file at the | precise time another process is writing it...in both cases the read | and write | operations are atomic and done with C code.

| READ | ==== | fp=fopen(fullname, "r"); | len=fread(filbuf,1,255,fp); // read entire file

Check for fp != NULL is missing here in this example code before fread(). If this also in the production version, it might be a problem if the file is not accessible for any reason.

R'

Ralf, I already put that in this morning, re compiled the code and after an hour, it crashed again.

The filename is built by scanning a directory so the filename must exist.

The code runs as root, so there are no perms issues

I've put in checks to avoid trying to read empty files

I am leaning towards possibly a cracked solder joint or board.

Elsewhere in this thread it is suggested checking fp!=nul. Not knowing what the actual program is doing might I suggest also closing fp after it has been read.

I don't think it was a SIGSEGV error, but you should be doing this regardless.

Have you run fsck on the file system since the power loss? Make sure the fstab entry does not have a zero in the sixth field for the file system(s) in use. If using systemd, run dracut -f after any fstab changes. Then reboot.

Regards, Dave Hodgins

both already done. Not closng it was the cause of a memory leak but I fixed that a fortnight ago.

I am beginning to wonder if I did more damage than just the power socket when I trod on it.

I assumed that the thing would have done its own fsck on every boot anyway...isnt that a debian default?

(The sixth fields are 2 and 1 respectively for the file systems)

PARTUUID=b8c9fbb7-01 /boot vfat defaults 0 2 PARTUUID=b8c9fbb7-02 / ext4 defaults,noatime 0 1

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required