List all NSPasteBoard names on macOS - macos

Is there a way to get a list of all the NSPasteBoards and their names on the current system?
I'm wondering if there's some function available (even if private API) to achieve this. Thank you!

No, there's no function to do this, even with private API.
The pboard program (/usr/libexec/pboard) runs as a daemon and manages all shared pasteboards. The NSPasteboard class talks to the pboard daemon using XPC, so to get a list of all pasteboards, pboard would need to handle some XPC message by responding with a list of pasteboard names.
The pboard program is very simple: it initializes various things (logs, sandbox, dispatch queue, mach service) and then calls __CFPasteboardStartServicingConnection, which is actually defined in the CoreFoundation framework. This function ultimately handles each incoming XPC request by calling _CFHandlePasteboardXPCEvent.
Looking at _CFHandlePasteboardXPCEvent in a disassembler (I used Hopper), we can see the complete list of requests supported by pboard:
com.apple.pboard.create
com.apple.pboard.get-counts
com.apple.pboard.barrier
com.apple.pboard.begin-generation
com.apple.pboard.has-entries
com.apple.pboard.register-entries
com.apple.pboard.request-data
com.apple.pboard.refresh-cache
com.apple.pboard.release
com.apple.pboard.unique-promise-file
com.apple.pboard.resolve-all-promises
com.apple.pboard.resolve-pboard-promises
com.apple.pboard.set-data-flags
com.apple.pboard.make-generation-local
None of these has an obvious name like com.apple.pboard.get-pboard-names. Looking at how they're handled, the first thing done by almost all of them is to get a pasteboard name from the event and look up or create the pasteboard with that name.
The only request that I found that doesn't immediately involve looking up a pasteboard by name is com.apple.pboard.resolve-all-promises, which in fact sends the intriguing message +[_CFPasteboardStore copyAllPasteboards]. However, it doesn't send the result, or in fact any result, back to the client, as far as I can tell. And that is the only use of the copyAllPasteboards selector in CoreFoundation.
So, unless you attach to the pboard daemon with a debugger and poke around, you won't find a list of all existing pasteboards. (Attaching to pboard with a debugger requires first disabling SIP, which requires booting your recovery partition.)

Related

What could cause Realm to lock up when attempting a write?

My team is currently facing an issue in our Xamarin.Forms app across all platforms(Android, iOS, and UWP). Realm will frequently become unresponsive, where the only way to use it again is to close the app. Over the past few months it's become more frequent and easy to reproduce, yet we have not been able to determine the cause or a workaround.
We have identified a few patterns that may help identify what's happening. We've noticed that whenever something that needs information from the database, we'll see that worker thread stuck on a Realm.Write() call. This behavior seems almost as if there's a deadlock occuring within the Realm system. It's not consistent as to which Write() call it's stuck on, seeming to be random based on when the Realm fails. At that point, any other attempts to access this realm through any method, such as Find(),All(),Remove(), etc also get stuck. We've also confirmed that the code within the Write() is never being run at this point, since we can put a realm independent logging call on the first line and never see it in our logs.
Once this issue occurs, some other issues can happen in addition to this. We have two other Realms in our app that handle completely separate data, and as such have no overlapping code. These Realms are never the cause of this issue, but when the problem Realm gets stuck, it sometimes causes the other Realms to get stuck on their next calls as well. This issue also sometimes persists between uses of the app, causing the very first call to Realm to get stuck and requires a complete reinstall to fix.
Due to our app using Reactive based programming, we've had to structure how we handle our database a bit differently. For the problem Realm, we have a service that keeps a single instance active in an observable stream, which can then be subscribed to for watching changes. I've added some examples of this architecture at the end of this post. We also route all our other non-observable actions through this stream, however during debugging we've been able to move these calls to their own independent realm instances with little issue/no change to functionality.
Currently, we're thinking it's most likely an issue related either to how we're converting Realm to an observable system, or with our Realms crashing/becoming corrupted somehow.
RealmStream declaration:
_realmStream = Observable
.Start(() => Realm.GetInstance(_dbConfig), _scheduler)
.Do(_ => logger.LogTrace("Realm created"), () => logger.LogTrace("Realm stream completed"))
.Replay()
.AutoConnect();
RealmStream use example:
public IObservable<IChangeSet<TResult>> GetChangeSetStream<TSource, TResult>(Func<Realm, IQueryable<TSource>> selector, Func<TSource, TResult> transformFactory) where TSource : RealmObject
{
return _realmStream
.Select(realm =>
selector(realm)
.AsRealmCollection()
.ToObservableChangeSet<IRealmCollection<TSource>, TSource>()
.SubscribeOn(_scheduler)
.Transform(transformFactory)
.DisposeMany())
.Switch()
.Catch<IChangeSet<TResult>, Exception>(ex =>
{
_logger.LogError(ex, "Error getting property change stream");
return Observable.Return<IChangeSet<TResult>>(default);
})
.SubscribeOn(_scheduler);
}
Non-Observable realm methodss:
public async Task Run(Action<Realm> action)
{
await _realmStream
.Do(action)
.SubscribeOn(_scheduler);
}
public async Task<TResult> Run<TResult>(Func<Realm, TResult> action)
{
return await _realmStream
.Select(action)
.SubscribeOn(_scheduler);
}
So far, we've attempted the following:
Made sure Realm and Xamarin are both on the most recent versions
Reducing the number of Realm.Write()s (Minor improvement)
Moving every Realm function into our observable system (No noticable change, most of our functions already do this)
Attempted moving everything that does not require observables to using independent realm instances (increased frequency of locking)
Attempted to move everything away from our single instance of Realm. We weren't able to do this, as we could not determine how to properly handle some observable events, such as a RealmObject being deleted, without causing major performance issues
realm.Write needs to acquire a write lock and based on your description, it appears that you do get a deadlock where a thread with an open write transaction waits for another thread that is stuck on the realm.Write call. If you're able to reproduce the hand with a debugger attached, you can inspect the threads window and try to pinpoint the offending code.
This article provides some tips about debugging deadlocks. Unfortunately, without the whole project and a repro case, it'd be hard to pinpoint the cause.

Allow-listing IP addresses using `call.cancel()` from within `EventListener.dnsEnd()` in OkHttp

i am overriding the dnsEnd() function in EventListener:
#Override
public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
inetAddressList.forEach(address -> {
logger.debug("checking if url ({}) is in allowlist", address.toString());
if (!allowlist.contains(address)) {
call.cancel();
}
});
}
i know, in the documentation it says not to alter call parameters etc:
"All event methods must execute fast, without external locking, cannot throw exceptions, attempt to mutate the event parameters, or be re-entrant back into the client. Any IO - writing to files or network should be done asynchronously."
but, as i don't care about the call if it is trying to get to an address outside the allowlist, i fail to see the issue with this implementation.
I want to know if anyone has experience with this, and why it may be an issue?
I tested this and it seems to work fine.
This is fine and safe. Probably the strangest consequence of this is the canceled event will be triggered by the thread already processing the DNS event.
But cancelling is not the best way to constrain permitted IP addresses to a list. You can instead implement the Dns interface. Your implementation should delegate to Dns.SYSTEM and them filter its results to your allowlist. That way you don't have to worry about races on cancelation.

XCB event loop not getting any events

I am making an addon in Firefox, so I have a ChromeWorker - which is a privileged WebWorker. This is just a thread other then the mainthread.
In here I have no code but this (modified to make it look like not js-ctypes [which is the language for addons])
On startup I run this code, conn is a global variable:
conn = xcb_connect(null, null);
Then I run this in a 200ms interval:
evt = xcb_poll_for_event(conn);
console.log('evt:', evt);
if (!evt.isNull()) {
console.log('good got an event!!');
ostypes.API('free')(evt);
}
However evt is always null, I am never getting any events. My goal is to get all events on the system.
Anyone know what can cause something so simple to not work?
I have tried
xcb_change_window_attributes (conn, screens.data->root, XCB_CW_EVENT_MASK, values);
But this didn't fix it :(
The only way I can get it to work is by doing xcb_create_window xcb_map_window but then I get ONLY the events that happen in this created window.
You don't just magically get all events by opening a connection. There's only very few messages any client will receive, such as client messages, most others will only be sent to a client if it explicitly registered itself to receive them.
And yes, that means you have to register them on each and every window, which involves both crawling the tree and listening for windows being created, mapped, unmapped and destroyed and registering on them as well.
However, I would reconsider whether
My goal is to get all events on the system.
isn't an A-B problem. Why do you "need" all events? What do you actually want to do?

Get process info making request inside TDI filter driver

I'm starting to write a TDI filter driver, and one of the things I'd like to know is which process is generating the requests. I'm guessing the info is available somewhere in the (mostly undocumented) structures. For example, I currently get the IP address and port inside TDI_CONNECT event like this:
stackIrp = IoGetCurrentIrpStackLocation(irp);
connectRequest = (TDI_REQUEST_KERNEL_CONNECT*) &stackIrp->Parameters;
transportAddr = (TRANSPORT_ADDRESS*) connectRequest->RequestConnectionInformation->RemoteAddress;
taAddr = (TA_ADDRESS*) transportAddr->Address;
ipAddr = (TDI_ADDRESS_IP*) taAddr->Address;
Do I end up just getting a socket handle and I have to work backwards to get process info, or do I get a process ID somewhere?
Ultimately I'd like to know the process info (EXE name, handle, etc), but also will need to know the Windows user that owns the session the process is running in... because yah, I'm writing yet another website filtering app, and like all of the others it needs to allow for different options per user.
You may use the 'IoGetRequestorProcessId' routine, which described at http://msdn.microsoft.com/en-us/library/windows/hardware/ff548391(v=vs.85).aspx, to get an unique 32-bit ULONG process id for the thread that originally request a given I/O operation.
After you get the process id, you can retrieve the process information, such as EXE name, modules, execution path and something else in a user-mode application.

Suggestions needed for architecting my code

Background
I'm writing an part of my app that has no UI. It sits in the background watching what you do and timing your work.
There should be no overlapping times, and there should be no breaks in the time data. If there are either of these things, the app has a bug somewhere and I need to be notified.
What I Want
A class called JGDataIntegrityController that does the following:
Check the data store for duplicate times. Scan since the last Duplicate Report Date stored in NSUserDefaults.
If duplicate times are found, build a report.
Send the report.
If the sending isn't successful, then exit. Otherwise continue.
Remove the duplicates
Update the last Duplicate Report Date in NSUserDefaults
Repeat the above for data breaks.
What I've Got
I've made a base class that does all the hard work of sending the report.
Class Diagram http://synapticmishap.co.uk/ReportClasses.jpg
JGReportSender has the following code:
-(void)postReport:(NSString *)report {
NSMutableDictionary *form = // Dictionary Holding Report;
NSURLRequest *request = [NSURLRequest requestWithURL:#"http://postURL" postForm:form];
[NSURLConnection connectionWithRequest:request delegate:self];
}
Where I'm Getting Stuck
What should I do when the report has been sent?
The delegate methods:
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError*)error
are called when the report has been sent. But how should I communicate with JGDataIntegrityController?
My Crap Idea
My idea is to have a reportStatus NSNumber property in JGReportSender. Then when the delegate methods get called, this is updated.
reportStatus = 1 means "report sent OK".
reportStatus = 2 means "problem sending report".
Then I could add an observer for reportStatus for JGDataDuplicateReportSender and JGDataBreakReportSender. This would then handle the report sending error or continue on.
Any Good Ideas?
I get the feeling this is a really messy way of doing this. I also feel like I'm overlooking something really obvious.
Any ideas how to do this in a neat way?
Update
I totally forgot to mention - this will be a 100% opt in feature. It'll be disabled by default. It'll also have 3 levels of privacy - from "a data break occurred" through to "a data break occurred after this application was active with this document path". And the reports will also be anonymous.
I'm conscious of all the privacy concerns - this is so I can make the software better, not so I can spy on people!
Give the report sender a delegate property and protocol, with at least two methods: reportSenderDidSucceed: and reportSender:failedWithError:. The report sender will send the latter message from its connection:didFailWithError: method, passing along the error object it got.
I do hope you'll make this feature optional. Expect lots of angry/curious email from users (not to mention public warnings of “don't use this app because it phones home” on web pages) if you don't.
Just a quick note to say if anyone wants a good tutorial on implementing your own delegates as Peter is suggesting I do, I found this one:
http://cocoadevcentral.com/articles/000075.php
Check it out. It's excellent!

Resources