-
Notifications
You must be signed in to change notification settings - Fork 12
Description
Building of dictd failed in Fedora (https://bugzilla.redhat.com/2433984 and https://koji.fedoraproject.org/koji/taskinfo?taskID=141152566) with this error:
libtool --tag=CC --mode=compile gcc -c -DHAVE_CONFIG_H -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m32 -march=i686 -mtune=generic -msse2 -mfpmath=sse -mstackrealign -fasynchronous-unwind-tables -fstack-clash-protection -mtls-dialect=gnu -Wall -Wwrite-strings -Wcast-align -Wmissing-prototypes -Wshadow -Wnested-externs -Waggregate-return -DDICT_PLUGIN_PATH=\"/usr/libexec/\" -DDICT_DICTIONARY_PATH=\"/usr/share/\" -DDICT_VERSION=\"1.13.3\" -DDICT_CONFIG_PATH=\"/etc/\" -I. -I. dictd.c -o dictd.o
y.tab.c:132: error: unterminated #ifndef
servparse.y:34:12: warning: 'string2bool' defined but not used [-Wunused-function]
34 | static int string2bool (const char *str)
| ^~~~~~~~~~~
servparse.y:32:22: warning: 'db' defined but not used [-Wunused-variable]
32 | static dictDatabase *db;
| ^~
make: *** [Makefile:120: clientparse.o] Error 1
make: *** Waiting for unfinished jobs....
mv: cannot stat 'y.tab.h': No such file or directory
mv: cannot stat 'y.tab.c'
This looks like race condition in this Makefile rule:
clientparse.c clientparse.h: clientparse.y
$(YACC) -tdv $<; \
cmp -s y.tab.h clientparse.h || mv y.tab.h clientparse.h; \
cmp -s y.tab.c clientparse.c || mv y.tab.c clientparse.c; \
rm -f y.tab.h y.tab.cIn a parallel build, make sees that both clientparse.c and clientparse.h are missing. Because they are listed on the same line but generated by a command that produces fixed-name temporary files (y.tab.c/h), the following happens:
-
Multiple Processes: make may launch two separate sub-shells to satisfy the two targets simultaneously.
-
File Overwriting: Both sub-shells run yacc at the same time. One shell might be running
mv y.tab.c clientparse.cwhile the other shell'syaccprocess is still writing to y.tab.c. -
Truncated Files: The compiler (
gcc) starts readingclientparse.cwhile it is in an incomplete state (half-moved or half-written), leading to the unterminated#ifndeferror you saw.
If your yacc has -o option (e.g., GNU/Bison has it, and the OpenBSD one seems to have it as well, but it is not POSIX), then we could try something like:
# Replace the existing multi-line rules with these:
servparse.c servparse.h: servparse.y
$(YACC) -d -o servparse.c $<
clientparse.c clientparse.h: clientparse.y
$(YACC) -d -o clientparse.c $<With POSIX yacc and POSIX make (i.e., without pattern rules of GNU/Make), we could slightly more complicated way:
# 1. Define that the header depends on the C file
clientparse.h: clientparse.c
@if test ! -f $@; then \
rm -f clientparse.c; \
$(MAKE) clientparse.c; \
fi
# 2. The actual rule that runs YACC
clientparse.c: clientparse.y
$(YACC) -tdv $(srcdir)/clientparse.y
mv y.tab.h clientparse.h
mv y.tab.c clientparse.c
rm -f y.tab.h y.tab.cWhat do you think?