Add POSIX Pipe feature to VxWorks

VxWorks has POSIX pipe2 functions, but doesn't pass threadsafe-cloexec
because it doesn't have threadsafe-cloexec dup3. By default on VxWorks
POSIX pipes are used, but now it's possible to switch to PipeDrv
pipes using "configure -feature-vxpipedrv ...".
dup3 and accept4 test are now separated from threadsafe-cloexec test.

Task-number: QTBUG-132889
Pick-to: 6.8 6.9
Change-Id: I9e4514e2795917e8f3685a1760ea82a0022e9ca2
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Karim Pinter 2025-05-02 16:13:38 +03:00
parent 5ff542493d
commit 53756dcfbc
5 changed files with 87 additions and 16 deletions

View File

@ -132,6 +132,46 @@ int pipes[2];
}
")
# dup3
qt_config_compile_test(dup3
LABEL "dup3"
CODE
"#define _GNU_SOURCE 1
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
/* BEGIN TEST: */
(void) dup3(0, 3, O_CLOEXEC);
/* END TEST: */
return 0;
}
")
# acccept4
qt_config_compile_test(accept4
LABEL "accept4"
CODE
"#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
/* BEGIN TEST: */
#if defined(__NetBSD__)
(void) paccept(0, 0, 0, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK);
#else
(void) accept4(0, 0, 0, SOCK_CLOEXEC | SOCK_NONBLOCK);
#endif
/* END TEST: */
return 0;
}
")
# copy_file_range
qt_config_compile_test(copy_file_range
LABEL "copy_file_range()"
@ -866,6 +906,19 @@ qt_feature("threadsafe-cloexec"
)
qt_feature_definition("threadsafe-cloexec" "QT_THREADSAFE_CLOEXEC" VALUE "1")
qt_feature_config("threadsafe-cloexec" QMAKE_PUBLIC_QT_CONFIG)
qt_feature("dup3" PRIVATE
LABEL "dup3 support"
CONDITION TEST_dup3
)
qt_feature("accept4" PRIVATE
LABEL "accept4 support"
CONDITION TEST_accept4
)
qt_feature("vxpipedrv" PRIVATE
LABEL "Use pipedrv pipes on VxWorks"
AUTODETECT OFF
CONDITION VXWORKS
)
qt_feature("regularexpression" PUBLIC
SECTION "Kernel"
LABEL "QRegularExpression"

View File

@ -52,6 +52,7 @@
#define QT_NO_DATASTREAM
#define QT_FEATURE_datestring 1
#define QT_FEATURE_datetimeparser -1
#define QT_FEATURE_dup3 -1
#define QT_FEATURE_easingcurve -1
#define QT_FEATURE_etw -1
#define QT_FEATURE_futimens -1

View File

@ -270,7 +270,6 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07
#undef QT_OPEN
#define QT_OPEN qt_safe_open
#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
// don't call ::pipe
// call qt_safe_pipe
static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
@ -299,8 +298,6 @@ static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
#endif
}
#endif // Q_OS_VXWORKS
// don't call dup or fcntl(F_DUPFD)
static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
{
@ -328,7 +325,7 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
int ret;
#ifdef QT_THREADSAFE_CLOEXEC
#if QT_CONFIG(dup3)
// use dup3
QT_EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0));
return ret;

View File

@ -27,8 +27,16 @@ static constexpr bool UsingEventfd = true;
static constexpr bool UsingEventfd = false;
#endif
#if defined(Q_OS_VXWORKS)
#if defined(Q_OS_VXWORKS) && QT_CONFIG(vxpipedrv)
# include "qbytearray.h"
# include "qdatetime.h"
# include "qdir.h" // to get application name
# include "qrandom.h"
# include <pipeDrv.h>
# include <selectLib.h>
# include <taskLib.h>
# include <rtpLib.h>
# include <sysLib.h>
#endif
using namespace std::chrono;
@ -62,12 +70,12 @@ QThreadPipe::~QThreadPipe()
if (!UsingEventfd && fds[1] >= 0)
close(fds[1]);
#if defined(Q_OS_VXWORKS)
#if defined(Q_OS_VXWORKS) && QT_CONFIG(vxpipedrv)
pipeDevDelete(name, true);
#endif
}
#if defined(Q_OS_VXWORKS)
#if defined(Q_OS_VXWORKS) && QT_CONFIG(vxpipedrv)
static void initThreadPipeFD(int fd)
{
int ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
@ -88,20 +96,32 @@ bool QThreadPipe::init()
{
#if defined(Q_OS_WASM)
// do nothing.
#elif defined(Q_OS_VXWORKS)
std::snprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
#elif defined(Q_OS_VXWORKS) && QT_CONFIG(vxpipedrv)
RTP_DESC rtpStruct;
rtpInfoGet((RTP_ID)NULL, &rtpStruct);
QByteArray pipeName("/pipe/qevloop_");
QByteArray path(rtpStruct.pathName);
pipeName.append(path.mid(path.lastIndexOf(QDir::separator().toLatin1())+1, path.size()));
pipeName.append("_");
pipeName.append(QByteArray::number((uint)rtpStruct.entrAddr, 16));
pipeName.append("_");
pipeName.append(QByteArray::number((uint)QThread::currentThreadId(), 16));
pipeName.append("_");
QRandomGenerator rg(QTime::currentTime().msecsSinceStartOfDay());
pipeName.append(QByteArray::number(rg.generate()));
// make sure there is no pipe with this name
pipeDevDelete(name, true);
pipeDevDelete(pipeName, true);
// create the pipe
if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
perror("QThreadPipe: Unable to create thread pipe device");
if (pipeDevCreate(pipeName, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
qCritical("QThreadPipe: Unable to create thread pipe device %s : %s", name, std::strerror(errno));
return false;
}
if ((fds[0] = open(name, O_RDWR, 0)) < 0) {
perror("QThreadPipe: Unable to open pipe device");
if ((fds[0] = open(pipeName, O_RDWR, 0)) < 0) {
qCritical("QThreadPipe: Unable to open pipe device %s : %s", name, std::strerror(errno));
return false;
}
@ -150,7 +170,7 @@ int QThreadPipe::check(const pollfd &pfd)
if (readyread) {
// consume the data on the thread pipe so that
// poll doesn't immediately return next time
#if defined(Q_OS_VXWORKS)
#if defined(Q_OS_VXWORKS) && QT_CONFIG(vxpipedrv)
::read(fds[0], c, sizeof(c));
::ioctl(fds[0], FIOFLUSH, 0);
#else

View File

@ -73,7 +73,7 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add
Q_ASSERT((flags & ~O_NONBLOCK) == 0);
int fd;
#ifdef QT_THREADSAFE_CLOEXEC
#if QT_CONFIG(accept4)
// use accept4
int sockflags = SOCK_CLOEXEC;
if (flags & O_NONBLOCK)