New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8181571: printing to CUPS fails on mac sandbox app #4861
8181571: printing to CUPS fails on mac sandbox app #4861
Conversation
|
@AlexanderScherbatiy The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
It is not clear how to write a test (automated or manual) for the fix. I run automated and manual The automated The following manual tests fail with and without the fix:
|
/label awt,2d |
@AlexanderScherbatiy |
/cc 2d |
@AlexanderScherbatiy The |
JDK-8247768 |
What is the relation between JDK-8247768 and the current pull request? |
private static String getDomainSocketPathname() { | ||
return domainSocketPathname; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will need to suppress deprecation warnings here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I add @SuppressWarnings("deprecation")
to the getDomainSocketPathname() method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SuppressWarnings("removal") is added for the isSandboxedApp() method.
IPPPrintService.debug_println(debugPrefix+"CUPS server "+getServer()+ | ||
" port "+getPort()); | ||
return canConnect(getServer(), getPort()); | ||
String server = getDomainSocketPathname() != null ? getDomainSocketPathname() : getServer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split this long line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
@@ -92,6 +94,13 @@ public Void run() { | |||
libFound = initIDs(); | |||
if (libFound) { | |||
cupsServer = getCupsServer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should wrap all the new lines in isMac()
Also can you explain the reasons for the logic that implies we may have a server starting with "/"
in which case your always change the cupServer to localhost even if it is not sandboxed ?
I ask because it seems to contradict what you pasted
"by the cupsServer() function and not changing the interface string to "localhost""
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic which replaces a server starting with "/" to localhost is the original logic which is implemented in native level in the getCupsServer() function:
if (strncmp(server, "/", 1) == 0) { |
The fix only moves this logic to the java level to store domainSocketPathname in case of sandboxed app on MacOS.
} | ||
return printerURIs; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if getCupsDefaultPrinters() doesn't find anything you always continue to the original code even though
it would seem that you know we are in a sandboxed app and it won't find anything ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the code to return null in case there are no printer names from j2d_cupsGetDests() function in a sandboxed on MacOS.
j2d_cupsFreeDests(num_dests, dests); | ||
DPRINTF("CUPSfuncs::bad alloc new array\n", "") | ||
(*env)->ExceptionClear(env); | ||
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this weird. What is the ExceptionClear for ? The only possible exception here is for
an OOME which might be thrown by NewObjectArray. So you clear that and then re-create it ?
And who do will catch this ? What's the point ? Maybe just clear and return null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The array creation error handling is implemented in the similar way as it is done in the getMedia() function.
The ExceptionClear() has been added to the getMedia() by 8031001: [Parfait] warnings from b121 for jdk/src/solaris/native/sun/awt: JNI-related warnings
I would prefer to have unified error handling in these methods. If ExceptionClear is not suitable in this place it would be better to recheck JDK-8031001 and update all places accordingly in a separate fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't agree with the apparent reasoning that "well that thing over there is wrong, so it's ok for me to add something here that's wrong too".
And the getMedia(..) case is different. It doesn't re-create the same exception.
It wants to create an OOME which is not actually thrown by GetStringUTFChars() since it needs to throw some exception and with an appropriate string reason.
And the clear there is just prudence since it is creating a new one and can't be 100% sure there isn't one pending.
In your case the JNI spec documents OOME
https://docs.oracle.com/en/java/javase/17/docs/specs/jni/functions.html#newobjectarray
So in your case it is pointless. Please just remote the Clear()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExceptionClear(env) is removed from the if (nameArray == NULL)
check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have said (as I did in the beginning) remove the clear - and the new throw - and just return null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JNU_ThrowOutOfMemoryError is removed from code where nameArray and utf_str are checked to NULL.
if (utf_str == NULL) { | ||
j2d_cupsFreeDests(num_dests, dests); | ||
DPRINTF("CUPSfuncs::bad alloc new string ->name\n", "") | ||
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar comments to above plus I am fairly sure you want to delete nameArray since it isn't returned.
For that matter if the NewString fails on the 4th printer you want to free the 3 previous ones too before returning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is updated to remove previously created strings and clear the nameArray in case of an error during new string creation.
@AlexanderScherbatiy This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
/label client |
@AlexanderScherbatiy |
/label remove awt,2d |
@AlexanderScherbatiy The label
|
Just some more details about code in CUPSPrinter class static initialization. The getCupsServer() native method from CUPSPrinter calls j2d_cupsServer() function to get the cups server. If the server name starts with "/" it is replaced to "localhost"
To keep the domain socket path name from j2d_cupsServer() call the fix moves the cups server name handling to the java side. The original domain socket path name is preserved in the CUPSPrinter class only for MacOS when sandboxed app is used. |
@AlexanderScherbatiy This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
Just a question. Should the fix have 2 reviewers? |
@AlexanderScherbatiy This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
I see that the fix has been inactive for several months. |
@AlexanderScherbatiy This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@AlexanderScherbatiy This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
/open |
@AlexanderScherbatiy This pull request is now open |
@AlexanderScherbatiy This change now passes all automated pre-integration checks. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 39 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.
|
/integrate |
Going to push as commit 3d4be14.
Your commit was automatically rebased without conflicts. |
@AlexanderScherbatiy Pushed as commit 3d4be14. |
The issue is reproduced on macOS Big Sur 11.0.1 with jdk 16.0.1+9.
Create a native macOS app from the Hello.java file, sign and run it in sandbox:
The signed app in sandbox shows null default printer and PrintServiceLookup.lookupPrintServices(null, null) returns "Unix Printer: lp".

The problem has been discussed on 2d-dev mail list:
https://mail.openjdk.java.net/pipermail/2d-dev/2017-June/008375.html
https://mail.openjdk.java.net/pipermail/2d-dev/2017-July/008418.html
According to the discussion:
The proposed solution is to use the domain socket pathname in httpConnect(...) cups function and cupsGetDests(...) to get list of printers from cups when the app is signed and is run in sandbox on MacOs.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/4861/head:pull/4861
$ git checkout pull/4861
Update a local copy of the PR:
$ git checkout pull/4861
$ git pull https://git.openjdk.java.net/jdk pull/4861/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 4861
View PR using the GUI difftool:
$ git pr show -t 4861
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/4861.diff