|
|
Agreed, it's not something I would rely on. I was just intrigued to discover that there is some sort of undocumented queue for sent (as opposed to posted) messages.
|
|
|
|
|
If I call SendMessageTimeout() with the flag SMTO_ABORTIFHUNG and a finite timeout period then it could fail (return 0) due to either of these reasons:
1. Timeout (the thread which owns the window started processing the message but didn't complete it within the timeout period).
2. The thread which owns the window was considered to be hung, so didn't (and won't) process the message.
In the first case GetLastError() returns ERROR_TIMEOUT (1460). I can't find any error codes in winerror.h which look relevant to the second case (hung thread).
What I actually want to know, immediately after SendMessageTimeout() returns, is whether the thread which owns the window has or will actually start processing the message. I don't need nor want to wait until it has finished processing the message.
I've spent a couple of hours searching the web and reading various articles, questions etc. but not found an answer to this.
A little while later... I've set up a test case where the window owning thread is spinning in a loop, and then I call SendMessageTimeout(hWnd, WM_MY_MESSAGE, wParam, lParam, SMTO_NORMAL|SMTO_ABORTIFHUNG, 1000, &dwResult).
SendMessageTimeout() immediately returns 0 as expected, and calling GetLastError() returns [drumroll...] 18 (ERROR_NO_MORE_FILES)!!! Go figure...
So it seems there are 2 yucky ways to trap this:
1) Wrap a timer around the call to SendMessageTimeout(), and if it returns in less than the timeout period (1000ms in the example above) then we know it failed because the thread is hung.
2) Test GetLastError(), if it's ERROR_TIMEOUT then we know it's a timeout, if it's ERROR_NO_MORE_FILES then we assume it's because the thread is hung. Or maybe if it's NOT ERROR_TIMEOUT then assume it's because the thread is hung.
Method 1 is smells of kludge, method 2 relies on undocumented behaviour.
And while we are on undocumented behaviour, it seems that passing a timeout value of 0 means "infinite timeout" although no doc I can find for SendMessageTimeout() mentions that.
And some time later again... Well the behaviour is inconsistent. I've also had it fail (return 0) immediately with ERROR_TIMEOUT, and bizarrely sometimes fail immediately with error code 0 (ERROR_SUCCESS). This is Windows 10. It seems that all bets are off in trying to interpret the return value and/or error code.
modified 12-Mar-24 8:27am.
|
|
|
|
|
I would suggest that you raise this on one of the Microsoft support forums, as it will then get through (in time) to the people responsible.
|
|
|
|
|
Yes, good idea. Thinking about it I probably should have posted this under Windows Development not C/C++ (ditto my following post about SendNotifyMessage()).
|
|
|
|
|
MikeBz wrote: because the thread is hung.
In my experience attempting to definitely trap that is just not going to work.
The states that one can reliably define for a thread
1. It worked. Worked can include returning an error result (of any sort.)
2. It took too long.
For the second case one might try to hypothesize about the cause. And then perhaps collect information, even over time, that allows one to narrow detectable types of failures.
But one should never expect that they can detect and certainly not correct all possible errors. All one can do is reduce the failure rate to a point where it can be ignored.
|
|
|
|
|
Understood, thanks for your reply. I'm looking at some not-very-well-designed legacy code and trying to work out whether its attempts to deal with a potential deadlock are flawed. Given that it's over 20 years old and nobody has complained it's probably better to just leave it alone.
|
|
|
|
|
Okay, I know this has got to be easy, but my search-fu is failing me.
I am lifting a VC6++ project written 20+ years ago to VS2022. There are a few burps along the way with some changes to MFC. Fine. In a past project, we had to move some EVC++ code to VS2008, and Microsoft really did not make it easy in some areas, moving things around - like the process of adding an event handler - they deleted the wizard and came up with a new model.
Fast forward 10+ years, and I'm facing the same struggle with VS2022. I'm trying to fix a menu issue in the MDI application with a drop down event handler. Part of my debug is I am trying to create a simple MDI application and add this event handler, but for the life of me, I cannot find where VS2022 does this.
Can someone point me in the right direction? I know it's got to be there.
Thanks
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
|
I'll give it a shot. Part of my problem is that I am still in google can find everything mode. Microsoft went and protected themselves - rightfully so - from google farming them.
I also have a bias against Microsoft support and forums. It's mostly filled in with useless drivel, "hi, I'm an independent contributor. I will help you. Have you rebooted your computer lately?" "Please follow the next 42 random suggestions, etc."
But I've not been to the developers forums in a while - that's against me.
Thanks.
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
Could somebody kindly help me to identify the problem with this code.
It is basically original C code I am trying to annotate.
I have included all what I can find about the
hci_devba function.
I have no better error description - the app just crashes executing the function.
I am confident the "dev_id" ( function descriptor ?) is valid - the app runs just fine when
function
hci_devba is bypassed.
I am not certain I am using the
bdaddr_t *bdaddr parameter correctly.
hci_get_route(NULL); uses same (address stricture) parameter, but passing it as NULL results
in "selecting any (default) local devices ".
Appreciate any help. Thanks.
<pre> dev_id = hci_get_route(NULL);
#ifdef BYPASS
// common bluetooth address
int hci_devba(int dev_id, bdaddr_t *bdaddr);
typedef struct {
uint8_t b[6];
} __attribute__((packed)) bdaddr_t;
int hci_devba(int dev_id, bdaddr_t *bdaddr)
{
struct hci_dev_info di;
memset(&di, 0, sizeof(di));
if (hci_devinfo(dev_id, &di))
return -1;
if (!hci_test_bit(HCI_UP, &di.flags)) {
errno = ENETDOWN;
return -1;
}
bacpy(bdaddr, &di.bdaddr);
return 0;
}
#endif
bdaddr_t *bdaddr_1 = NULL;
result = hci_devba(dev_id,bdaddr_1);
|
|
|
|
|
Did you try to debug our code?
|
|
|
|
|
Digging around it seems that bacpy is defined in bluetooth.h as
static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
} The C standard says that if the destination address for memcpy is null, then the results are undefined. It looks like the GNU libc implementation causes a seg-fault in this case. Other libraries may do something different. My take is that wherever you got your documentation for hci_devba() , it is mistaken about passing a NULL pointer to hci_devba for the bdaddr parameter.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Got caught by "bluez" library...and I will leave it alone...
Apparently "hci_devba" does not "return" device address and crashes when "dev_id" is passed to it.
When "socket" is build using
sock = hci_open_dev( dev_id );
it makes little sense ( to me) to pass "socket" to
hci_devba
BUT at least it does not crash...
<pre> bdaddr_t *bdaddr_1={0};
result = hci_devba(sock, bdaddr_1);
if(result == 0)
{
text = "SUCCESs local device address ";
//CONVERT char to string
ba2str(bdaddr_1, addr);
text = addr;
}
else
{
text = "FAILED to get local device address (socket) ";
}
qDebug()<< text;
PS
I do not get why your definition ) of
hci_devba and mine do not match.
|
|
|
|
|
My "definition" of hci_devba (e.g. hci_devba() ) was only meant to convey that the "object" referred to was a "function", and not meant to be a full "prototype" for same.
Salvatore Terress wrote: it makes little sense ( to me) to pass "socket" to I can only assume that's the requirement of the function, as written by its author. It's no more mysterious than requiring a file descriptor when calling read() or write() (n.b. those are just indications that read() and write() are functions, and not some other object type ... )
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
I have verified that the first parameter is indeed "dev_id" , unfortunately "bluez" does not brother to farther identify it . I "assume" it is "file descriptor"...
Since I cannot identify what causes the run to crash I am going to cheat, for now , and use "hcitool dev" to identify the local Bluetooth device.
I may get ambitious and find the source for "hcitool" and verify what somebody else coded to identify local device , and its address...
cheers
|
|
|
|
|
So, I'm lifting a VC6++ code base to VS2022. It's tedious. Lot's of landmine opportunities, and to say VS2022 is more particular is an understatement... but this code snippet has me mystified - here is the beginning of my original code and it throws a "Warning C6011" possible NULL pointer. Okay, so I see that.
void CInfoBar::SetText(LPCTSTR lpszNew)
{
ASSERT(lpszNew && AfxIsValidString(lpszNew));
if (*lpszNew == _T('#'))
{
TCHAR szNum[8];
INT nCount = 0;
.
.
.
per the help page, it encourages me to check the pointer passed before using it. So I changed the code to below (wrapped it in an if statement.
if (NULL != lpszNew)
{
ASSERT(lpszNew && AfxIsValidString(lpszNew));
if (*lpszNew == _T('#'))
{
TCHAR szNum[8];
INT nCount = 0;
.
.
.
It still throws the warning. I only have a couple of hundred of these things in code the original developer lifted from Microsoft 20 years ago, so...
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
oh ffs. In a small spot of inspiration, I changed my if statement from:
"
if (NULL != lpszNew)
{
to
if (lpszNew != NULL)
{
and the warning goes away. The first form is a time honored coding tradition to prevent typos in conditionals. You obviously cannot assign a value to NULL, so you catch it when you mistype the conditional.
Fine, I'm moving on. In about 6 months, I'm going to be fishing.
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
It's nice to know that even well-seasoned developers like you can have these kinds of moments.
I thought I was alone.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
charlieg wrote: The first form is a time honored coding tradition to prevent typos in conditionals. I wonder if anyone ever has remembered to write the conditional backwards, yet used '=' rather than '=='. My impression is that those who turns the condition around never mixes up assignment and equality operators.
I prefer the natural way of writing conditionals, emphasizing readability over dogmas. (I never say 'if 1979 is the vintage', but 'if the vintage is 1979', or 'if green is the car' but 'if the car is green'.)
And, I can't remember as far back as to when the C compiler did not give a warning at 'if (lpszNew != NULL)', something like 'Possibly unintended assignment'.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
trønderen wrote: those who turns the condition around never mixes up assignment and equality operators. Well, then the backwards writing of the conditional served its purpose, right? If it makes you give extra attention to the code, then that's a good thing.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
At the cost of reduced readability. No, I prefer more readable code.
And I trust that the compiler will warn me about 'Possibly unintended assignment' - as it does, maybe once every 2-3 years.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
trønderen wrote: I wonder if anyone ever has remembered to write the conditional backwards, yet used '=' rather than '=='.
Probably not enough to agonize over it.
trønderen wrote: I prefer the natural way of writing conditionals
I do too. Every time I see the other form my brain tends to do a little twist as I try to figure it out.
And of course these days if one is really concerned then add a method 'IsNull()' and use that. That makes it really obvious.
|
|
|
|
|
trønderen wrote: I never say 'if 1979 is the vintage'
... because a Jedi master you are not
Mircea
|
|
|
|
|
trønderen wrote: I wonder if anyone ever has remembered to write the conditional backwards, yet used '=' rather than '=='. My impression is that those who turns the condition around never mixes up assignment and equality operators. Right. However I sometimes make a typo.
Quote: I prefer the natural way of writing conditionals,emphasizing readability over dogmas Me too. Luckily, modern compilers produce a warning.
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|