My cross-platform C program takes an IPv6 address and port number, and tries to connect to the remote server they designate. The address may or may not have a scope suffix.
I use getifaddrs() and iterate through the results using a pointer struct ifaddr * pAdapter, ignoring the entries where pAdapter->ifa_addr->sa_family != AF_INET6.
If the user supplied a numeric scope suffix, I only look at entries where the scope ID (sockaddr_in6 *)(pAdapter->ifa_addr)->sin6_scope_id matches it, and if they supplied a non-numeric suffix, I only look at the entries where pAdapter->ifa_name matches it. But if the scope suffix was empty, I simply try all of the entries in turn, and the user has to live with the first successful one whichever it is. (This iteration seems unnecessary on Windows 10—from what I can tell, winsock2 seems to actually do its own similar cascade of attempts under the hood if you leave the scope ID and flow-control fields zeroed.)
On each attempt, I take a copy of *(sockaddr_in6 *)(pAdapter->ifa_addr), fill in the desired sin6_addr and sin6_port, and try to connect() my socket. On my Ubuntu box, this works. On Windows 10, it also works, though it's probably redundant as I mentioned. But on MacBooks running system 10.13.6 and 11.2.3, I have a problem: for some reason there are two IPv6 interfaces both called "lo0", one with scope ID 0 and one with scope ID 1, and connect() hangs when trying through the latter.
For example, I might be trying to connect to fe80::dead:beef%en0 (scope ID 5) and I only supply fe80::dead:beef. The fe80::dead:beef%0 attempt fails with "No route to host" and we move on, but the fe80::dead:beef%1 attempt hangs indefinitely and we never get as far as scope 5.
Why the duplication, why does it hang, and what should I do? Merely adding a timeout to the attempt would make the whole thing prohibitively slow. Is there any other way I determine that scope 1 is not a viable option, and move on?
Related
I want to create an experiment in PsychoPy Builder that conditionally shows a second routine to participants based on their keyboard response.
In the task, I have a loop that first goes through a routine where participants have three options to respond ('left','right','down') and only if they select 'left', regardless of the correct answer, should they see a second routine that asks a follow-up question to respond to. The loop should then restart with routine 1 each time.
I've tried using bits of code in the "begin experiment" section as such:
if response.key=='left':
continueRoutine=True
elif response.key!='left':
continueRoutine=False
But here I get an error saying response.key is not defined.
Assuming your keyboard component is actually called response, the attribute you are looking for is called response.keys. It is pluralised as it returns a list rather than a single value. This is because it is capable of storing multiple keypresses. Even if you only specify a single response, it will still be returned as a list containing just that single response (e.g. ['left'] rather than 'left'). So you either need to extract just one element from that list (e.g. response.keys[0]) and test against that, or use a construction like if 'left' in response.keys to check inside the list.
Secondly, you don't need to have a check that assigns True to continueRoutine, as it defaults to being True at the beginning of a routine. So it is only setting it to False that results in any action. So you could simply do something like this:
if not 'left' in response.keys:
continueRoutine = False
Lastly, for PsychoPy-specific questions, you might get better support via the dedicated forum at https://discourse.psychopy.org as it allows for more to-and-fro discussion than the single question/answer structure here at SO.
I have two loops:
One loop gets data from a device and processes it. Scales received variables, calculates extra data.
Second loop visualizes the data and stores it.
There are lots of different variables that need to passed between those two loops - about 50 variables. I need the second loop to have access only to the newest values of the data. It needs to be able to read those variables any time they are needed to be visualized.
What is the best way to share such vector between two loops?
There are various ways of sharing data.
The fastest and simplest is a local variable, however that is rather uncontrolled, and you need to make sure to write them at one place (plus you need an indicator).
One of the most advanced options is creating a class for your data, and use an instance (if you create a by-ref class, otherwise it won't matter), and create a public 'GET' method.
In between you have sevaral other options:
queues
semaphores
property nodes
global variables
shared variables
notifiers
events
TCP-IP
In short there is no best way, it all depends on your skills and application.
As long as you're considering loops within the SAME application, there ARE good and bad ideas, though:
queues (OK, has most features)
notifiers (OK)
events (OK)
FGVs (OK, but keep an eye on massively parallel access hindering exec)
semaphores (that's not data comms)
property nodes (very inefficient, prone to race cond.)
global variables (prone to race cond.)
shared variables (badly implemented by NI, prone to race cond.)
TCP-IP (slow, awkward, affected by firewall config)
The quick and dirty way to do this is to write each value to an indicator in the producer loop - these indicators can be hidden offscreen, or in a page of a tab control, if you don't want to see them - and read a local variable of each one in the consumer loop. However if you have 50 different values it may become hard to maintain this code if you need to change or extend it.
As Ton says there are many different options but my suggestion would be:
Create a cluster control, with named elements, containing all your data
Save this cluster as a typedef
Create a notifier using this cluster as the data type
Bundle the data into the cluster (by name) and write this to the notifier in the producer loop
Read the cluster from the notifier in the consumer loop, unbundle it by name and do what you want with each element.
Using a cluster means you can easily pass it to different subVIs to process different elements if you like, and saving as a typedef means you can add, rename or alter the elements and your code will update to match. In your consumer loop you can use the timeout setting of the notifier read to control the loop timing, if you want. You can also use the notifier to tell the loops when to exit, by force-destroying it and trapping the error.
Two ways:
Use a display loop with SEQ (Single Element Queue)
Use a event structure with User Event. (Do not put two event structures in same loop!! Use another)
Use an enum with case structure and variant to cast the data to expected type.
(Notifier isn't reliable to stream data, because is a lossy scheme. Leave this only to trigger small actions)
If all of your variables can be bundled together in a single cluster to send at once, then you should use a single element queue. If your requirements change later such that the transmission cannot be lossy, then it's a matter of changing the input to the Obtain Queue VI (with a notifier you'd have to swap out all of the VIs). Setting up individual indicators and local variables would be pretty darn tedious. Also, not good style.
If the loops are inside of the same VI then:
The simplest solution would be local variables.
Little bit better to use shared variables.
Better is to use functional global variables (FGVs)
The best solution would be using SEQ (Single Element Queue).
Anyway for better understanding please go trough this paper.
Can anybody explain to me why XOpenDisplay() doesn't fail with bad display names? As long as the names follow the syntax convention, it always seems to succeed - even if the specified host name doesn't exist. XOpenDisplay() only seems to fail if the string uses a bad syntax, e.g.
d = XOpenDisplay("foobar"); // fails - presumably because of bad syntax in string
d = XOpenDisplay("foobar:0.0"); // works - although there is no host named "foobar"
When specifying a hostname that doesn't exist, XOpenDisplay() seems to fallback to $DISPLAY. Is that how it is supposed to be? I didn't find anything about these fallbacks in the Xlib documentation. If it is correct behaviour, is there a way to check whether the returned display really connected me to "foobar:0.0" or whether it is just a fallback to $DISPLAY?
That does seem like rather weak behavior, but http://tronche.com/gui/x/xlib/display/opening.html says:
The encoding and interpretation of the display name is implementation
dependent.
So it seems that this "interpretation" is allowed.
To tell if the default display was opened instead, you might try:
d_default = XOpenDisplay(NULL);
d = XOpenDisplay("foobar:0.0");
if (!d || d == d_default) {
// foobar:0.0 was not opened.
}
If this doesn't work because d and d_default are different even though referring to the same hardware, you might try comparing a field of the _XDisplay struct instead of the returned pointers, which are apparently pointing to different structs which somewhere must have similar data since they reference the same hardware. See the following reference for possibilities, but the simplest (if it works) might be to see if d->fd == d_default->fd.
Reference: http://xwindow.angelfire.com/page28.html
The only way I know of to force connection to a particular display is to stick the desired display name into the environment:
setenv("DISPLAY", "foobar:0.0", 1);
d = XOpenDisplay(0);
This is generally also desirable as the proper display name is also propagated to any child processes that are started, though if you want to avoid that, you could record the old $DISPLAY and restore it afterwards.
I have this code
n_userobject inv_userobject[]
For i = 1 to dw_1.Rowcount()
inv_userobject[i] = create n_userobject
.
.
.
NEXT
dw_1.rowcount() returns only 210 rows. Its so odd that in the range of 170 up, the application stop and crashes on inv_userobject[i] = create n_userobject.
My question, is there any limit on array or userobject declaration using arrays?
I already try destroying it after the loop so as to check if that will be a possible solution, but it is still crashing.
Or how can i be able to somehow refresh the userobject?
Or is there anyone out there encounter this?
Thanks for all your help.
First, your memory problem. You're definitely not running into an array limit. If I was to take a guess, one of the instance variables in n_userobject isn't being cleaned up properly (i.e. pointing to a class that isn't being destroyed when the parent class is destroyed) or pointing to a class that similarly doesn't clean itself up. If you've got PB Enterprise, I'd do a profiling trace with a smaller loop and see what is being garbage collected (there's a utility called CDMatch that really helps this process).
Secondly, let's face it, you're just doing this to avoid writing a reset method. Even if you get this functional, it will never be as efficient as writing your own reset method and reusing the same instance over again. Yes, it's another method you'll have to maintain whenever the instance variable list changes or the defaults change, but you'll easily gain that back in performance.
Good luck,
Terry.
I'm assuming the crash you're facing is at the PBVM level, and not a regular PB exception (which you can catch in your code). If I'm wrong, please add the exception details.
A loop of 170-210 iterations really isn't a large one. However, crashes within loops are usually the result of resource exhaustion. What we usually do in long loops is call GarbageCollect() occasionally. How often should it be called depends on what your code does - using it frequently could allow the use of less memory, but it will slow down the run. Read this for more.
If this doesn't help, make sure the error does not come from some non-PB code (imported DLL or so). You can check the stack trace during the crash to see the exception's origin.
Lastly, if you're supported by Sybase (or a local representative), you can send them a crash dump. They can analyze it, and see if it's a bug in PB, and if so, let you know when it was (or will be) fixed.
What I would normally do with a DataWindow is to create an object that processes the data in a row and call it for each row.
the only suggestion i have for this is to remove the rowcount from the for (For i = 1 to dw_1.Rowcount()) this will cause the code to recount the rows every time it uses one. get the count into a variable and then use the variable. it should run a bit better and be far more easy to debug.
My list view contains 3 columns Name, address and phone number.
I want to retrieve an index for a particular name.
I'm using ListView_FindItem macro to find the index number but when my code comes to this line it crashes the program.
It just says Payroll has stopped working. Windows can check online for a solution to the problem.
I'm sure I have passed right handle to the ListView_FindItem macro but I'm not sure about the LVFINDINFO structure.
Here's my code
WCHAR szProcess[80] = {0};
LVFINDINFO item = {LVFI_STRING, (LPCTSTR) szProcess};
//code to find parent handles
...
//code to find index
index = ListView_FindItem(hwndListView, -1, &item);
I'm not sure about the LVFI_STRING flag and I have even tried passing a constant LVFINDINFO structure to ListView_FindItem macro still my program crashes.
Note : The above code is not part of
the payroll application. I mean to say
the payroll application has the
listview and I'm trying to search the
item from other application.
Can some one point me in a right direction ?
Thanks.
Your description is a little unclear, but I interpret it that you are sending LVM_FINDITEM message (via the ListView_FindItem() macro) to a window in a different process.
This simply does not work for this particular Windows message since it passes a pointer to a struct in the calling process which is meaningless when interpreted in the context of the other process (the payroll app that owns the list view).
To solve your problem you could allocate memory in the other process although this is quite a complex task. A commonly cited example of the technique is to be found in the Code Project article, Stealing Program's Memory.
Perhaps a simpler approach would be to use WM_COPYDATA which will marshal string data between processes. If that doesn't have enough flexibility then you'd need to find another IPC mechanism, e.g. named pipes.