Re: [Interest] can't dump QStringList with qDebug()

2023-03-07 Thread Thiago Macieira
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()

2023-03-07 Thread Hamish Moffatt via Interest

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

2023-03-07 Thread Maxim
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()

2023-03-07 Thread Thiago Macieira
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

2023-03-07 Thread Scott Bloom
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([0], , 4);
   std::memcpy([1], , 4);
   std::memcpy([2], , 4);

   became

std::memcpy( [ 0 ], >startupInfo->hStdInput, 
sizeof( HANDLE ) );
std::memcpy( [ 1 ], >startupInfo->hStdOutput, 
sizeof( HANDLE ) );
std::memcpy( [ 2 ], >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([1], , 4);
   std::memcpy([2], , 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([1], FOPEN | FDEV, 2);

   const HANDLE invalid = INVALID_HANDLE_VALUE;
   std::memcpy([0], , 4);
   std::memcpy([1], , 4);
   std::memcpy([2], , 4);

   startInf.cbReserved2 = sizeof(HackedHandlePasser);
   startInf.lpReserved2 = reinterpret_cast();

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

Re: [Interest] QProcess unbuffered

2023-03-07 Thread Scott Bloom
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([1], , 4);
   std::memcpy([2], , 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([1], FOPEN | FDEV, 2);

   const HANDLE invalid = INVALID_HANDLE_VALUE;
   std::memcpy([0], , 4);
   std::memcpy([1], , 4);
   std::memcpy([2], , 4);

   startInf.cbReserved2 = sizeof(HackedHandlePasser);
   startInf.lpReserved2 = reinterpret_cast();

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

2023-03-07 Thread Scott Bloom
Maybe Im being dense (its been a long day)

But where is pipe defined ?

   std::memcpy([1], , 4);
   std::memcpy([2], , 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([1], FOPEN | FDEV, 2);

   const HANDLE invalid = INVALID_HANDLE_VALUE;
   std::memcpy([0], , 4);
   std::memcpy([1], , 4);
   std::memcpy([2], , 4);

   startInf.cbReserved2 = sizeof(HackedHandlePasser);
   startInf.lpReserved2 = reinterpret_cast();

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()

2023-03-07 Thread Hamish Moffatt via Interest

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

2023-03-07 Thread Scott Bloom



-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

2023-03-07 Thread Thiago Macieira
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

2023-03-07 Thread Björn Schäpers
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();

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([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

2023-03-07 Thread 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();

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([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

2023-03-07 Thread Scott Bloom
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([1], FOPEN | FDEV, 2);

   const HANDLE invalid = INVALID_HANDLE_VALUE;
   std::memcpy([0], , 4);
   std::memcpy([1], , 4);
   std::memcpy([2], , 4);

   startInf.cbReserved2 = sizeof(HackedHandlePasser);
   startInf.lpReserved2 = reinterpret_cast();

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

2023-03-07 Thread Björn Schäpers

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([1], FOPEN | FDEV, 2);

  const HANDLE invalid = INVALID_HANDLE_VALUE;
  std::memcpy([0], , 4);
  std::memcpy([1], , 4);
  std::memcpy([2], , 4);

  startInf.cbReserved2 = sizeof(HackedHandlePasser);
  startInf.lpReserved2 = reinterpret_cast();

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()

2023-03-07 Thread Thiago Macieira
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

2023-03-07 Thread Ulf Hermann via Interest
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()

2023-03-07 Thread Dmitriy Purgin
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 )
> >>  ^
> > 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()

2023-03-07 Thread Hamish Moffatt via Interest

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 )
 ^

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()

2023-03-07 Thread Kai Köhne via Interest
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 )
> ^

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