On 10/23/2026 3:46 PM, Lawrence D?Oliveiro wrote:
On Fri, 23 Oct 2026 12:55:02 -0700, Chris M. Thomasson wrote:
Fwiw, vcpkg has a lot of them, ready to automatically build and
integrate. vcpkg is actually... Well, its pretty nice and so
far... Seems to work for me.
How does it work for end-users? Are your dependencies automatically
brought in when they install your package? How are they kept
up-to-date?
Oh yeah. In your build directory, say Debug or Release, it has all
of the built shared libs and everything you need to run it.
Keeping them up to date is, afaict, manual.
On 2026-10-23, Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
What was that error message? I was expecting something like ?DISK
ERROR? or ?I/O ERROR?. Instead, it said
I?m having trouble with the disk.
The idea of an error message phrased in plain, approachable
language (using a first-person pronoun, even) instead of technical
terms?? That was a revelation.
Unfortunately it's not the kind of revelation I welcome. Back in my
mainframe days, I learned to hate catch-all error messages; they're
the sign of a programmer who's too lazy to try to help the user. If
something goes wrong, I want to be given some clues as to where to
look. But more and more these days, your typical error message is
"Something went wrong." Nothing more. This kind of conduct should be condemned.
On Fri, 23 Oct 2026 23:31:41 GMT, Charlie Gibbs wrote:
On 2026-10-23, Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
What was that error message? I was expecting something like ?DISK
ERROR? or ?I/O ERROR?. Instead, it said
I?m having trouble with the disk.
The idea of an error message phrased in plain, approachable
language (using a first-person pronoun, even) instead of technical
terms?? That was a revelation.
Unfortunately it's not the kind of revelation I welcome. Back in my
mainframe days, I learned to hate catch-all error messages; they're
the sign of a programmer who's too lazy to try to help the user. If
something goes wrong, I want to be given some clues as to where to
look. But more and more these days, your typical error message is
"Something went wrong." Nothing more. This kind of conduct should be
condemned.
This was not like that though, was it? On systems of that era, you
would typically get something like ?DISK ERROR? or ?I/O ERROR?. The plain-language message was no less specific than that.
Do you want more detail about what went wrong? Perhaps a CRC
validation failure? Sector-addressing failure? Missing address/data
marks? Invalid GCR/RLL encoding?
That kind of low-level detail might be helpful to somebody (perhaps a hardware engineer) trying to fix the problem. And perhaps it should
appear in a system log somewhere.
And it wouldn?t have mattered much in this case, anyway, since it
would have been obvious to anybody? sitting or standing in front of the machine, that the most likely cause was the fact that there was no
disk in the drive.
?Anybody who had made much use of floppy disks on micros, anyway.
On 10/23/2026 8:44 PM, Lawrence D?Oliveiro wrote:
On Fri, 23 Oct 2026 23:31:41 GMT, Charlie Gibbs wrote:
On 2026-10-23, Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
What was that error message? I was expecting something like ?DISK
ERROR? or ?I/O ERROR?. Instead, it said
I?m having trouble with the disk.
The idea of an error message phrased in plain, approachable
language (using a first-person pronoun, even) instead of technical
terms?? That was a revelation.
Unfortunately it's not the kind of revelation I welcome. Back in my
mainframe days, I learned to hate catch-all error messages; they're
the sign of a programmer who's too lazy to try to help the user. If
something goes wrong, I want to be given some clues as to where to
look. But more and more these days, your typical error message is
"Something went wrong." Nothing more. This kind of conduct should be
condemned.
This was not like that though, was it? On systems of that era, you
would typically get something like ?DISK ERROR? or ?I/O ERROR?. The
plain-language message was no less specific than that.
Do you want more detail about what went wrong? Perhaps a CRC
validation failure? Sector-addressing failure? Missing address/data
marks? Invalid GCR/RLL encoding?
That kind of low-level detail might be helpful to somebody (perhaps a
hardware engineer) trying to fix the problem. And perhaps it should
appear in a system log somewhere.
And it wouldn?t have mattered much in this case, anyway, since it
would have been obvious to anybody? sitting or standing in front of the
machine, that the most likely cause was the fact that there was no
disk in the drive.
?Anybody who had made much use of floppy disks on micros, anyway.
Iirc, BASIC had a fun error. I cannot remember the damn exact phrase, it
was something like expression too complex or something.
Shared state? Just use memory mapped files. You don't need
pipes/sockets etc. You need to know how to properly sync things.
On 2026-10-24, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
On 10/23/2026 8:44 PM, Lawrence D?Oliveiro wrote:
On Fri, 23 Oct 2026 23:31:41 GMT, Charlie Gibbs wrote:
On 2026-10-23, Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
What was that error message? I was expecting something like ?DISK
ERROR? or ?I/O ERROR?. Instead, it said
I?m having trouble with the disk.
The idea of an error message phrased in plain, approachable
language (using a first-person pronoun, even) instead of technical
terms?? That was a revelation.
Unfortunately it's not the kind of revelation I welcome. Back in my
mainframe days, I learned to hate catch-all error messages; they're
the sign of a programmer who's too lazy to try to help the user. If
something goes wrong, I want to be given some clues as to where to
look. But more and more these days, your typical error message is
"Something went wrong." Nothing more. This kind of conduct should be
condemned.
This was not like that though, was it? On systems of that era, you
would typically get something like ?DISK ERROR? or ?I/O ERROR?. The
plain-language message was no less specific than that.
Do you want more detail about what went wrong? Perhaps a CRC
validation failure? Sector-addressing failure? Missing address/data
marks? Invalid GCR/RLL encoding?
That kind of low-level detail might be helpful to somebody (perhaps a
hardware engineer) trying to fix the problem. And perhaps it should
appear in a system log somewhere.
And it wouldn?t have mattered much in this case, anyway, since it
would have been obvious to anybody? sitting or standing in front of the
machine, that the most likely cause was the fact that there was no
disk in the drive.
?Anybody who had made much use of floppy disks on micros, anyway.
Iirc, BASIC had a fun error. I cannot remember the damn exact phrase, it
was something like expression too complex or something.
"Who is General Failure and why is he reading my disk?"
On 10/23/2026 8:39 PM, Lawrence D?Oliveiro wrote:
On Fri, 23 Oct 2026 16:58:04 -0700, Chris M. Thomasson wrote:
Keeping them up to date is, afaict, manual.
In the Linux world, we have ?development? packages versus ?runtime?
packages.
The development package contains the source includes, pkg-config
info etc. The runtime version includes the actual shared library.
So your built package has a dependency on the latter; when a user
tries to install your package, it should automatically pull in the
latter as necessary.
Example from my system:
lrwxrwxrwx 1 root root 13 Apr 24 2026 /usr/lib/x86_64-linux-gnu/libcairo.so -> libcairo.so.2
lrwxrwxrwx 1 root root 21 Apr 24 2026 /usr/lib/x86_64-linux-gnu/libcairo.so.2 -> libcairo.so.2.11804.4
-rw-r--r-- 1 root root 1366728 Apr 24 2026 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11804.4
Where did these come from?
root@theon:~ # dpkg-query -S /usr/lib/x86_64-linux-gnu/libcairo.so.2
libcairo2:amd64: /usr/lib/x86_64-linux-gnu/libcairo.so.2
root@theon:~ # dpkg-query -S /usr/lib/x86_64-linux-gnu/libcairo.so
libcairo2-dev:amd64: /usr/lib/x86_64-linux-gnu/libcairo.so
Notice how the development library is not versioned, but is just a
symlink to a versioned library.
The runtime library is always versioned. This allows multiple
versions of the library to be present at once, with some older
packages, that haven?t been rebuilt, still depending on an older
version, while up-to-date packages make use of the newer version.
I was in the linux world for a whiel, along with solaris, etc. But
Windows, oh my. vcpkg is a big turn.
That's where threads are useful: The GUI is one thread, and the
"other things" are in one or more other threads. There are
altogether too many programs that hang the GUI while "other things"
are going on. That should never happen!
Threading is still definitely useful, mainly for performance, where
the bottleneck is in CPU usage. But if a program is spending most of
its time waiting for I/O over the network, or for a user to initiate a
GUI action, or something external and relatively slow like that, then coroutines keep things simpler.
I've always tried to avoid the complexities of threading; in most
cases I can get away with round-robin scheduling. But I found that
some servers are very slow to respond, and even when trying to do a non-blocking setup of a TCP/IP connection, the connect() API would unavoidably block. I had to spin that part off into its own thread
to keep the rest of the program (including other connections) from
hanging.
On Sat, 31 Oct 2026 04:14:05 GMT, Charlie Gibbs wrote:
I've always tried to avoid the complexities of threading; in most
cases I can get away with round-robin scheduling. But I found that
some servers are very slow to respond, and even when trying to do a
non-blocking setup of a TCP/IP connection, the connect() API would
unavoidably block. I had to spin that part off into its own thread
to keep the rest of the program (including other connections) from
hanging.
Here?s a fun little thing: if you set a socket to nonblocking and then
do the connect(2) call, it will seemingly fail with an EINPROGRESS
error. But in fact, the connection attempt gets initiated, and you can monitor its subsequent progress from your event loop.
From the ERRORS section of <https://manpages.debian.org/connect(2)>:
EINPROGRESS
The socket is nonblocking and the connection cannot be
completed immediately. (UNIX domain sockets failed with EAGAIN
instead.) It is possible to select(2) or poll(2) for
completion by selecting the socket for writing. After
select(2) indicates writability, use getsockopt(2) to read the
SO_ERROR option at level SOL_SOCKET to determine whether
connect() completed successfully (SO_ERROR is zero) or
unsuccessfully (SO_ERROR is one of the usual error codes
listed here, explaining the reason for the failure).
I?m not sure about doing this sort of thing from other libraries that
wrap socket connections (e.g. SSL/TLS libraries); for these, the usual fallback is still available, as you say, by turning a blocking call
into a nonblocking one by pushing it off to a separate thread.
On 2026-10-31, Lawrence D?Oliveiro <ldo@nz.invalid> wrote:
On Sat, 31 Oct 2026 04:14:05 GMT, Charlie Gibbs wrote:
I've always tried to avoid the complexities of threading; in most
cases I can get away with round-robin scheduling. But I found that
some servers are very slow to respond, and even when trying to do a
non-blocking setup of a TCP/IP connection, the connect() API would
unavoidably block. I had to spin that part off into its own thread
to keep the rest of the program (including other connections) from
hanging.
Here?s a fun little thing: if you set a socket to nonblocking and then
do the connect(2) call, it will seemingly fail with an EINPROGRESS
error. But in fact, the connection attempt gets initiated, and you can
monitor its subsequent progress from your event loop.
From the ERRORS section of <https://manpages.debian.org/connect(2)>:
EINPROGRESS
The socket is nonblocking and the connection cannot be
completed immediately. (UNIX domain sockets failed with EAGAIN
instead.) It is possible to select(2) or poll(2) for
completion by selecting the socket for writing. After
select(2) indicates writability, use getsockopt(2) to read the
SO_ERROR option at level SOL_SOCKET to determine whether
connect() completed successfully (SO_ERROR is zero) or
unsuccessfully (SO_ERROR is one of the usual error codes
listed here, explaining the reason for the failure).
I?m not sure about doing this sort of thing from other libraries that
wrap socket connections (e.g. SSL/TLS libraries); for these, the usual
fallback is still available, as you say, by turning a blocking call
into a nonblocking one by pushing it off to a separate thread.
I was already setting the socket to non-blocking before calling
connect() - and yet there were times when the API blocked anyway.
I never did figure out why, and we had a customer getting impatient,
so I just spun off another thread and moved on to other things.
On 11/1/2026 11:40 AM, Charlie Gibbs wrote:
I was already setting the socket to non-blocking before calling
connect() - and yet there were times when the API blocked anyway.
I never did figure out why, and we had a customer getting impatient,
so I just spun off another thread and moved on to other things.
connect? On Windows we use ConnectEx.
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_connectex
For accept, AcceptEx:
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
On 2026-11-02, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
On 11/1/2026 11:40 AM, Charlie Gibbs wrote:
I was already setting the socket to non-blocking before calling
connect() - and yet there were times when the API blocked anyway.
I never did figure out why, and we had a customer getting impatient,
so I just spun off another thread and moved on to other things.
connect? On Windows we use ConnectEx.
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_connectex
For accept, AcceptEx:
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
Ah, but then we come to that critical clause:
Note This function is a Microsoft-specific extension to the Windows Sockets specification.
Yes, one more attempt to close the open socket model with
Microsoft proprietary extensions. My code has to run under
Linux as well. Opening the socket in a separate thread is
guaranteed to avoid hangs, regardless of operating system.
On 2026-11-02, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
On 11/1/2026 11:40 AM, Charlie Gibbs wrote:
I was already setting the socket to non-blocking before calling
connect() - and yet there were times when the API blocked anyway.
I never did figure out why, and we had a customer getting impatient,
so I just spun off another thread and moved on to other things.
connect? On Windows we use ConnectEx.
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_connectex
For accept, AcceptEx:
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
Ah, but then we come to that critical clause:
Note This function is a Microsoft-specific extension to the Windows Sockets specification.
Yes, one more attempt to close the open socket model with
Microsoft proprietary extensions. My code has to run under
Linux as well. Opening the socket in a separate thread is
guaranteed to avoid hangs, regardless of operating system.
On 11/2/2026 6:42 PM, Charlie Gibbs wrote:
On 2026-11-02, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
On 11/1/2026 11:40 AM, Charlie Gibbs wrote:
I was already setting the socket to non-blocking before calling
connect() - and yet there were times when the API blocked anyway.
I never did figure out why, and we had a customer getting impatient,
so I just spun off another thread and moved on to other things.
connect? On Windows we use ConnectEx.
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_connectex
For accept, AcceptEx:
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
Ah, but then we come to that critical clause:
Note This function is a Microsoft-specific extension to the Windows Sockets specification.
Yes, one more attempt to close the open socket model with
Microsoft proprietary extensions. My code has to run under
Linux as well. Opening the socket in a separate thread is
guaranteed to avoid hangs, regardless of operating system.
These are for high performance systems. But, they solve a lot of
problems. Say your program starts to gain a lot of users?
On Mon, 26 Oct 2026 19:51:23 -0700, Chris M. Thomasson wrote:
On 10/23/2026 8:39 PM, Lawrence D?Oliveiro wrote:
On Fri, 23 Oct 2026 16:58:04 -0700, Chris M. Thomasson wrote:
Keeping them up to date is, afaict, manual.
In the Linux world, we have ?development? packages versus ?runtime?
packages.
The development package contains the source includes, pkg-config
info etc. The runtime version includes the actual shared library.
So your built package has a dependency on the latter; when a user
tries to install your package, it should automatically pull in the
latter as necessary.
Example from my system:
lrwxrwxrwx 1 root root 13 Apr 24 2026 /usr/lib/x86_64-linux-gnu/libcairo.so -> libcairo.so.2
lrwxrwxrwx 1 root root 21 Apr 24 2026 /usr/lib/x86_64-linux-gnu/libcairo.so.2 -> libcairo.so.2.11804.4
-rw-r--r-- 1 root root 1366728 Apr 24 2026 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11804.4
Where did these come from?
root@theon:~ # dpkg-query -S /usr/lib/x86_64-linux-gnu/libcairo.so.2 >>> libcairo2:amd64: /usr/lib/x86_64-linux-gnu/libcairo.so.2
root@theon:~ # dpkg-query -S /usr/lib/x86_64-linux-gnu/libcairo.so
libcairo2-dev:amd64: /usr/lib/x86_64-linux-gnu/libcairo.so
Notice how the development library is not versioned, but is just a
symlink to a versioned library.
The runtime library is always versioned. This allows multiple
versions of the library to be present at once, with some older
packages, that haven?t been rebuilt, still depending on an older
version, while up-to-date packages make use of the newer version.
I was in the linux world for a whiel, along with solaris, etc. But
Windows, oh my. vcpkg is a big turn.
Windows isn?t even in the same league, is it.
On 2026-11-03, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
On 11/2/2026 6:42 PM, Charlie Gibbs wrote:
On 2026-11-02, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote: >>>
On 11/1/2026 11:40 AM, Charlie Gibbs wrote:
I was already setting the socket to non-blocking before calling
connect() - and yet there were times when the API blocked anyway.
I never did figure out why, and we had a customer getting impatient, >>>>> so I just spun off another thread and moved on to other things.
connect? On Windows we use ConnectEx.
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_connectex
For accept, AcceptEx:
https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
Ah, but then we come to that critical clause:
Note This function is a Microsoft-specific extension to the Windows Sockets specification.
Yes, one more attempt to close the open socket model with
Microsoft proprietary extensions. My code has to run under
Linux as well. Opening the socket in a separate thread is
guaranteed to avoid hangs, regardless of operating system.
These are for high performance systems. But, they solve a lot of
problems. Say your program starts to gain a lot of users?
In our environment that should never happen.
The only legitimate
users are those that are other elements of our software package.
Any others (or too many seemingly legitimate users) get a rejection
message, followed by disconnection.
| Sysop: | Tetrazocine |
|---|---|
| Location: | Melbourne, VIC, Australia |
| Users: | 4 |
| Nodes: | 8 (0 / 8) |
| Uptime: | 234:46:36 |
| Calls: | 222 |
| Files: | 21,513 |
| Messages: | 82,481 |