Bug 281574 - bc(1) runs in endless loop
Summary: bc(1) runs in endless loop
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 15.0-CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-09-18 16:50 UTC by Wolfram Schneider
Modified: 2024-09-20 16:51 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wolfram Schneider freebsd_committer freebsd_triage 2024-09-18 16:50:25 UTC
I killed a terminal with a running bc command. The terminal is gone, but bc(1) runs in an endless loop now:

top(1) output:
40325 wosch         1 135    0    13M  3332K CPU0     0   1:14  99.86% bc


ktrace -p 40325
kdump

 40325 bc       CALL  read(0,0x217008d92da8,0x1)
 40325 bc       GIO   fd 0 read 0 bytes
       ""
 40325 bc       RET   read 0
 40325 bc       CALL  ioctl(0,TIOCSETAW,0x3821a3c5b238)
 40325 bc       RET   ioctl -1 errno 25 Inappropriate ioctl for device
 40325 bc       CALL  sigprocmask(SIG_BLOCK,0x217008d92e58,0x217008d92e68)
 40325 bc       RET   sigprocmask 0
 40325 bc       CALL  ioctl(0,TIOCGWINSZ,0x217008d92e10)
 40325 bc       RET   ioctl -1 errno 25 Inappropriate ioctl for device
 40325 bc       CALL  sigprocmask(SIG_SETMASK,0x217008d92e68,0)
 40325 bc       RET   sigprocmask 0
 40325 bc       CALL  read(0,0x217008d92da8,0x1)
 40325 bc       GIO   fd 0 read 0 bytes
       ""
 40325 bc       RET   read 0
 40325 bc       CALL  ioctl(0,TIOCSETAW,0x3821a3c5b238)
 40325 bc       RET   ioctl -1 errno 25 Inappropriate ioctl for device
 40325 bc       CALL  sigprocmask(SIG_BLOCK,0x217008d92e58,0x217008d92e68)
 40325 bc       RET   sigprocmask 0
 40325 bc       CALL  ioctl(0,TIOCGWINSZ,0x217008d92e10)
 40325 bc       RET   ioctl -1 errno 25 Inappropriate ioctl for device
 40325 bc       CALL  sigprocmask(SIG_SETMASK,0x217008d92e68,0)
 40325 bc       RET   sigprocmask 0
 40325 bc       CALL  read(0,0x217008d92da8,0x1)
 40325 bc       GIO   fd 0 read 0 bytes


I tried to kill the process, but it worked only with SIGKILL and not SIGTERM/SIGHUP
kill -9 40325
Comment 1 Wolfram Schneider freebsd_committer freebsd_triage 2024-09-18 17:08:40 UTC
I see this on stable/13, stable14 and current, both amd64 and arm.

/usr/bin/bc --version
bc 7.0.1
Comment 2 Wolfram Schneider freebsd_committer freebsd_triage 2024-09-18 17:11:27 UTC
(In reply to Wolfram Schneider from comment #1)
the previous version is not affected (as on freefall right now)

/usr/bin/bc --version
bc 6.7.6
Comment 3 John F. Carr 2024-09-19 16:47:14 UTC
There is no obvious change to bc that would be responsible, but commit 8e022d3cdea10ee1039a632f670c27fd93f65625 changed the way yacc-generated programs process input.
Comment 4 John F. Carr 2024-09-20 16:51:20 UTC
I was looking in the wrong place for bc when I commented on the change history.  Source directory usr.bin/bc is not the one that is installed.  (That one also behaves oddly in response to ^D, probably due to the "error QUIT" rule in the grammar not causing it to quit.)

Here is what truss says when I type ^D to an older bc, version 5.2.2 or 6.7.6:

28787: ioctl(0,TIOCSETAW,0x75c7d3a5b264)         = 0 (0x0)
28787: read(0,"\^D",1)                           = 1 (0x1)
28787: fstat(1,{ mode=crw--w---- ,inode=96,size=0,blksize=4096 }) = 0 (0x0)
28787: ioctl(1,TIOCGETA,0x4c2f87f0125c)          = 0 (0x0)
28787: write(1,"^D",2)                           = 2 (0x2)
28787: ioctl(0,TIOCSETAW,0x75c7d3a5b238)         = 0 (0x0)
28787: write(1,"\n",1)                           = 1 (0x1)
28787: ioctl(0,TIOCSETAF,0x75c7d3a5b20c)         = 0 (0x0)
28787: exit(0x0)

All is well despite the odd behavior of a literal ^D being read.

If I have 7.0.1 then it does not quit and truss says

37822: ioctl(0,TIOCSETAW,0x88d4efe5b264)	 = 0 (0x0)
37822: read(0,"\^D",1)				 = 1 (0x1)
37822: fstat(1,{ mode=crw------- ,inode=45,size=0,blksize=4096 }) = 0 (0x0)
37822: ioctl(1,TIOCGETA,0x7ddad4152e7c)		 = 0 (0x0)
37822: write(1,"^D",2)				 = 2 (0x2)
37822: ioctl(0,TIOCSETAW,0x88d4efe5b238)	 = 0 (0x0)
37822: sigprocmask(SIG_BLOCK,{ SIGWINCH },{ })	 = 0 (0x0)
37822: ioctl(0,TIOCGWINSZ,0x7ddad4153100)	 = 0 (0x0)
37822: sigprocmask(SIG_SETMASK,{ },0x0)		 = 0 (0x0)
37822: ioctl(0,TIOCGETA,0x88d4efe5b290)		 = 0 (0x0)
37822: ioctl(0,TIOCSETAW,0x88d4efe5b264)