Re: [Interest] can't dump QStringList with qDebug()
On Tuesday, 7 March 2023 21:20:02 PST Hamish Moffatt via Interest wrote: > I confirm that my test code compiles in 6.5.0-beta3. And I can reproduce the error with GCC 13 if I check out the 6.4.2 headers. GCC 13 says: note: candidate: ‘template QDebugIfHasDebugStreamContainer, T> operator<<(QDebug, const QList&)’ note: template argument deduction/substitution failed qdebug.h:217:53: required by substitution of ‘template QDebugIfHasDebugStreamContainer, T> operator<<(QDebug, const QList&) [with T = QString]’ type_traits:2594:11: error: no type named ‘type’ in ‘struct std::enable_if’ This is GCC speak for "condition evaluated to false" By moving the constraint from the return type to a static_assert inside the function, I can prove that the ostream test fails: qdebug.h:219:5: error: static assertion failed due to requirement 'QTypeTraits::has_ostream_operator_v' But that test is: std::void_t() << detail::const_reference())> and if I copy that expression to the function, it does compile. Moreover, the changes to qdebug.h and qtypeinfo.h don't seem related. So I have no clue *why* the check fails and *how* it was fixed. This is template black magic. It works right now and I've spent enough time investigating. -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
On 8/3/23 14:45, Thiago Macieira wrote: On Tuesday, 7 March 2023 17:21:11 PST Hamish Moffatt via Interest wrote: I said gcc 10 earlier, but I meant to say clang 11. But I also see it in clang 14, and in VS 2019 (17.5.1 - latest). Cannot reproduce with those files with GCC 11, 12, 13 or Clang 15, all with Qt 6.6. Looking at the generated assembly, I can also see the compiler realised the list is always empty, so the loop from printSequentialContainer() disappears.f I confirm that my test code compiles in 6.5.0-beta3. thanks Hamish ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QML singleton properties are undefined if file placed in subdirectory
Maybe i did not cleary note at question: I placing all qml files related to module (main.qml, Style.qml) into "qml" subdirectory (it was working until i try to use singletons) If i add ".qml" to the URI then QQmlApplicationEngine fails to load component from either QUrl url1(u"qrc:/untitled/qml/main.qml"_qs), url2(u"qrc:/untitled/main.qml"_qs) CMakeLists.txt: ... qt_add_executable(untitled main.cpp ) set_source_files_properties(Style.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(untitled URI untitled.qml VERSION 1.0 QML_FILES qml/main.qml qml/Style.qml ) ... On Tue, Mar 7, 2023 at 2:55 PM Ulf Hermann via Interest < interest@qt-project.org> wrote: > > Qt 6.4.2 QML singleton's properties undefined if singleton QML file > > placed in subdirectory e.g "/qml" (${CMAKE_SOURCE_DIR}/qml/Style.qml) > > You should not place your QML files in a different directory than the > module (as denoted by the generated qmldir file). Otherwise their > implicit import is not the same as the module they belong to, which then > leads to effects like this. > > The implicit import is the way you can use QML components placed in .qml > files in the same directory without importing anything. > > The component in question is a singleton in the module since it has a > "singleton" line in the qmldir. It is, however, a regular non-singleton > component in the implicit import since the implicit import does not see > the qmldir. > > You can move the whole QML module into the "qml" subdirectory and add > ".qml" to the URI to avoid this. Or you can move all the .qml files into > the base directory of the module. > > best regards, > Ulf > ___ > Interest mailing list > Interest@qt-project.org > https://lists.qt-project.org/listinfo/interest > ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
On Tuesday, 7 March 2023 17:21:11 PST Hamish Moffatt via Interest wrote: > I said gcc 10 earlier, but I meant to say clang 11. But I also see it in > clang 14, and in VS 2019 (17.5.1 - latest). Cannot reproduce with those files with GCC 11, 12, 13 or Clang 15, all with Qt 6.6. Looking at the generated assembly, I can also see the compiler realised the list is always empty, so the loop from printSequentialContainer() disappears.f -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
I really want to thank Björn With his starting point, I was able to tweak his changes, and seem to have it working 😊 I have more testing to do. But it was actually pretty straight forward. * I use VS (2022) so the packing was different __attribute__((packed)) became __pragma( pack( push, 1 ) ) struct HackedHandlePasser * The handles are 64 bit in the existing Startup Info, so I kept them as such, which changed the definition of HANDLE32 using HANDLE32 = std::int32_t; was removed, and the standard HANDLE defined in windows.h was used * The static assert was updated to reflect this * I copy all 3 handles from the existing startupinfo std::memcpy(&handles.Handles[0], &invalid, 4); std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); became std::memcpy( &handles.Handles[ 0 ], &args->startupInfo->hStdInput, sizeof( HANDLE ) ); std::memcpy( &handles.Handles[ 1 ], &args->startupInfo->hStdOutput, sizeof( HANDLE ) ); std::memcpy( &handles.Handles[ 2 ], &args->startupInfo->hStdError, sizeof( HANDLE ) ); Then I wrapped this into a function that returns a QProcess::QCreateProcessArgumentModifier. And finally in my process, I set the modifier using process-> setCreateProcessArgumentsModifier( func ); You can find the code https://github.com/towel42-com/SABUtils/blob/trunk/ForceUnbufferedProcessModifier.h and https://github.com/towel42-com/SABUtils/blob/trunk/ForceUnbufferedProcessModifier.cpp and its usage at https://github.com/towel42-com/MediaManager/blob/trunk/Models/DirModel.cpp Thanks again. Scott -Original Message- From: Scott Bloom Sent: Tuesday, March 7, 2023 5:34 PM To: Scott Bloom ; Björn Schäpers ; interest@qt-project.org Subject: RE: [Interest] QProcess unbuffered Yeah, Im being dense.. its from the existing startupinfo.. I read that paragraph a dozen times and missed it each time -Original Message- From: Interest On Behalf Of Scott Bloom Sent: Tuesday, March 7, 2023 5:28 PM To: Björn Schäpers ; interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered Maybe Im being dense (its been a long day) But where is pipe defined ? std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); -- Scott -Original Message- From: Björn Schäpers Sent: Tuesday, March 7, 2023 12:58 PM To: Scott Bloom ; interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered So here is what I have: struct __attribute__((packed)) HackedHandlePasser { using HANDLE32 = std::int32_t; DWORD NumberOfHandles = 3; // 4 Byte BYTE FlagsPerHandle[3]; // 3 * 1 Byte HANDLE32 Handles[3]; // 3 * 4 Byte }; static_assert(sizeof(HackedHandlePasser) == 19); HackedHandlePasser handles; #ifndef FOPEN #define FOPEN 0x01 #endif #ifndef FDEV #define FDEV 0x40 #endif handles.FlagsPerHandle[0] = 0; std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); const HANDLE invalid = INVALID_HANDLE_VALUE; std::memcpy(&handles.Handles[0], &invalid, 4); std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); startInf.cbReserved2 = sizeof(HackedHandlePasser); startInf.lpReserved2 = reinterpret_cast(&handles); Some explanations: * I have the HANDLE32 because I start a 32 bit application from within a 64 bit, as far as I understood the structure needs the right HANDLE size, thus for a 64 bit application it should be std:int64_t, but since I don't need that I never tested it. * In cbReserved2 there is the size of the data in lpReserved2. * The data in lpReserved2 starts with 2 bytes which indicate how many handles are passed to the spawned process (they may be INVALID_HANDLE_VALUE). Followed by one byte per handle with the opened flags - and here comes the trick: If it has the flag FDEV the ms runtime printf assumes it writes to a console and thus flushes. And then followed by the handles. * My use case needs only stdout (and I also open stderr, in my case to the same handle), these are the handles number 1 and 2. Number 0 would be stdin. So when using it with QProcess I think one should copy the handles from the STARTUPINFOW structure into this struct, then I think the normal QIODevice interface should keep working. If one should clear the STARTF_USESTDHANDLES flag I also don't know. I stopped my experiments when I achieved success for my "simple" use case. Let me know what works for you. And last but not least some sources: https://stackoverflow.com/questions/40965496/windows-how-to-stop-buffering-of-redirected-stdout-using-createprocess which apparently now also has a C/C++ answer, when I needed it there was only the python code. http://www.catch22.net/tuts/undocumented-createprocess does use the fields
Re: [Interest] QProcess unbuffered
Yeah, Im being dense.. its from the existing startupinfo.. I read that paragraph a dozen times and missed it each time -Original Message- From: Interest On Behalf Of Scott Bloom Sent: Tuesday, March 7, 2023 5:28 PM To: Björn Schäpers ; interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered Maybe Im being dense (its been a long day) But where is pipe defined ? std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); -- Scott -Original Message- From: Björn Schäpers Sent: Tuesday, March 7, 2023 12:58 PM To: Scott Bloom ; interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered So here is what I have: struct __attribute__((packed)) HackedHandlePasser { using HANDLE32 = std::int32_t; DWORD NumberOfHandles = 3; // 4 Byte BYTE FlagsPerHandle[3]; // 3 * 1 Byte HANDLE32 Handles[3]; // 3 * 4 Byte }; static_assert(sizeof(HackedHandlePasser) == 19); HackedHandlePasser handles; #ifndef FOPEN #define FOPEN 0x01 #endif #ifndef FDEV #define FDEV 0x40 #endif handles.FlagsPerHandle[0] = 0; std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); const HANDLE invalid = INVALID_HANDLE_VALUE; std::memcpy(&handles.Handles[0], &invalid, 4); std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); startInf.cbReserved2 = sizeof(HackedHandlePasser); startInf.lpReserved2 = reinterpret_cast(&handles); Some explanations: * I have the HANDLE32 because I start a 32 bit application from within a 64 bit, as far as I understood the structure needs the right HANDLE size, thus for a 64 bit application it should be std:int64_t, but since I don't need that I never tested it. * In cbReserved2 there is the size of the data in lpReserved2. * The data in lpReserved2 starts with 2 bytes which indicate how many handles are passed to the spawned process (they may be INVALID_HANDLE_VALUE). Followed by one byte per handle with the opened flags - and here comes the trick: If it has the flag FDEV the ms runtime printf assumes it writes to a console and thus flushes. And then followed by the handles. * My use case needs only stdout (and I also open stderr, in my case to the same handle), these are the handles number 1 and 2. Number 0 would be stdin. So when using it with QProcess I think one should copy the handles from the STARTUPINFOW structure into this struct, then I think the normal QIODevice interface should keep working. If one should clear the STARTF_USESTDHANDLES flag I also don't know. I stopped my experiments when I achieved success for my "simple" use case. Let me know what works for you. And last but not least some sources: https://stackoverflow.com/questions/40965496/windows-how-to-stop-buffering-of-redirected-stdout-using-createprocess which apparently now also has a C/C++ answer, when I needed it there was only the python code. http://www.catch22.net/tuts/undocumented-createprocess does use the fields for some other stuff, but explains a bit of background. https://github.com/cansou/msvcrt/blob/master/src/isatty.c One if the involved files to handle the input. Kind Regards, Björn. ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
Maybe Im being dense (its been a long day) But where is pipe defined ? std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); -- Scott -Original Message- From: Björn Schäpers Sent: Tuesday, March 7, 2023 12:58 PM To: Scott Bloom ; interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered So here is what I have: struct __attribute__((packed)) HackedHandlePasser { using HANDLE32 = std::int32_t; DWORD NumberOfHandles = 3; // 4 Byte BYTE FlagsPerHandle[3]; // 3 * 1 Byte HANDLE32 Handles[3]; // 3 * 4 Byte }; static_assert(sizeof(HackedHandlePasser) == 19); HackedHandlePasser handles; #ifndef FOPEN #define FOPEN 0x01 #endif #ifndef FDEV #define FDEV 0x40 #endif handles.FlagsPerHandle[0] = 0; std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); const HANDLE invalid = INVALID_HANDLE_VALUE; std::memcpy(&handles.Handles[0], &invalid, 4); std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); startInf.cbReserved2 = sizeof(HackedHandlePasser); startInf.lpReserved2 = reinterpret_cast(&handles); Some explanations: * I have the HANDLE32 because I start a 32 bit application from within a 64 bit, as far as I understood the structure needs the right HANDLE size, thus for a 64 bit application it should be std:int64_t, but since I don't need that I never tested it. * In cbReserved2 there is the size of the data in lpReserved2. * The data in lpReserved2 starts with 2 bytes which indicate how many handles are passed to the spawned process (they may be INVALID_HANDLE_VALUE). Followed by one byte per handle with the opened flags - and here comes the trick: If it has the flag FDEV the ms runtime printf assumes it writes to a console and thus flushes. And then followed by the handles. * My use case needs only stdout (and I also open stderr, in my case to the same handle), these are the handles number 1 and 2. Number 0 would be stdin. So when using it with QProcess I think one should copy the handles from the STARTUPINFOW structure into this struct, then I think the normal QIODevice interface should keep working. If one should clear the STARTF_USESTDHANDLES flag I also don't know. I stopped my experiments when I achieved success for my "simple" use case. Let me know what works for you. And last but not least some sources: https://stackoverflow.com/questions/40965496/windows-how-to-stop-buffering-of-redirected-stdout-using-createprocess which apparently now also has a C/C++ answer, when I needed it there was only the python code. http://www.catch22.net/tuts/undocumented-createprocess does use the fields for some other stuff, but explains a bit of background. https://github.com/cansou/msvcrt/blob/master/src/isatty.c One if the involved files to handle the input. Kind Regards, Björn. ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
On 8/3/23 04:15, Thiago Macieira wrote: On Monday, 6 March 2023 22:15:01 PST Hamish Moffatt via Interest wrote: ../../../../Qt6.4.2/6.4.2/gcc_64/include/QtCore/qdebug.h:217:53: note: candidate template ignored: requirement 'std::conjunction_v, QString>, QTypeTraits::has_ostream_operator>>' was not satisfied [with T = QString] This is the expected template and the compiler told us why it couldn't expand: it thinks that the QDebugIfHasDebugStreamContainer condition wasn't satisfied. That condition is std::is_base_of OR QTypeTraits::has_ostream_operator Obviously, QStringList is not a base class of QString; we're expecting the second check to be true, that there's an output streaming operator for QDebug- QString That of course is there; it's in QDebug itself. So my conclusion is that your compiler has a bug and improperly parsed the C++ code. Does this problem happen with GCC 11 or 12? I said gcc 10 earlier, but I meant to say clang 11. But I also see it in clang 14, and in VS 2019 (17.5.1 - latest). It seems to be related to #including the moc output in the cpp file. Here's a minimal example: Header file: #pragma once #include #include namespace TServer { class Test : public QObject { Q_OBJECT private: void test(); signals: void databaseOpened(QString schoolCode); void databaseEvent(QString schoolCode, QString notification); void databaseRemoved(QString schoolCode, QString dbFilename); }; } Source file: #include "server_database2.h" #include #include void TServer::Test::test() { qDebug() << QStringList{}; } Hamish ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
-Original Message- From: Interest On Behalf Of Thiago Macieira Sent: Tuesday, March 7, 2023 2:40 PM To: interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered On Tuesday, 7 March 2023 14:23:00 PST Björn Schäpers wrote: > From the code I reviewed back then (and remember it now) it unpacks > the handles directly to a HANDLE, which is pointer size (although it > only uses the lower 32 bit). But Scott will tell us what the field > width has to be for a 64 bit process. Yup. BTW, Scott, when using QProcess::setCreateProcessArgumentsModifier(), you get access to QProcess' standard handles so you can place them in your fd table. Björn's code probably predates that function (Qt 5.7). Just getting to play with it now... Thanks for looking at this. ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
On Tuesday, 7 March 2023 14:23:00 PST Björn Schäpers wrote: > From the code I reviewed back then (and remember it now) it unpacks the > handles directly to a HANDLE, which is pointer size (although it only uses > the lower 32 bit). But Scott will tell us what the field width has to be > for a 64 bit process. Yup. BTW, Scott, when using QProcess::setCreateProcessArgumentsModifier(), you get access to QProcess' standard handles so you can place them in your fd table. Björn's code probably predates that function (Qt 5.7). -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
That's right. It depends on the runtime, but I have not seen a process which uses not a Microsoft provided runtime (of course I didn't check all the programs I used). And that's all I've found. It serves my purposes to the fullest. From the code I reviewed back then (and remember it now) it unpacks the handles directly to a HANDLE, which is pointer size (although it only uses the lower 32 bit). But Scott will tell us what the field width has to be for a 64 bit process. Am 07.03.2023 um 23:06 schrieb Thiago Macieira: [quoting out of order] On Tuesday, 7 March 2023 12:57:59 PST Björn Schäpers wrote: startInf.cbReserved2 = sizeof(HackedHandlePasser); startInf.lpReserved2 = reinterpret_cast(&handles); These reserved fields are how the runtimes "pass file descriptors" to child processes. This mimics the Unix fork() behaviour that the parent's open file descriptors are available in the child, without implementing the full fork() behaviour. The fields are undocumented (AFAIK) but since both msvcrt and ucrt depend on the specific behaviours, they can't change. That includes these bit fields for flags: #ifndef FOPEN #define FOPEN 0x01 #endif #ifndef FDEV #define FDEV 0x40 #endif handles.FlagsPerHandle[0] = 0; std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); According to the UCRT source code, the FDEV flag controls whether the standard streams will be buffered or not. The UCRT implementation of isatty() is a check to see if this flag is set. The UCRT source code isn't complete (ucrtbase isn't included AFAICS), so I couldn't find all details when trying to give you a more specific answer. * I have the HANDLE32 because I start a 32 bit application from within a 64 bit, as far as I understood the structure needs the right HANDLE size, thus for a 64 bit application it should be std:int64_t, but since I don't need that I never tested it. The parent process wouldn't know whether the child is 32-bit or not, so I imagine the size must be fixed at 32 bits in order to be inheritable. If you have MSVC, you have access to the UCRT source code too and you can search for those two reserved fields to see if they hardcode to 32-bit or pointer sizes. So when using it with QProcess I think one should copy the handles from the STARTUPINFOW structure into this struct, then I think the normal QIODevice interface should keep working. If one should clear the STARTF_USESTDHANDLES flag I also don't know. I stopped my experiments when I achieved success for my "simple" use case. QProcess uses CreateProcessW directly, not the _spawnv* CRT family of functions, which is why file descriptors aren't usually inherited via QProcess. I don't know either whether the STARTF_USESTDHANDLES flag must be cleared because they're handled at separate times. If this flag is passed, then the three handles in STARTUPINFO[1] are passed to the child as its default handles, by the Win32 call itself. That means those handles are installed in the child before the runtime gets a chance to initialise and read the file descriptor table passed in those reserved fields. Whether the runtime overwrites the standard file descriptors or not, I couldn't find in the UCRT sources. And for the same reason, I can't tell either how the FDEV flag is set for the standard file descriptors from outside the file descriptor table. Moreover, please note that this is *runtime* -driven behaviour, not OS- mandated. So it's entirely possible that this executable that Scott wants to run operates differently because it uses a weird runtime. (Strictly speaking, it's the same on Unix systems, but all libcs have the same behaviour) [1] https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
[quoting out of order] On Tuesday, 7 March 2023 12:57:59 PST Björn Schäpers wrote: >startInf.cbReserved2 = sizeof(HackedHandlePasser); >startInf.lpReserved2 = reinterpret_cast(&handles); These reserved fields are how the runtimes "pass file descriptors" to child processes. This mimics the Unix fork() behaviour that the parent's open file descriptors are available in the child, without implementing the full fork() behaviour. The fields are undocumented (AFAIK) but since both msvcrt and ucrt depend on the specific behaviours, they can't change. That includes these bit fields for flags: >#ifndef FOPEN > #define FOPEN 0x01 >#endif >#ifndef FDEV > #define FDEV 0x40 >#endif > >handles.FlagsPerHandle[0] = 0; >std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); According to the UCRT source code, the FDEV flag controls whether the standard streams will be buffered or not. The UCRT implementation of isatty() is a check to see if this flag is set. The UCRT source code isn't complete (ucrtbase isn't included AFAICS), so I couldn't find all details when trying to give you a more specific answer. > * I have the HANDLE32 because I start a 32 bit application from within a 64 > bit, as far as I understood the structure needs the right HANDLE size, thus > for a 64 bit application it should be std:int64_t, but since I don't need > that I never tested it. The parent process wouldn't know whether the child is 32-bit or not, so I imagine the size must be fixed at 32 bits in order to be inheritable. If you have MSVC, you have access to the UCRT source code too and you can search for those two reserved fields to see if they hardcode to 32-bit or pointer sizes. > So when using it with QProcess I think one should copy the handles from the > STARTUPINFOW structure into this struct, then I think the normal QIODevice > interface should keep working. If one should clear the STARTF_USESTDHANDLES > flag I also don't know. I stopped my experiments when I achieved success > for my "simple" use case. QProcess uses CreateProcessW directly, not the _spawnv* CRT family of functions, which is why file descriptors aren't usually inherited via QProcess. I don't know either whether the STARTF_USESTDHANDLES flag must be cleared because they're handled at separate times. If this flag is passed, then the three handles in STARTUPINFO[1] are passed to the child as its default handles, by the Win32 call itself. That means those handles are installed in the child before the runtime gets a chance to initialise and read the file descriptor table passed in those reserved fields. Whether the runtime overwrites the standard file descriptors or not, I couldn't find in the UCRT sources. And for the same reason, I can't tell either how the FDEV flag is set for the standard file descriptors from outside the file descriptor table. Moreover, please note that this is *runtime* -driven behaviour, not OS- mandated. So it's entirely possible that this executable that Scott wants to run operates differently because it uses a weird runtime. (Strictly speaking, it's the same on Unix systems, but all libcs have the same behaviour) [1] https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
Thanks. Ill take a look and see what I can workup, including the testing of 64 bit (I no longer build 32 bit windows, so any changes will have the opposite of your issues) Scott -Original Message- From: Björn Schäpers Sent: Tuesday, March 7, 2023 12:58 PM To: Scott Bloom ; interest@qt-project.org Subject: Re: [Interest] QProcess unbuffered So here is what I have: struct __attribute__((packed)) HackedHandlePasser { using HANDLE32 = std::int32_t; DWORD NumberOfHandles = 3; // 4 Byte BYTE FlagsPerHandle[3]; // 3 * 1 Byte HANDLE32 Handles[3]; // 3 * 4 Byte }; static_assert(sizeof(HackedHandlePasser) == 19); HackedHandlePasser handles; #ifndef FOPEN #define FOPEN 0x01 #endif #ifndef FDEV #define FDEV 0x40 #endif handles.FlagsPerHandle[0] = 0; std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); const HANDLE invalid = INVALID_HANDLE_VALUE; std::memcpy(&handles.Handles[0], &invalid, 4); std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); startInf.cbReserved2 = sizeof(HackedHandlePasser); startInf.lpReserved2 = reinterpret_cast(&handles); Some explanations: * I have the HANDLE32 because I start a 32 bit application from within a 64 bit, as far as I understood the structure needs the right HANDLE size, thus for a 64 bit application it should be std:int64_t, but since I don't need that I never tested it. * In cbReserved2 there is the size of the data in lpReserved2. * The data in lpReserved2 starts with 2 bytes which indicate how many handles are passed to the spawned process (they may be INVALID_HANDLE_VALUE). Followed by one byte per handle with the opened flags - and here comes the trick: If it has the flag FDEV the ms runtime printf assumes it writes to a console and thus flushes. And then followed by the handles. * My use case needs only stdout (and I also open stderr, in my case to the same handle), these are the handles number 1 and 2. Number 0 would be stdin. So when using it with QProcess I think one should copy the handles from the STARTUPINFOW structure into this struct, then I think the normal QIODevice interface should keep working. If one should clear the STARTF_USESTDHANDLES flag I also don't know. I stopped my experiments when I achieved success for my "simple" use case. Let me know what works for you. And last but not least some sources: https://stackoverflow.com/questions/40965496/windows-how-to-stop-buffering-of-redirected-stdout-using-createprocess which apparently now also has a C/C++ answer, when I needed it there was only the python code. http://www.catch22.net/tuts/undocumented-createprocess does use the fields for some other stuff, but explains a bit of background. https://github.com/cansou/msvcrt/blob/master/src/isatty.c One if the involved files to handle the input. Kind Regards, Björn. ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QProcess unbuffered
So here is what I have: struct __attribute__((packed)) HackedHandlePasser { using HANDLE32 = std::int32_t; DWORD NumberOfHandles = 3; // 4 Byte BYTE FlagsPerHandle[3]; // 3 * 1 Byte HANDLE32 Handles[3]; // 3 * 4 Byte }; static_assert(sizeof(HackedHandlePasser) == 19); HackedHandlePasser handles; #ifndef FOPEN #define FOPEN 0x01 #endif #ifndef FDEV #define FDEV 0x40 #endif handles.FlagsPerHandle[0] = 0; std::memset(&handles.FlagsPerHandle[1], FOPEN | FDEV, 2); const HANDLE invalid = INVALID_HANDLE_VALUE; std::memcpy(&handles.Handles[0], &invalid, 4); std::memcpy(&handles.Handles[1], &pipe.Write, 4); std::memcpy(&handles.Handles[2], &pipe.Write, 4); startInf.cbReserved2 = sizeof(HackedHandlePasser); startInf.lpReserved2 = reinterpret_cast(&handles); Some explanations: * I have the HANDLE32 because I start a 32 bit application from within a 64 bit, as far as I understood the structure needs the right HANDLE size, thus for a 64 bit application it should be std:int64_t, but since I don't need that I never tested it. * In cbReserved2 there is the size of the data in lpReserved2. * The data in lpReserved2 starts with 2 bytes which indicate how many handles are passed to the spawned process (they may be INVALID_HANDLE_VALUE). Followed by one byte per handle with the opened flags - and here comes the trick: If it has the flag FDEV the ms runtime printf assumes it writes to a console and thus flushes. And then followed by the handles. * My use case needs only stdout (and I also open stderr, in my case to the same handle), these are the handles number 1 and 2. Number 0 would be stdin. So when using it with QProcess I think one should copy the handles from the STARTUPINFOW structure into this struct, then I think the normal QIODevice interface should keep working. If one should clear the STARTF_USESTDHANDLES flag I also don't know. I stopped my experiments when I achieved success for my "simple" use case. Let me know what works for you. And last but not least some sources: https://stackoverflow.com/questions/40965496/windows-how-to-stop-buffering-of-redirected-stdout-using-createprocess which apparently now also has a C/C++ answer, when I needed it there was only the python code. http://www.catch22.net/tuts/undocumented-createprocess does use the fields for some other stuff, but explains a bit of background. https://github.com/cansou/msvcrt/blob/master/src/isatty.c One if the involved files to handle the input. Kind Regards, Björn. ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
On Monday, 6 March 2023 22:15:01 PST Hamish Moffatt via Interest wrote: > ../../../../Qt6.4.2/6.4.2/gcc_64/include/QtCore/qdebug.h:217:53: note: > candidate template ignored: requirement > 'std::conjunction_v, > QString>, QTypeTraits::has_ostream_operator>>' was > not satisfied [with T = QString] This is the expected template and the compiler told us why it couldn't expand: it thinks that the QDebugIfHasDebugStreamContainer condition wasn't satisfied. That condition is std::is_base_of OR QTypeTraits::has_ostream_operator Obviously, QStringList is not a base class of QString; we're expecting the second check to be true, that there's an output streaming operator for QDebug- QString That of course is there; it's in QDebug itself. So my conclusion is that your compiler has a bug and improperly parsed the C++ code. Does this problem happen with GCC 11 or 12? -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] QML singleton properties are undefined if file placed in subdirectory
Qt 6.4.2 QML singleton's properties undefined if singleton QML file placed in subdirectory e.g "/qml" (${CMAKE_SOURCE_DIR}/qml/Style.qml) You should not place your QML files in a different directory than the module (as denoted by the generated qmldir file). Otherwise their implicit import is not the same as the module they belong to, which then leads to effects like this. The implicit import is the way you can use QML components placed in .qml files in the same directory without importing anything. The component in question is a singleton in the module since it has a "singleton" line in the qmldir. It is, however, a regular non-singleton component in the implicit import since the implicit import does not see the qmldir. You can move the whole QML module into the "qml" subdirectory and add ".qml" to the URI to avoid this. Or you can move all the .qml files into the base directory of the module. best regards, Ulf ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
Hi, I'm sure you have already tried it, but just a wild guess: do you have #include in this .cpp file? Cheers Dmitriy On Tue, Mar 7, 2023 at 11:04 AM Hamish Moffatt via Interest < interest@qt-project.org> wrote: > On 7/3/23 20:11, Kai Köhne wrote: > > Hi, > > > > This looks like a compiler issue to me. > >> const auto connections = QSqlDatabase::connectionNames(); > >> qDebug() << "Closing open connections:" << connections; > >> > >> claiming that > >> ../../../src/server/server_database.cpp:691:45: error: invalid operands > to binary expression ('QDebug' and> > >> 'const QList') > > I think this is the place where it goes wrong: > > > >> ../../../../Qt6.4.2/6.4.2/gcc_64/include/QtCore/qdebug.h:217:53: note: > candidate template ignored: requirement > 'std::conjunction_v, > QString>, QTypeTraits::has_ostream_operator>>' was > not satisfied [with T = QString] > >> inline QDebugIfHasDebugStreamContainer, T> operator<<(QDebug > debug, const QList &vec) > >> ^ > > Anyhow, I couldn't reproduce this in a minimal example (and apparently > you didn't manage either?). At minimum we need the exact compiler + > compiler options passed on command line. > > > It's happening in both Visual C++ and gcc 10, but on further > investigation, only in one .cpp file; the same code in other files works > fine. I'll keep investigating. > > > thanks > > Hamish > > ___ > Interest mailing list > Interest@qt-project.org > https://lists.qt-project.org/listinfo/interest > ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
On 7/3/23 20:11, Kai Köhne wrote: Hi, This looks like a compiler issue to me. const auto connections = QSqlDatabase::connectionNames(); qDebug() << "Closing open connections:" << connections; claiming that ../../../src/server/server_database.cpp:691:45: error: invalid operands to binary expression ('QDebug' and> 'const QList') I think this is the place where it goes wrong: ../../../../Qt6.4.2/6.4.2/gcc_64/include/QtCore/qdebug.h:217:53: note: candidate template ignored: requirement 'std::conjunction_v, QString>, QTypeTraits::has_ostream_operator>>' was not satisfied [with T = QString] inline QDebugIfHasDebugStreamContainer, T> operator<<(QDebug debug, const QList &vec) ^ Anyhow, I couldn't reproduce this in a minimal example (and apparently you didn't manage either?). At minimum we need the exact compiler + compiler options passed on command line. It's happening in both Visual C++ and gcc 10, but on further investigation, only in one .cpp file; the same code in other files works fine. I'll keep investigating. thanks Hamish ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
Re: [Interest] can't dump QStringList with qDebug()
Hi, This looks like a compiler issue to me. > const auto connections = QSqlDatabase::connectionNames(); > qDebug() << "Closing open connections:" << connections; > > claiming that > ../../../src/server/server_database.cpp:691:45: error: invalid operands to > binary expression ('QDebug' and> > 'const QList') I think this is the place where it goes wrong: > ../../../../Qt6.4.2/6.4.2/gcc_64/include/QtCore/qdebug.h:217:53: note: > candidate template ignored: requirement > 'std::conjunction_v, > QString>, QTypeTraits::has_ostream_operator>>' was not > satisfied [with T = QString] > inline QDebugIfHasDebugStreamContainer, T> operator<<(QDebug debug, > const QList &vec) > ^ Anyhow, I couldn't reproduce this in a minimal example (and apparently you didn't manage either?). At minimum we need the exact compiler + compiler options passed on command line. I also suggest to move this to bugreports.qt.io. Regards Kai ___ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest