Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175854368
ctty-last-close-repro.c
vova_fbsd.ru (Vova Grebenschikov)
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
vova_fbsd.ru
Tue, Oct 13, 10:14 PM
2026-10-13 22:14:53 (UTC+0)
Size
2 KB
Referenced Files
None
Subscribers
None
ctty-last-close-repro.c
View Options
/* SPDX-License-Identifier: BSD-2-Clause */
/* Tests Linux semantics; native FreeBSD may intentionally fail this test.
* cc -O2 -Wall -Wextra -Werror ctty-last-close-repro.c -o ctty-last-close-repro
*/
#define _GNU_SOURCE
#include
<sys/types.h>
#include
<sys/ioctl.h>
#include
<sys/wait.h>
#include
<errno.h>
#include
<fcntl.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<unistd.h>
static
void
setup_error
(
const
char
*
what
)
{
perror
(
what
);
_exit
(
2
);
}
int
main
(
void
)
{
int
master
,
status
;
pid_t
child
;
char
slave_name
[
256
];
setbuf
(
stdout
,
NULL
);
master
=
posix_openpt
(
O_RDWR
|
O_NOCTTY
);
if
(
master
<
0
)
setup_error
(
"posix_openpt"
);
if
(
grantpt
(
master
)
<
0
||
unlockpt
(
master
)
<
0
)
setup_error
(
"grantpt/unlockpt"
);
char
*
name
=
ptsname
(
master
);
if
(
name
==
NULL
)
setup_error
(
"ptsname"
);
if
(
strlen
(
name
)
>=
sizeof
(
slave_name
))
{
fprintf
(
stderr
,
"slave path too long
\n
"
);
return
2
;
}
strcpy
(
slave_name
,
name
);
child
=
fork
();
if
(
child
<
0
)
setup_error
(
"fork"
);
if
(
child
==
0
)
{
/* Parent keeps the master open until this process exits. */
close
(
master
);
if
(
setsid
()
<
0
)
setup_error
(
"setsid"
);
int
slave
=
open
(
slave_name
,
O_RDWR
|
O_NOCTTY
);
if
(
slave
<
0
)
setup_error
(
"open slave"
);
if
(
ioctl
(
slave
,
TIOCSCTTY
,
0
)
<
0
)
setup_error
(
"TIOCSCTTY"
);
int
tty
=
open
(
"/dev/tty"
,
O_RDWR
|
O_NOCTTY
);
if
(
tty
<
0
)
setup_error
(
"open /dev/tty before last close"
);
printf
(
"before last close: /dev/tty works
\n
"
);
if
(
close
(
tty
)
<
0
)
setup_error
(
"close /dev/tty"
);
/* No dup or stdio descriptors refer to this new slave. */
if
(
close
(
slave
)
<
0
)
setup_error
(
"close last slave"
);
tty
=
open
(
"/dev/tty"
,
O_RDWR
|
O_NOCTTY
);
if
(
tty
<
0
)
{
int
saved
=
errno
;
printf
(
"FAIL: /dev/tty after last slave close: errno=%d (%s)
\n
"
,
saved
,
strerror
(
saved
));
_exit
(
1
);
}
printf
(
"PASS: /dev/tty still opens after last slave close
\n
"
);
close
(
tty
);
_exit
(
0
);
}
while
(
waitpid
(
child
,
&
status
,
0
)
<
0
)
{
if
(
errno
!=
EINTR
)
setup_error
(
"waitpid"
);
}
close
(
master
);
if
(
!
WIFEXITED
(
status
))
{
fprintf
(
stderr
,
"child terminated by signal %d
\n
"
,
WTERMSIG
(
status
));
return
2
;
}
return
WEXITSTATUS
(
status
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40821688
Default Alt Text
ctty-last-close-repro.c (2 KB)
Attached To
Mode
D60701: devfs: Keep a Linux controlling tty across the last slave close
Attached
Detach File
Event Timeline
Log In to Comment