From 9e3c08db40b8916968b9f30096c7be3f00ce9647 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:44:51 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- docs/_addons/bzlink.py | 63 ++ docs/_search_template/searchbox.html | 16 + docs/_static/custom_theme.css | 71 ++ docs/_static/sphinx_design.css | 21 + docs/_static/sphinx_design.js | 72 ++ docs/_templates/breadcrumbs.html | 18 + docs/bug-mgmt/guides/bug-pipeline.rst | 37 + docs/bug-mgmt/guides/bug-types.rst | 29 + docs/bug-mgmt/guides/other-metadata.rst | 28 + docs/bug-mgmt/guides/priority.rst | 27 + docs/bug-mgmt/guides/severity.rst | 71 ++ docs/bug-mgmt/guides/status-flags.rst | 33 + docs/bug-mgmt/index.rst | 40 + docs/bug-mgmt/policies/new-feature-triage.rst | 55 + docs/bug-mgmt/policies/regressions-github.rst | 151 +++ docs/bug-mgmt/policies/triage-bugzilla.rst | 276 +++++ docs/bug-mgmt/processes/accessibility-review.md | 72 ++ docs/bug-mgmt/processes/doc-requests.rst | 39 + docs/bug-mgmt/processes/fixing-security-bugs.rst | 217 ++++ docs/bug-mgmt/processes/labels.rst | 155 +++ docs/bug-mgmt/processes/regressions.rst | 64 ++ docs/bug-mgmt/processes/security-approval.rst | 194 ++++ docs/bug-mgmt/processes/shared-bug-queues.rst | 34 + .../code-quality/coding-style/about-logins-rtl.png | Bin 0 -> 6257 bytes .../coding-style/about-protections-rtl.png | Bin 0 -> 2310 bytes .../code-quality/coding-style/coding_style_cpp.rst | 1150 ++++++++++++++++++++ .../coding-style/coding_style_general.rst | 18 + .../coding-style/coding_style_java.rst | 68 ++ docs/code-quality/coding-style/coding_style_js.rst | 147 +++ .../coding-style/coding_style_python.rst | 71 ++ docs/code-quality/coding-style/css_guidelines.rst | 572 ++++++++++ .../format_cpp_code_with_clang-format.rst | 272 +++++ docs/code-quality/coding-style/index.rst | 20 + docs/code-quality/coding-style/rtl_guidelines.rst | 356 ++++++ docs/code-quality/coding-style/svg_guidelines.rst | 347 ++++++ .../coding-style/using_cxx_in_firefox_code.rst | 1075 ++++++++++++++++++ docs/code-quality/index.rst | 185 ++++ docs/code-quality/lint/create.rst | 368 +++++++ docs/code-quality/lint/index.rst | 33 + docs/code-quality/lint/linters/android-format.rst | 31 + docs/code-quality/lint/linters/black.rst | 36 + docs/code-quality/lint/linters/clang-format.rst | 35 + docs/code-quality/lint/linters/clippy.rst | 36 + docs/code-quality/lint/linters/codespell.rst | 36 + .../lint/linters/eslint-plugin-mozilla.rst | 114 ++ .../eslint-plugin-mozilla/avoid-Date-timing.rst | 30 + .../eslint-plugin-mozilla/avoid-removeChild.rst | 20 + .../eslint-plugin-mozilla/balanced-listeners.rst | 20 + .../eslint-plugin-mozilla/balanced-observers.rst | 20 + .../consistent-if-bracing.rst | 23 + .../linters/eslint-plugin-mozilla/environment.rst | 76 ++ .../import-browser-window-globals.rst | 8 + .../import-content-task-globals.rst | 14 + .../eslint-plugin-mozilla/import-globals-from.rst | 18 + .../eslint-plugin-mozilla/import-globals.rst | 5 + .../import-headjs-globals.rst | 28 + .../lazy-getter-object-name.rst | 25 + .../mark-exported-symbols-as-used.rst | 23 + .../mark-test-function-used.rst | 8 + .../linters/eslint-plugin-mozilla/no-aArgs.rst | 22 + .../eslint-plugin-mozilla/no-addtask-setup.rst | 27 + .../no-arbitrary-setTimeout.rst | 23 + .../no-compare-against-boolean-literals.rst | 23 + .../eslint-plugin-mozilla/no-cu-reportError.rst | 23 + .../eslint-plugin-mozilla/no-define-cc-etc.rst | 23 + .../no-redeclare-with-import-autofix.rst | 21 + .../eslint-plugin-mozilla/no-throw-cr-literal.rst | 38 + .../no-useless-parameters.rst | 26 + .../no-useless-removeEventListener.rst | 20 + .../eslint-plugin-mozilla/no-useless-run-test.rst | 6 + .../prefer-boolean-length-check.rst | 24 + .../eslint-plugin-mozilla/prefer-formatValues.rst | 23 + .../eslint-plugin-mozilla/reject-addtask-only.rst | 6 + .../reject-chromeutils-import-params.rst | 22 + .../reject-eager-module-in-lazy-getter.rst | 35 + .../eslint-plugin-mozilla/reject-global-this.rst | 29 + .../reject-globalThis-modification.rst | 19 + ...reject-import-system-module-from-non-system.rst | 36 + .../reject-importGlobalProperties.rst | 45 + .../reject-lazy-imports-into-globals.rst | 36 + .../reject-mixing-eager-and-lazy.rst | 22 + .../reject-multiple-getters-calls.rst | 27 + .../reject-relative-requires.rst | 22 + .../reject-requires-await.rst | 20 + .../reject-scriptableunicodeconverter.rst | 13 + .../eslint-plugin-mozilla/reject-some-requires.rst | 6 + .../reject-top-level-await.rst | 26 + .../linters/eslint-plugin-mozilla/use-cc-etc.rst | 26 + .../use-chromeutils-generateqi.rst | 33 + .../use-chromeutils-import.rst | 24 + .../use-default-preference-values.rst | 19 + .../use-includes-instead-of-indexOf.rst | 21 + .../eslint-plugin-mozilla/use-isInstance.rst | 42 + .../eslint-plugin-mozilla/use-ownerGlobal.rst | 20 + .../eslint-plugin-mozilla/use-returnValue.rst | 20 + .../linters/eslint-plugin-mozilla/use-services.rst | 21 + .../eslint-plugin-mozilla/use-static-import.rst | 21 + .../eslint-plugin-mozilla/valid-ci-uses.rst | 42 + .../linters/eslint-plugin-mozilla/valid-lazy.rst | 55 + .../valid-services-property.rst | 30 + .../eslint-plugin-mozilla/valid-services.rst | 24 + .../var-only-at-top-level.rst | 21 + .../lint/linters/eslint-plugin-spidermonkey-js.rst | 18 + docs/code-quality/lint/linters/eslint.rst | 211 ++++ docs/code-quality/lint/linters/file-perm.rst | 42 + docs/code-quality/lint/linters/file-whitespace.rst | 38 + docs/code-quality/lint/linters/fluent-lint.rst | 47 + docs/code-quality/lint/linters/l10n.rst | 45 + docs/code-quality/lint/linters/license.rst | 39 + docs/code-quality/lint/linters/lintpref.rst | 32 + .../lint/linters/mingw-capitalization.rst | 28 + docs/code-quality/lint/linters/perfdocs.rst | 84 ++ docs/code-quality/lint/linters/rejected-words.rst | 28 + docs/code-quality/lint/linters/rstlinter.rst | 32 + docs/code-quality/lint/linters/ruff.rst | 44 + docs/code-quality/lint/linters/rustfmt.rst | 33 + docs/code-quality/lint/linters/stylelint.rst | 77 ++ docs/code-quality/lint/linters/trojan-source.rst | 34 + docs/code-quality/lint/linters/yamllint.rst | 31 + docs/code-quality/lint/mozlint.rst | 23 + docs/code-quality/lint/usage.rst | 133 +++ docs/code-quality/static-analysis/existing.rst | 245 +++++ docs/code-quality/static-analysis/index.rst | 30 + .../static-analysis/writing-new/adding-a-check.rst | 107 ++ .../writing-new/advanced-check-features.rst | 148 +++ .../static-analysis/writing-new/clang-query.rst | 167 +++ .../writing-new/documentation-expanded.png | Bin 0 -> 41142 bytes .../static-analysis/writing-new/index.rst | 14 + .../writing-new/matcher-cookbook.rst | 23 + .../writing-new/narrowing-matcher.png | Bin 0 -> 47851 bytes .../writing-new/narrowing-matcher.xcf | Bin 0 -> 79407 bytes .../writing-new/writing-matchers.rst | 199 ++++ docs/conf.py | 152 +++ docs/config.yml | 115 ++ docs/contributing/Code_Review_FAQ.rst | 93 ++ docs/contributing/build/artifact_builds.rst | 173 +++ .../contributing/build/building_mobile_firefox.rst | 34 + docs/contributing/build/supported.rst | 1 + .../committing_rules_and_responsibilities.rst | 198 ++++ docs/contributing/contributing_to_mozilla.rst | 63 ++ docs/contributing/contribution_quickref.rst | 369 +++++++ docs/contributing/debugging/capturing_minidump.rst | 259 +++++ .../debugging/debugging_a_hang_on_macos.rst | 10 + .../debugging/debugging_a_minidump.rst | 202 ++++ .../debugging/debugging_firefox_with_gdb.rst | 501 +++++++++ .../debugging/debugging_firefox_with_lldb.rst | 80 ++ .../debugging/debugging_firefox_with_rr.rst | 98 ++ .../debugging/debugging_firefox_with_valgrind.rst | 177 +++ docs/contributing/debugging/debugging_on_macos.rst | 359 ++++++ .../debugging/debugging_on_windows.rst | 330 ++++++ .../contributing/debugging/img/about-processes.png | Bin 0 -> 48363 bytes docs/contributing/debugging/img/about-support.png | Bin 0 -> 33803 bytes docs/contributing/debugging/img/crash-gmp.png | Bin 0 -> 6731 bytes docs/contributing/debugging/img/crash-gpu.png | Bin 0 -> 2184 bytes docs/contributing/debugging/img/crash-rdd.png | Bin 0 -> 102996 bytes docs/contributing/debugging/img/crashlist.jpg | Bin 0 -> 77200 bytes docs/contributing/debugging/img/crashreporter.png | Bin 0 -> 10065 bytes .../debugging/img/process-explorer.png | Bin 0 -> 37316 bytes docs/contributing/debugging/img/sdk-installer.png | Bin 0 -> 32390 bytes docs/contributing/debugging/img/tabcrashed.png | Bin 0 -> 39540 bytes .../debugging/img/windbg-in-startmenu.png | Bin 0 -> 48528 bytes docs/contributing/debugging/local_symbols.rst | 64 ++ .../debugging/process_dump_task_manager.rst | 69 ++ docs/contributing/debugging/stacktrace_report.rst | 153 +++ docs/contributing/debugging/stacktrace_windbg.rst | 232 ++++ .../debugging/understanding_crash_reports.rst | 325 ++++++ docs/contributing/directory_structure.rst | 565 ++++++++++ docs/contributing/editor.rst | 26 + docs/contributing/editors/emacs.rst | 121 ++ docs/contributing/editors/others.rst | 41 + docs/contributing/editors/vim.rst | 75 ++ docs/contributing/editors/vscode.rst | 179 +++ docs/contributing/engineering_show_and_tell.rst | 83 ++ docs/contributing/how_to_submit_a_patch.rst | 245 +++++ docs/contributing/img/auto_completion.gif | Bin 0 -> 61333 bytes docs/contributing/img/connection_done.png | Bin 0 -> 34017 bytes docs/contributing/img/diagnostic_error.gif | Bin 0 -> 201909 bytes docs/contributing/img/example-stack.png | Bin 0 -> 103888 bytes docs/contributing/img/find_references.gif | Bin 0 -> 142707 bytes docs/contributing/img/format_selection.gif | Bin 0 -> 206874 bytes docs/contributing/img/goto_definition.gif | Bin 0 -> 249396 bytes docs/contributing/img/remote_explorer.png | Bin 0 -> 53727 bytes docs/contributing/img/remote_explorer_add.png | Bin 0 -> 18579 bytes docs/contributing/img/remote_explorer_add_wind.png | Bin 0 -> 25862 bytes docs/contributing/img/rename_symbol.gif | Bin 0 -> 194963 bytes docs/contributing/img/type_hierarchy.gif | Bin 0 -> 138625 bytes docs/contributing/index.rst | 41 + .../contributing/pocket-guide-shipping-firefox.rst | 523 +++++++++ docs/contributing/reviewer_checklist.rst | 181 +++ docs/contributing/reviews.rst | 145 +++ docs/contributing/stack_quickref.rst | 166 +++ docs/contributing/vcs/mercurial.rst | 194 ++++ docs/contributing/vcs/mercurial_bundles.rst | 65 ++ .../crash-reporting/img/default-search-results.png | Bin 0 -> 74498 bytes .../img/default-search-results2.png | Bin 0 -> 97584 bytes docs/crash-reporting/img/facet-search-results.png | Bin 0 -> 19042 bytes docs/crash-reporting/img/facet-search-results2.png | Bin 0 -> 58106 bytes docs/crash-reporting/img/facet-search-results3.png | Bin 0 -> 25830 bytes .../img/narrower-search-results.png | Bin 0 -> 53573 bytes docs/crash-reporting/img/super-search-form.png | Bin 0 -> 26165 bytes docs/crash-reporting/img/super-search-form2.png | Bin 0 -> 28824 bytes docs/crash-reporting/img/super-search-form3.png | Bin 0 -> 40430 bytes docs/crash-reporting/index.rst | 52 + docs/crash-reporting/searching_crash_reports.rst | 257 +++++ docs/crash-reporting/uploading_symbol.rst | 49 + docs/gtest/index.rst | 312 ++++++ docs/index.rst | 71 ++ docs/jsdoc.json | 5 + docs/metrics/index.md | 6 + docs/nspr/about_nspr.rst | 154 +++ docs/nspr/creating_a_cookie_log.rst | 65 ++ docs/nspr/index.rst | 66 ++ docs/nspr/layeredpoll.rst | 118 ++ docs/nspr/listing.rst | 10 + docs/nspr/nonblocking_io_in_nspr.rst | 153 +++ docs/nspr/nonblockinglayeredio.rst | 94 ++ docs/nspr/nspr_build_instructions.rst | 136 +++ docs/nspr/nspr_contributor_guide.rst | 182 ++++ docs/nspr/nspr_poll_method.rst | 134 +++ docs/nspr/nspr_release_procedure.rst | 50 + ...spr_s_position_on_abrupt_thread_termination.rst | 88 ++ docs/nspr/optimizing_applications_for_nspr.rst | 45 + docs/nspr/platforms.rst | 145 +++ docs/nspr/process_forking_in_nspr.rst | 23 + docs/nspr/reference/anonymous_shared_memory.rst | 118 ++ docs/nspr/reference/atomic_operations.rst | 32 + docs/nspr/reference/cached_monitors.rst | 37 + docs/nspr/reference/condition_variables.rst | 50 + docs/nspr/reference/date_and_time.rst | 83 ++ docs/nspr/reference/dynamic_library_linking.rst | 114 ++ .../floating_point_number_to_string_conversion.rst | 24 + docs/nspr/reference/hash_tables.rst | 42 + docs/nspr/reference/i_o_functions.rst | 240 ++++ docs/nspr/reference/i_o_types.rst | 105 ++ docs/nspr/reference/index.rst | 289 +++++ docs/nspr/reference/interval_timing.rst | 72 ++ docs/nspr/reference/introduction_to_nspr.rst | 408 +++++++ docs/nspr/reference/ipc_semaphores.rst | 23 + docs/nspr/reference/linked_lists.rst | 36 + docs/nspr/reference/locks.rst | 42 + docs/nspr/reference/logging.rst | 116 ++ .../nspr/reference/long_long_(64-bit)_integers.rst | 32 + .../reference/memory_management_operations.rst | 49 + docs/nspr/reference/monitors.rst | 63 ++ docs/nspr/reference/named_shared_memory.rst | 95 ++ docs/nspr/reference/network_addresses.rst | 82 ++ docs/nspr/reference/nspr_error_handling.rst | 206 ++++ docs/nspr/reference/nspr_log_file.rst | 31 + docs/nspr/reference/nspr_log_modules.rst | 88 ++ docs/nspr/reference/nspr_types.rst | 180 +++ docs/nspr/reference/pl_comparestrings.rst | 27 + docs/nspr/reference/pl_comparevalues.rst | 27 + docs/nspr/reference/pl_hashstring.rst | 36 + docs/nspr/reference/pl_hashtableadd.rst | 52 + docs/nspr/reference/pl_hashtabledestroy.rst | 32 + .../reference/pl_hashtableenumerateentries.rst | 46 + docs/nspr/reference/pl_hashtablelookup.rst | 45 + docs/nspr/reference/pl_hashtableremove.rst | 46 + docs/nspr/reference/pl_newhashtable.rst | 67 ++ docs/nspr/reference/pl_strcpy.rst | 40 + docs/nspr/reference/pl_strdup.rst | 48 + docs/nspr/reference/pl_strfree.rst | 21 + docs/nspr/reference/pl_strlen.rst | 28 + docs/nspr/reference/plhashallocops.rst | 40 + docs/nspr/reference/plhashcomparator.rst | 41 + docs/nspr/reference/plhashentry.rst | 36 + docs/nspr/reference/plhashenumerator.rst | 41 + docs/nspr/reference/plhashfunction.rst | 22 + docs/nspr/reference/plhashnumber.rst | 29 + docs/nspr/reference/plhashtable.rst | 21 + docs/nspr/reference/pr_abort.rst | 21 + docs/nspr/reference/pr_accept.rst | 65 ++ docs/nspr/reference/pr_acceptread.rst | 73 ++ docs/nspr/reference/pr_access.rst | 41 + docs/nspr/reference/pr_append_link.rst | 32 + docs/nspr/reference/pr_assert.rst | 43 + docs/nspr/reference/pr_atomicadd.rst | 37 + docs/nspr/reference/pr_atomicdecrement.rst | 37 + docs/nspr/reference/pr_atomicincrement.rst | 37 + docs/nspr/reference/pr_atomicset.rst | 42 + docs/nspr/reference/pr_attachsharedmemory.rst | 44 + docs/nspr/reference/pr_attachthread.rst | 76 ++ docs/nspr/reference/pr_available.rst | 51 + docs/nspr/reference/pr_available64.rst | 51 + docs/nspr/reference/pr_bind.rst | 54 + docs/nspr/reference/pr_blockclockinterrupts.rst | 14 + docs/nspr/reference/pr_callback.rst | 24 + docs/nspr/reference/pr_calloc.rst | 42 + docs/nspr/reference/pr_callonce.rst | 35 + docs/nspr/reference/pr_canceljob.rst | 30 + docs/nspr/reference/pr_centermonitor.rst | 57 + docs/nspr/reference/pr_cexitmonitor.rst | 44 + docs/nspr/reference/pr_cleanup.rst | 39 + docs/nspr/reference/pr_clearinterrupt.rst | 29 + docs/nspr/reference/pr_clist_is_empty.rst | 28 + docs/nspr/reference/pr_close.rst | 40 + docs/nspr/reference/pr_closedir.rst | 47 + docs/nspr/reference/pr_closefilemap.rst | 40 + docs/nspr/reference/pr_closesemaphore.rst | 30 + docs/nspr/reference/pr_closesharedmemory.rst | 32 + docs/nspr/reference/pr_cnotify.rst | 43 + docs/nspr/reference/pr_cnotifyall.rst | 43 + docs/nspr/reference/pr_cnvtf.rst | 45 + docs/nspr/reference/pr_connect.rst | 67 ++ docs/nspr/reference/pr_connectcontinue.rst | 53 + docs/nspr/reference/pr_convertipv4addrtoipv6.rst | 30 + docs/nspr/reference/pr_createfilemap.rst | 66 ++ docs/nspr/reference/pr_createiolayerstub.rst | 46 + docs/nspr/reference/pr_createpipe.rst | 53 + docs/nspr/reference/pr_createthread.rst | 79 ++ docs/nspr/reference/pr_createthreadpool.rst | 43 + docs/nspr/reference/pr_cwait.rst | 63 ++ docs/nspr/reference/pr_delete.rst | 38 + docs/nspr/reference/pr_delete_.rst | 37 + docs/nspr/reference/pr_deletesemaphore.rst | 30 + docs/nspr/reference/pr_deletesharedmemory.rst | 32 + docs/nspr/reference/pr_destroycondvar.rst | 30 + docs/nspr/reference/pr_destroylock.rst | 30 + docs/nspr/reference/pr_destroymonitor.rst | 31 + docs/nspr/reference/pr_destroypollableevent.rst | 33 + docs/nspr/reference/pr_detachsharedmemory.rst | 35 + docs/nspr/reference/pr_detachthread.rst | 57 + docs/nspr/reference/pr_disableclockinterrupts.rst | 14 + docs/nspr/reference/pr_dtoa.rst | 93 ++ docs/nspr/reference/pr_entermonitor.rst | 41 + docs/nspr/reference/pr_enumerateaddrinfo.rst | 58 + docs/nspr/reference/pr_enumeratehostent.rst | 61 ++ docs/nspr/reference/pr_exitmonitor.rst | 44 + docs/nspr/reference/pr_explodetime.rst | 46 + docs/nspr/reference/pr_exportfilemapasstring.rst | 47 + docs/nspr/reference/pr_extern.rst | 30 + docs/nspr/reference/pr_familyinet.rst | 23 + docs/nspr/reference/pr_findsymbol.rst | 52 + docs/nspr/reference/pr_findsymbolandlibrary.rst | 59 + docs/nspr/reference/pr_free.rst | 33 + docs/nspr/reference/pr_freeaddrinfo.rst | 32 + docs/nspr/reference/pr_freeif.rst | 34 + docs/nspr/reference/pr_freelibraryname.rst | 39 + docs/nspr/reference/pr_getaddrinfobyname.rst | 48 + .../nspr/reference/pr_getcanonnamefromaddrinfo.rst | 33 + docs/nspr/reference/pr_getconnectstatus.rst | 48 + docs/nspr/reference/pr_getcurrentthread.rst | 32 + docs/nspr/reference/pr_getdefaultiomethods.rst | 31 + docs/nspr/reference/pr_getdesctype.rst | 58 + docs/nspr/reference/pr_geterror.rst | 23 + docs/nspr/reference/pr_geterrortext.rst | 32 + docs/nspr/reference/pr_geterrortextlength.rst | 22 + docs/nspr/reference/pr_getfileinfo.rst | 55 + docs/nspr/reference/pr_getfileinfo64.rst | 55 + docs/nspr/reference/pr_gethostbyaddr.rst | 57 + docs/nspr/reference/pr_gethostbyname.rst | 48 + docs/nspr/reference/pr_getidentitieslayer.rst | 48 + docs/nspr/reference/pr_getinheritedfilemap.rst | 44 + docs/nspr/reference/pr_getlayersidentity.rst | 30 + docs/nspr/reference/pr_getlibraryname.rst | 53 + docs/nspr/reference/pr_getlibrarypath.rst | 37 + docs/nspr/reference/pr_getnameforidentity.rst | 41 + docs/nspr/reference/pr_getopenfileinfo.rst | 54 + docs/nspr/reference/pr_getopenfileinfo64.rst | 56 + docs/nspr/reference/pr_getoserror.rst | 31 + docs/nspr/reference/pr_getpeername.rst | 35 + docs/nspr/reference/pr_getprotobyname.rst | 47 + docs/nspr/reference/pr_getprotobynumber.rst | 47 + docs/nspr/reference/pr_getrandomnoise.rst | 56 + docs/nspr/reference/pr_getsocketoption.rst | 40 + docs/nspr/reference/pr_getsockname.rst | 35 + docs/nspr/reference/pr_getspecialfd.rst | 56 + docs/nspr/reference/pr_getthreadpriority.rst | 23 + docs/nspr/reference/pr_getthreadprivate.rst | 38 + docs/nspr/reference/pr_getthreadscope.rst | 21 + docs/nspr/reference/pr_getuniqueidentity.rst | 49 + docs/nspr/reference/pr_gmtparameters.rst | 47 + docs/nspr/reference/pr_htonl.rst | 29 + docs/nspr/reference/pr_htons.rst | 29 + docs/nspr/reference/pr_implement.rst | 28 + docs/nspr/reference/pr_implodetime.rst | 36 + docs/nspr/reference/pr_importfilemapfromstring.rst | 39 + docs/nspr/reference/pr_importtcpsocket.rst | 70 ++ docs/nspr/reference/pr_init.rst | 44 + docs/nspr/reference/pr_init_clist.rst | 27 + docs/nspr/reference/pr_init_static_clist.rst | 32 + docs/nspr/reference/pr_initialize.rst | 63 ++ docs/nspr/reference/pr_initialized.rst | 23 + docs/nspr/reference/pr_initializenetaddr.rst | 80 ++ docs/nspr/reference/pr_insert_after.rst | 32 + docs/nspr/reference/pr_insert_before.rst | 32 + docs/nspr/reference/pr_insert_link.rst | 32 + docs/nspr/reference/pr_interrupt.rst | 71 ++ docs/nspr/reference/pr_intervalnow.rst | 50 + docs/nspr/reference/pr_intervaltomicroseconds.rst | 34 + docs/nspr/reference/pr_intervaltomilliseconds.rst | 34 + docs/nspr/reference/pr_intervaltoseconds.rst | 33 + docs/nspr/reference/pr_joinjob.rst | 30 + docs/nspr/reference/pr_jointhread.rst | 57 + docs/nspr/reference/pr_jointhreadpool.rst | 31 + docs/nspr/reference/pr_list_head.rst | 33 + docs/nspr/reference/pr_list_tail.rst | 33 + docs/nspr/reference/pr_listen.rst | 48 + docs/nspr/reference/pr_loadlibrary.rst | 46 + docs/nspr/reference/pr_localtimeparameters.rst | 39 + docs/nspr/reference/pr_lock.rst | 42 + docs/nspr/reference/pr_malloc.rst | 35 + docs/nspr/reference/pr_memmap.rst | 50 + docs/nspr/reference/pr_microsecondstointerval.rst | 30 + docs/nspr/reference/pr_millisecondstointerval.rst | 30 + docs/nspr/reference/pr_mkdir.rst | 67 ++ docs/nspr/reference/pr_msec_per_sec.rst | 16 + docs/nspr/reference/pr_name.rst | 18 + docs/nspr/reference/pr_netaddrtostring.rst | 50 + docs/nspr/reference/pr_netdb_buf_size.rst | 20 + docs/nspr/reference/pr_new.rst | 36 + docs/nspr/reference/pr_newcondvar.rst | 34 + docs/nspr/reference/pr_newlock.rst | 30 + docs/nspr/reference/pr_newmonitor.rst | 31 + docs/nspr/reference/pr_newpollableevent.rst | 24 + docs/nspr/reference/pr_newprocessattr.rst | 39 + docs/nspr/reference/pr_newtcpsocket.rst | 56 + docs/nspr/reference/pr_newthreadprivateindex.rst | 65 ++ docs/nspr/reference/pr_newudpsocket.rst | 46 + docs/nspr/reference/pr_newzap.rst | 38 + docs/nspr/reference/pr_next_link.rst | 35 + docs/nspr/reference/pr_normalizetime.rst | 62 ++ docs/nspr/reference/pr_notify.rst | 48 + docs/nspr/reference/pr_notifyall.rst | 46 + docs/nspr/reference/pr_notifyallcondvar.rst | 35 + docs/nspr/reference/pr_notifycondvar.rst | 49 + docs/nspr/reference/pr_now.rst | 38 + docs/nspr/reference/pr_nsec_per_msec.rst | 16 + docs/nspr/reference/pr_nsec_per_sec.rst | 16 + docs/nspr/reference/pr_ntohl.rst | 29 + docs/nspr/reference/pr_ntohs.rst | 29 + docs/nspr/reference/pr_open.rst | 117 ++ docs/nspr/reference/pr_openanonfilemap.rst | 51 + docs/nspr/reference/pr_opendir.rst | 41 + docs/nspr/reference/pr_opensemaphore.rst | 58 + docs/nspr/reference/pr_opensharedmemory.rst | 68 ++ docs/nspr/reference/pr_opentcpsocket.rst | 59 + docs/nspr/reference/pr_openudpsocket.rst | 49 + docs/nspr/reference/pr_poll.rst | 110 ++ docs/nspr/reference/pr_popiolayer.rst | 53 + docs/nspr/reference/pr_postsemaphore.rst | 30 + docs/nspr/reference/pr_prev_link.rst | 35 + .../pr_processattrsetinheritablefilemap.rst | 53 + docs/nspr/reference/pr_processexit.rst | 23 + docs/nspr/reference/pr_pushiolayer.rst | 87 ++ docs/nspr/reference/pr_queuejob.rst | 43 + docs/nspr/reference/pr_queuejob_connect.rst | 49 + docs/nspr/reference/pr_queuejob_read.rst | 46 + docs/nspr/reference/pr_queuejob_timer.rst | 49 + docs/nspr/reference/pr_queuejob_write.rst | 46 + docs/nspr/reference/pr_queuejobaccept.rst | 46 + docs/nspr/reference/pr_read.rst | 50 + docs/nspr/reference/pr_readdir.rst | 93 ++ docs/nspr/reference/pr_realloc.rst | 43 + docs/nspr/reference/pr_recv.rst | 56 + docs/nspr/reference/pr_recvfrom.rst | 62 ++ docs/nspr/reference/pr_remove_and_init_link.rst | 29 + docs/nspr/reference/pr_remove_link.rst | 27 + docs/nspr/reference/pr_rename.rst | 45 + docs/nspr/reference/pr_rmdir.rst | 46 + docs/nspr/reference/pr_secondstointerval.rst | 30 + docs/nspr/reference/pr_seek.rst | 85 ++ docs/nspr/reference/pr_seek64.rst | 73 ++ docs/nspr/reference/pr_send.rst | 56 + docs/nspr/reference/pr_sendto.rst | 58 + docs/nspr/reference/pr_setconcurrency.rst | 42 + docs/nspr/reference/pr_seterror.rst | 35 + docs/nspr/reference/pr_seterrortext.rst | 43 + docs/nspr/reference/pr_setlibrarypath.rst | 45 + docs/nspr/reference/pr_setpollableevent.rst | 32 + docs/nspr/reference/pr_setsocketoption.rst | 45 + docs/nspr/reference/pr_setthreadpriority.rst | 37 + docs/nspr/reference/pr_setthreadprivate.rst | 56 + docs/nspr/reference/pr_shutdown.rst | 57 + docs/nspr/reference/pr_shutdownthreadpool.rst | 30 + docs/nspr/reference/pr_sleep.rst | 52 + docs/nspr/reference/pr_static_assert.rst | 46 + docs/nspr/reference/pr_stringtonetaddr.rst | 48 + docs/nspr/reference/pr_strtod.rst | 50 + docs/nspr/reference/pr_sync.rst | 40 + docs/nspr/reference/pr_tickspersecond.rst | 36 + docs/nspr/reference/pr_transmitfile.rst | 76 ++ docs/nspr/reference/pr_unblockclockinterrupts.rst | 14 + docs/nspr/reference/pr_unloadlibrary.rst | 41 + docs/nspr/reference/pr_unlock.rst | 43 + docs/nspr/reference/pr_unmap.rst | 45 + docs/nspr/reference/pr_usec_per_msec.rst | 16 + docs/nspr/reference/pr_usec_per_sec.rst | 16 + docs/nspr/reference/pr_version.rst | 19 + docs/nspr/reference/pr_versioncheck.rst | 50 + docs/nspr/reference/pr_wait.rst | 82 ++ docs/nspr/reference/pr_waitcondvar.rst | 68 ++ docs/nspr/reference/pr_waitforpollableevent.rst | 33 + docs/nspr/reference/pr_waitsemaphore.rst | 42 + docs/nspr/reference/pr_write.rst | 50 + docs/nspr/reference/pr_writev.rst | 79 ++ docs/nspr/reference/praccesshow.rst | 17 + docs/nspr/reference/prbool.rst | 27 + docs/nspr/reference/prcalloncefn.rst | 22 + docs/nspr/reference/prcalloncetype.rst | 41 + docs/nspr/reference/prclist.rst | 27 + docs/nspr/reference/prcondvar.rst | 20 + docs/nspr/reference/prdescidentity.rst | 36 + docs/nspr/reference/prdir.rst | 26 + docs/nspr/reference/prerrorcode.rst | 30 + docs/nspr/reference/prexplodedtime.rst | 70 ++ docs/nspr/reference/prfiledesc.rst | 53 + docs/nspr/reference/prfileinfo.rst | 49 + docs/nspr/reference/prfileinfo64.rst | 47 + docs/nspr/reference/prfilemap.rst | 27 + docs/nspr/reference/prfileprivate.rst | 24 + docs/nspr/reference/prfiletype.rst | 34 + docs/nspr/reference/prfloat64.rst | 15 + docs/nspr/reference/prhostent.rst | 69 ++ docs/nspr/reference/print16.rst | 14 + docs/nspr/reference/print32.rst | 22 + docs/nspr/reference/print64.rst | 22 + docs/nspr/reference/print8.rst | 14 + docs/nspr/reference/printervaltime.rst | 72 ++ docs/nspr/reference/printn.rst | 17 + docs/nspr/reference/priomethods.rst | 132 +++ docs/nspr/reference/pripv6addr.rst | 26 + docs/nspr/reference/prjob.rst | 10 + docs/nspr/reference/prjobfn.rst | 12 + docs/nspr/reference/prjobiodesc.rst | 16 + docs/nspr/reference/prlibrary.rst | 22 + docs/nspr/reference/prlinger.rst | 56 + docs/nspr/reference/prlock.rst | 22 + docs/nspr/reference/prlogmoduleinfo.rst | 23 + docs/nspr/reference/prlogmodulelevel.rst | 26 + docs/nspr/reference/prmcastrequest.rst | 40 + docs/nspr/reference/prmonitor.rst | 15 + docs/nspr/reference/prnetaddr.rst | 85 ++ docs/nspr/reference/process_initialization.rst | 63 ++ ...s_management_and_interprocess_communication.rst | 64 ++ docs/nspr/reference/prpackedbool.rst | 20 + docs/nspr/reference/prprimordialfn.rst | 19 + docs/nspr/reference/prprocess.rst | 20 + docs/nspr/reference/prprocessattr.rst | 23 + docs/nspr/reference/prprotoent.rst | 37 + docs/nspr/reference/prptrdiff.rst | 14 + docs/nspr/reference/prseekwhence.rst | 35 + docs/nspr/reference/prsize.rst | 15 + docs/nspr/reference/prsocketoptiondata.rst | 83 ++ docs/nspr/reference/prsockoption.rst | 79 ++ docs/nspr/reference/prstaticlinktable.rst | 22 + docs/nspr/reference/prstatus.rst | 14 + docs/nspr/reference/prthread.rst | 26 + docs/nspr/reference/prthreadpool.rst | 10 + docs/nspr/reference/prthreadpriority.rst | 62 ++ docs/nspr/reference/prthreadprivatedtor.rst | 24 + docs/nspr/reference/prthreadscope.rst | 56 + docs/nspr/reference/prthreadstack.rst | 31 + docs/nspr/reference/prthreadstate.rst | 54 + docs/nspr/reference/prthreadtype.rst | 40 + docs/nspr/reference/prtime.rst | 33 + docs/nspr/reference/prtimeparameters.rst | 54 + docs/nspr/reference/prtimeparamfn.rst | 24 + docs/nspr/reference/pruint16.rst | 14 + docs/nspr/reference/pruint32.rst | 22 + docs/nspr/reference/pruint64.rst | 22 + docs/nspr/reference/pruint8.rst | 15 + docs/nspr/reference/pruintn.rst | 17 + docs/nspr/reference/prunichar.rst | 18 + docs/nspr/reference/pruptrdiff.rst | 14 + docs/nspr/reference/random_number_generator.rst | 12 + docs/nspr/reference/string_operations.rst | 11 + docs/nspr/reference/thread_pools.rst | 41 + .../reference/thread_synchronization_sample.rst | 2 + docs/nspr/reference/threads.rst | 129 +++ docs/nspr/running_nspr_tests.rst | 95 ++ .../using_io_timeouts_and_interrupts_on_nt.rst | 131 +++ docs/performance/Benchmarking.md | 98 ++ docs/performance/GPU_performance.md | 42 + docs/performance/activity_monitor_and_top.md | 165 +++ ...automated_performance_testing_and_sheriffing.md | 24 + docs/performance/bestpractices.md | 578 ++++++++++ docs/performance/build_metrics/build_metrics.md | 31 + docs/performance/dtrace.md | 49 + docs/performance/img/ActMon-Energy.png | Bin 0 -> 148867 bytes docs/performance/img/EJCrt4N.png | Bin 0 -> 331906 bytes docs/performance/img/PerfDotHTMLRedLines.png | Bin 0 -> 8383 bytes docs/performance/img/annotation.png | Bin 0 -> 150000 bytes docs/performance/img/battery-status-menu.png | Bin 0 -> 26645 bytes docs/performance/img/dominators-1.png | Bin 0 -> 28248 bytes docs/performance/img/dominators-10.png | Bin 0 -> 22011 bytes docs/performance/img/dominators-2.png | Bin 0 -> 29454 bytes docs/performance/img/dominators-3.png | Bin 0 -> 33064 bytes docs/performance/img/dominators-4.png | Bin 0 -> 40001 bytes docs/performance/img/dominators-5.png | Bin 0 -> 31844 bytes docs/performance/img/dominators-6.png | Bin 0 -> 56667 bytes docs/performance/img/dominators-7.png | Bin 0 -> 26682 bytes docs/performance/img/dominators-8.png | Bin 0 -> 26678 bytes docs/performance/img/dominators-9.png | Bin 0 -> 45509 bytes docs/performance/img/memory-1-small.png | Bin 0 -> 12408 bytes docs/performance/img/memory-2-small.png | Bin 0 -> 20870 bytes docs/performance/img/memory-3-small.png | Bin 0 -> 20962 bytes docs/performance/img/memory-4-small.png | Bin 0 -> 20940 bytes docs/performance/img/memory-5-small.png | Bin 0 -> 21140 bytes docs/performance/img/memory-6-small.png | Bin 0 -> 20922 bytes docs/performance/img/memory-7-small.png | Bin 0 -> 20555 bytes .../memory-graph-dominator-multiple-references.svg | 4 + docs/performance/img/memory-graph-dominators.svg | 4 + .../img/memory-graph-immediate-dominator.svg | 4 + docs/performance/img/memory-graph-unreachable.svg | 4 + docs/performance/img/memory-graph.svg | 4 + .../performance/img/memory-tool-aggregate-view.png | Bin 0 -> 55175 bytes .../img/memory-tool-call-stack-expanded.png | Bin 0 -> 69021 bytes docs/performance/img/memory-tool-call-stack.png | Bin 0 -> 37960 bytes docs/performance/img/memory-tool-in-group-icon.png | Bin 0 -> 6376 bytes .../img/memory-tool-in-group-retaining-paths.png | Bin 0 -> 47488 bytes docs/performance/img/memory-tool-in-group.png | Bin 0 -> 32277 bytes .../img/memory-tool-inverted-call-stack.png | Bin 0 -> 42582 bytes docs/performance/img/memory-tool-switch-view.png | Bin 0 -> 26038 bytes docs/performance/img/monsters.svg | 4 + docs/performance/img/pid.png | Bin 0 -> 43742 bytes docs/performance/img/power-planes.jpg | Bin 0 -> 85483 bytes docs/performance/img/rendering.png | Bin 0 -> 103379 bytes docs/performance/img/reportingperf1.png | Bin 0 -> 10237 bytes docs/performance/img/reportingperf2.png | Bin 0 -> 27651 bytes docs/performance/img/reportingperf3.png | Bin 0 -> 20182 bytes docs/performance/img/treemap-bbc.png | Bin 0 -> 48965 bytes docs/performance/img/treemap-domnodes.png | Bin 0 -> 10998 bytes docs/performance/img/treemap-monsters.png | Bin 0 -> 20713 bytes docs/performance/index.md | 53 + docs/performance/intel_power_gadget.md | 56 + docs/performance/jit_profiling_with_perf.md | 119 ++ docs/performance/memory/DOM_allocation_example.md | 57 + docs/performance/memory/about_colon_memory.md | 274 +++++ docs/performance/memory/aggregate_view.md | 198 ++++ docs/performance/memory/awsy.md | 22 + docs/performance/memory/basic_operations.md | 82 ++ docs/performance/memory/bloatview.md | 245 +++++ docs/performance/memory/dmd.md | 489 +++++++++ docs/performance/memory/dominators.md | 90 ++ docs/performance/memory/dominators_view.md | 221 ++++ docs/performance/memory/gc_and_cc_logs.md | 109 ++ docs/performance/memory/heap_scan_mode.md | 313 ++++++ docs/performance/memory/leak_gauge.md | 45 + .../memory/leak_hunting_strategies_and_tips.md | 219 ++++ docs/performance/memory/memory.md | 64 ++ docs/performance/memory/monster_example.md | 79 ++ .../memory/refcount_tracing_and_balancing.md | 235 ++++ docs/performance/memory/tree_map_view.md | 62 ++ docs/performance/perf.md | 57 + docs/performance/perfstats.md | 30 + .../platform_microbenchmarks.md | 21 + docs/performance/power_profiling_overview.md | 326 ++++++ docs/performance/powermetrics.md | 167 +++ .../profiling_with_concurrency_visualizer.md | 5 + docs/performance/profiling_with_instruments.md | 110 ++ docs/performance/profiling_with_xperf.md | 180 +++ docs/performance/profiling_with_zoom.md | 5 + .../performance/reporting_a_performance_problem.md | 94 ++ docs/performance/scroll-linked_effects.md | 177 +++ docs/performance/sorting_algorithms_comparison.md | 52 + docs/performance/timerfirings_logging.md | 136 +++ docs/performance/tools_power_rapl.md | 113 ++ docs/performance/turbostat.md | 50 + docs/setup/building_with_debug_symbols.rst | 61 ++ docs/setup/configuring_build_options.rst | 404 +++++++ docs/setup/contributing_code.rst | 181 +++ docs/setup/index.rst | 25 + docs/setup/linux_32bit_build_on_64bit_OS.rst | 37 + docs/setup/linux_build.rst | 151 +++ docs/setup/macos_build.rst | 122 +++ docs/setup/windows_build.rst | 181 +++ docs/testing-rust-code/index.md | 123 +++ docs/update-infrastructure/index.md | 36 + docs/writing-rust-code/basics.md | 84 ++ docs/writing-rust-code/cpp-interop.md | 240 ++++ docs/writing-rust-code/index.md | 16 + docs/writing-rust-code/uniffi.md | 70 ++ docs/writing-rust-code/update-policy.md | 150 +++ docs/writing-rust-code/xpcom.md | 120 ++ 675 files changed, 42625 insertions(+) create mode 100644 docs/_addons/bzlink.py create mode 100644 docs/_search_template/searchbox.html create mode 100644 docs/_static/custom_theme.css create mode 100644 docs/_static/sphinx_design.css create mode 100644 docs/_static/sphinx_design.js create mode 100644 docs/_templates/breadcrumbs.html create mode 100644 docs/bug-mgmt/guides/bug-pipeline.rst create mode 100644 docs/bug-mgmt/guides/bug-types.rst create mode 100644 docs/bug-mgmt/guides/other-metadata.rst create mode 100644 docs/bug-mgmt/guides/priority.rst create mode 100644 docs/bug-mgmt/guides/severity.rst create mode 100644 docs/bug-mgmt/guides/status-flags.rst create mode 100644 docs/bug-mgmt/index.rst create mode 100644 docs/bug-mgmt/policies/new-feature-triage.rst create mode 100644 docs/bug-mgmt/policies/regressions-github.rst create mode 100644 docs/bug-mgmt/policies/triage-bugzilla.rst create mode 100644 docs/bug-mgmt/processes/accessibility-review.md create mode 100644 docs/bug-mgmt/processes/doc-requests.rst create mode 100644 docs/bug-mgmt/processes/fixing-security-bugs.rst create mode 100644 docs/bug-mgmt/processes/labels.rst create mode 100644 docs/bug-mgmt/processes/regressions.rst create mode 100644 docs/bug-mgmt/processes/security-approval.rst create mode 100644 docs/bug-mgmt/processes/shared-bug-queues.rst create mode 100644 docs/code-quality/coding-style/about-logins-rtl.png create mode 100644 docs/code-quality/coding-style/about-protections-rtl.png create mode 100644 docs/code-quality/coding-style/coding_style_cpp.rst create mode 100644 docs/code-quality/coding-style/coding_style_general.rst create mode 100644 docs/code-quality/coding-style/coding_style_java.rst create mode 100644 docs/code-quality/coding-style/coding_style_js.rst create mode 100644 docs/code-quality/coding-style/coding_style_python.rst create mode 100644 docs/code-quality/coding-style/css_guidelines.rst create mode 100644 docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst create mode 100644 docs/code-quality/coding-style/index.rst create mode 100644 docs/code-quality/coding-style/rtl_guidelines.rst create mode 100644 docs/code-quality/coding-style/svg_guidelines.rst create mode 100644 docs/code-quality/coding-style/using_cxx_in_firefox_code.rst create mode 100644 docs/code-quality/index.rst create mode 100644 docs/code-quality/lint/create.rst create mode 100644 docs/code-quality/lint/index.rst create mode 100644 docs/code-quality/lint/linters/android-format.rst create mode 100644 docs/code-quality/lint/linters/black.rst create mode 100644 docs/code-quality/lint/linters/clang-format.rst create mode 100644 docs/code-quality/lint/linters/clippy.rst create mode 100644 docs/code-quality/lint/linters/codespell.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst create mode 100644 docs/code-quality/lint/linters/eslint.rst create mode 100644 docs/code-quality/lint/linters/file-perm.rst create mode 100644 docs/code-quality/lint/linters/file-whitespace.rst create mode 100644 docs/code-quality/lint/linters/fluent-lint.rst create mode 100644 docs/code-quality/lint/linters/l10n.rst create mode 100644 docs/code-quality/lint/linters/license.rst create mode 100644 docs/code-quality/lint/linters/lintpref.rst create mode 100644 docs/code-quality/lint/linters/mingw-capitalization.rst create mode 100644 docs/code-quality/lint/linters/perfdocs.rst create mode 100644 docs/code-quality/lint/linters/rejected-words.rst create mode 100644 docs/code-quality/lint/linters/rstlinter.rst create mode 100644 docs/code-quality/lint/linters/ruff.rst create mode 100644 docs/code-quality/lint/linters/rustfmt.rst create mode 100644 docs/code-quality/lint/linters/stylelint.rst create mode 100644 docs/code-quality/lint/linters/trojan-source.rst create mode 100644 docs/code-quality/lint/linters/yamllint.rst create mode 100644 docs/code-quality/lint/mozlint.rst create mode 100644 docs/code-quality/lint/usage.rst create mode 100644 docs/code-quality/static-analysis/existing.rst create mode 100644 docs/code-quality/static-analysis/index.rst create mode 100644 docs/code-quality/static-analysis/writing-new/adding-a-check.rst create mode 100644 docs/code-quality/static-analysis/writing-new/advanced-check-features.rst create mode 100644 docs/code-quality/static-analysis/writing-new/clang-query.rst create mode 100644 docs/code-quality/static-analysis/writing-new/documentation-expanded.png create mode 100644 docs/code-quality/static-analysis/writing-new/index.rst create mode 100644 docs/code-quality/static-analysis/writing-new/matcher-cookbook.rst create mode 100644 docs/code-quality/static-analysis/writing-new/narrowing-matcher.png create mode 100644 docs/code-quality/static-analysis/writing-new/narrowing-matcher.xcf create mode 100644 docs/code-quality/static-analysis/writing-new/writing-matchers.rst create mode 100644 docs/conf.py create mode 100644 docs/config.yml create mode 100644 docs/contributing/Code_Review_FAQ.rst create mode 100644 docs/contributing/build/artifact_builds.rst create mode 100644 docs/contributing/build/building_mobile_firefox.rst create mode 100644 docs/contributing/build/supported.rst create mode 100644 docs/contributing/committing_rules_and_responsibilities.rst create mode 100644 docs/contributing/contributing_to_mozilla.rst create mode 100644 docs/contributing/contribution_quickref.rst create mode 100644 docs/contributing/debugging/capturing_minidump.rst create mode 100644 docs/contributing/debugging/debugging_a_hang_on_macos.rst create mode 100644 docs/contributing/debugging/debugging_a_minidump.rst create mode 100644 docs/contributing/debugging/debugging_firefox_with_gdb.rst create mode 100644 docs/contributing/debugging/debugging_firefox_with_lldb.rst create mode 100644 docs/contributing/debugging/debugging_firefox_with_rr.rst create mode 100644 docs/contributing/debugging/debugging_firefox_with_valgrind.rst create mode 100644 docs/contributing/debugging/debugging_on_macos.rst create mode 100644 docs/contributing/debugging/debugging_on_windows.rst create mode 100644 docs/contributing/debugging/img/about-processes.png create mode 100644 docs/contributing/debugging/img/about-support.png create mode 100644 docs/contributing/debugging/img/crash-gmp.png create mode 100644 docs/contributing/debugging/img/crash-gpu.png create mode 100644 docs/contributing/debugging/img/crash-rdd.png create mode 100644 docs/contributing/debugging/img/crashlist.jpg create mode 100644 docs/contributing/debugging/img/crashreporter.png create mode 100644 docs/contributing/debugging/img/process-explorer.png create mode 100644 docs/contributing/debugging/img/sdk-installer.png create mode 100644 docs/contributing/debugging/img/tabcrashed.png create mode 100644 docs/contributing/debugging/img/windbg-in-startmenu.png create mode 100644 docs/contributing/debugging/local_symbols.rst create mode 100644 docs/contributing/debugging/process_dump_task_manager.rst create mode 100644 docs/contributing/debugging/stacktrace_report.rst create mode 100644 docs/contributing/debugging/stacktrace_windbg.rst create mode 100644 docs/contributing/debugging/understanding_crash_reports.rst create mode 100644 docs/contributing/directory_structure.rst create mode 100644 docs/contributing/editor.rst create mode 100644 docs/contributing/editors/emacs.rst create mode 100644 docs/contributing/editors/others.rst create mode 100644 docs/contributing/editors/vim.rst create mode 100644 docs/contributing/editors/vscode.rst create mode 100644 docs/contributing/engineering_show_and_tell.rst create mode 100644 docs/contributing/how_to_submit_a_patch.rst create mode 100644 docs/contributing/img/auto_completion.gif create mode 100644 docs/contributing/img/connection_done.png create mode 100644 docs/contributing/img/diagnostic_error.gif create mode 100644 docs/contributing/img/example-stack.png create mode 100644 docs/contributing/img/find_references.gif create mode 100644 docs/contributing/img/format_selection.gif create mode 100644 docs/contributing/img/goto_definition.gif create mode 100644 docs/contributing/img/remote_explorer.png create mode 100644 docs/contributing/img/remote_explorer_add.png create mode 100644 docs/contributing/img/remote_explorer_add_wind.png create mode 100644 docs/contributing/img/rename_symbol.gif create mode 100644 docs/contributing/img/type_hierarchy.gif create mode 100644 docs/contributing/index.rst create mode 100644 docs/contributing/pocket-guide-shipping-firefox.rst create mode 100644 docs/contributing/reviewer_checklist.rst create mode 100644 docs/contributing/reviews.rst create mode 100644 docs/contributing/stack_quickref.rst create mode 100644 docs/contributing/vcs/mercurial.rst create mode 100644 docs/contributing/vcs/mercurial_bundles.rst create mode 100644 docs/crash-reporting/img/default-search-results.png create mode 100644 docs/crash-reporting/img/default-search-results2.png create mode 100644 docs/crash-reporting/img/facet-search-results.png create mode 100644 docs/crash-reporting/img/facet-search-results2.png create mode 100644 docs/crash-reporting/img/facet-search-results3.png create mode 100644 docs/crash-reporting/img/narrower-search-results.png create mode 100644 docs/crash-reporting/img/super-search-form.png create mode 100644 docs/crash-reporting/img/super-search-form2.png create mode 100644 docs/crash-reporting/img/super-search-form3.png create mode 100644 docs/crash-reporting/index.rst create mode 100644 docs/crash-reporting/searching_crash_reports.rst create mode 100644 docs/crash-reporting/uploading_symbol.rst create mode 100644 docs/gtest/index.rst create mode 100644 docs/index.rst create mode 100644 docs/jsdoc.json create mode 100644 docs/metrics/index.md create mode 100644 docs/nspr/about_nspr.rst create mode 100644 docs/nspr/creating_a_cookie_log.rst create mode 100644 docs/nspr/index.rst create mode 100644 docs/nspr/layeredpoll.rst create mode 100644 docs/nspr/listing.rst create mode 100644 docs/nspr/nonblocking_io_in_nspr.rst create mode 100644 docs/nspr/nonblockinglayeredio.rst create mode 100644 docs/nspr/nspr_build_instructions.rst create mode 100644 docs/nspr/nspr_contributor_guide.rst create mode 100644 docs/nspr/nspr_poll_method.rst create mode 100644 docs/nspr/nspr_release_procedure.rst create mode 100644 docs/nspr/nspr_s_position_on_abrupt_thread_termination.rst create mode 100644 docs/nspr/optimizing_applications_for_nspr.rst create mode 100644 docs/nspr/platforms.rst create mode 100644 docs/nspr/process_forking_in_nspr.rst create mode 100644 docs/nspr/reference/anonymous_shared_memory.rst create mode 100644 docs/nspr/reference/atomic_operations.rst create mode 100644 docs/nspr/reference/cached_monitors.rst create mode 100644 docs/nspr/reference/condition_variables.rst create mode 100644 docs/nspr/reference/date_and_time.rst create mode 100644 docs/nspr/reference/dynamic_library_linking.rst create mode 100644 docs/nspr/reference/floating_point_number_to_string_conversion.rst create mode 100644 docs/nspr/reference/hash_tables.rst create mode 100644 docs/nspr/reference/i_o_functions.rst create mode 100644 docs/nspr/reference/i_o_types.rst create mode 100644 docs/nspr/reference/index.rst create mode 100644 docs/nspr/reference/interval_timing.rst create mode 100644 docs/nspr/reference/introduction_to_nspr.rst create mode 100644 docs/nspr/reference/ipc_semaphores.rst create mode 100644 docs/nspr/reference/linked_lists.rst create mode 100644 docs/nspr/reference/locks.rst create mode 100644 docs/nspr/reference/logging.rst create mode 100644 docs/nspr/reference/long_long_(64-bit)_integers.rst create mode 100644 docs/nspr/reference/memory_management_operations.rst create mode 100644 docs/nspr/reference/monitors.rst create mode 100644 docs/nspr/reference/named_shared_memory.rst create mode 100644 docs/nspr/reference/network_addresses.rst create mode 100644 docs/nspr/reference/nspr_error_handling.rst create mode 100644 docs/nspr/reference/nspr_log_file.rst create mode 100644 docs/nspr/reference/nspr_log_modules.rst create mode 100644 docs/nspr/reference/nspr_types.rst create mode 100644 docs/nspr/reference/pl_comparestrings.rst create mode 100644 docs/nspr/reference/pl_comparevalues.rst create mode 100644 docs/nspr/reference/pl_hashstring.rst create mode 100644 docs/nspr/reference/pl_hashtableadd.rst create mode 100644 docs/nspr/reference/pl_hashtabledestroy.rst create mode 100644 docs/nspr/reference/pl_hashtableenumerateentries.rst create mode 100644 docs/nspr/reference/pl_hashtablelookup.rst create mode 100644 docs/nspr/reference/pl_hashtableremove.rst create mode 100644 docs/nspr/reference/pl_newhashtable.rst create mode 100644 docs/nspr/reference/pl_strcpy.rst create mode 100644 docs/nspr/reference/pl_strdup.rst create mode 100644 docs/nspr/reference/pl_strfree.rst create mode 100644 docs/nspr/reference/pl_strlen.rst create mode 100644 docs/nspr/reference/plhashallocops.rst create mode 100644 docs/nspr/reference/plhashcomparator.rst create mode 100644 docs/nspr/reference/plhashentry.rst create mode 100644 docs/nspr/reference/plhashenumerator.rst create mode 100644 docs/nspr/reference/plhashfunction.rst create mode 100644 docs/nspr/reference/plhashnumber.rst create mode 100644 docs/nspr/reference/plhashtable.rst create mode 100644 docs/nspr/reference/pr_abort.rst create mode 100644 docs/nspr/reference/pr_accept.rst create mode 100644 docs/nspr/reference/pr_acceptread.rst create mode 100644 docs/nspr/reference/pr_access.rst create mode 100644 docs/nspr/reference/pr_append_link.rst create mode 100644 docs/nspr/reference/pr_assert.rst create mode 100644 docs/nspr/reference/pr_atomicadd.rst create mode 100644 docs/nspr/reference/pr_atomicdecrement.rst create mode 100644 docs/nspr/reference/pr_atomicincrement.rst create mode 100644 docs/nspr/reference/pr_atomicset.rst create mode 100644 docs/nspr/reference/pr_attachsharedmemory.rst create mode 100644 docs/nspr/reference/pr_attachthread.rst create mode 100644 docs/nspr/reference/pr_available.rst create mode 100644 docs/nspr/reference/pr_available64.rst create mode 100644 docs/nspr/reference/pr_bind.rst create mode 100644 docs/nspr/reference/pr_blockclockinterrupts.rst create mode 100644 docs/nspr/reference/pr_callback.rst create mode 100644 docs/nspr/reference/pr_calloc.rst create mode 100644 docs/nspr/reference/pr_callonce.rst create mode 100644 docs/nspr/reference/pr_canceljob.rst create mode 100644 docs/nspr/reference/pr_centermonitor.rst create mode 100644 docs/nspr/reference/pr_cexitmonitor.rst create mode 100644 docs/nspr/reference/pr_cleanup.rst create mode 100644 docs/nspr/reference/pr_clearinterrupt.rst create mode 100644 docs/nspr/reference/pr_clist_is_empty.rst create mode 100644 docs/nspr/reference/pr_close.rst create mode 100644 docs/nspr/reference/pr_closedir.rst create mode 100644 docs/nspr/reference/pr_closefilemap.rst create mode 100644 docs/nspr/reference/pr_closesemaphore.rst create mode 100644 docs/nspr/reference/pr_closesharedmemory.rst create mode 100644 docs/nspr/reference/pr_cnotify.rst create mode 100644 docs/nspr/reference/pr_cnotifyall.rst create mode 100644 docs/nspr/reference/pr_cnvtf.rst create mode 100644 docs/nspr/reference/pr_connect.rst create mode 100644 docs/nspr/reference/pr_connectcontinue.rst create mode 100644 docs/nspr/reference/pr_convertipv4addrtoipv6.rst create mode 100644 docs/nspr/reference/pr_createfilemap.rst create mode 100644 docs/nspr/reference/pr_createiolayerstub.rst create mode 100644 docs/nspr/reference/pr_createpipe.rst create mode 100644 docs/nspr/reference/pr_createthread.rst create mode 100644 docs/nspr/reference/pr_createthreadpool.rst create mode 100644 docs/nspr/reference/pr_cwait.rst create mode 100644 docs/nspr/reference/pr_delete.rst create mode 100644 docs/nspr/reference/pr_delete_.rst create mode 100644 docs/nspr/reference/pr_deletesemaphore.rst create mode 100644 docs/nspr/reference/pr_deletesharedmemory.rst create mode 100644 docs/nspr/reference/pr_destroycondvar.rst create mode 100644 docs/nspr/reference/pr_destroylock.rst create mode 100644 docs/nspr/reference/pr_destroymonitor.rst create mode 100644 docs/nspr/reference/pr_destroypollableevent.rst create mode 100644 docs/nspr/reference/pr_detachsharedmemory.rst create mode 100644 docs/nspr/reference/pr_detachthread.rst create mode 100644 docs/nspr/reference/pr_disableclockinterrupts.rst create mode 100644 docs/nspr/reference/pr_dtoa.rst create mode 100644 docs/nspr/reference/pr_entermonitor.rst create mode 100644 docs/nspr/reference/pr_enumerateaddrinfo.rst create mode 100644 docs/nspr/reference/pr_enumeratehostent.rst create mode 100644 docs/nspr/reference/pr_exitmonitor.rst create mode 100644 docs/nspr/reference/pr_explodetime.rst create mode 100644 docs/nspr/reference/pr_exportfilemapasstring.rst create mode 100644 docs/nspr/reference/pr_extern.rst create mode 100644 docs/nspr/reference/pr_familyinet.rst create mode 100644 docs/nspr/reference/pr_findsymbol.rst create mode 100644 docs/nspr/reference/pr_findsymbolandlibrary.rst create mode 100644 docs/nspr/reference/pr_free.rst create mode 100644 docs/nspr/reference/pr_freeaddrinfo.rst create mode 100644 docs/nspr/reference/pr_freeif.rst create mode 100644 docs/nspr/reference/pr_freelibraryname.rst create mode 100644 docs/nspr/reference/pr_getaddrinfobyname.rst create mode 100644 docs/nspr/reference/pr_getcanonnamefromaddrinfo.rst create mode 100644 docs/nspr/reference/pr_getconnectstatus.rst create mode 100644 docs/nspr/reference/pr_getcurrentthread.rst create mode 100644 docs/nspr/reference/pr_getdefaultiomethods.rst create mode 100644 docs/nspr/reference/pr_getdesctype.rst create mode 100644 docs/nspr/reference/pr_geterror.rst create mode 100644 docs/nspr/reference/pr_geterrortext.rst create mode 100644 docs/nspr/reference/pr_geterrortextlength.rst create mode 100644 docs/nspr/reference/pr_getfileinfo.rst create mode 100644 docs/nspr/reference/pr_getfileinfo64.rst create mode 100644 docs/nspr/reference/pr_gethostbyaddr.rst create mode 100644 docs/nspr/reference/pr_gethostbyname.rst create mode 100644 docs/nspr/reference/pr_getidentitieslayer.rst create mode 100644 docs/nspr/reference/pr_getinheritedfilemap.rst create mode 100644 docs/nspr/reference/pr_getlayersidentity.rst create mode 100644 docs/nspr/reference/pr_getlibraryname.rst create mode 100644 docs/nspr/reference/pr_getlibrarypath.rst create mode 100644 docs/nspr/reference/pr_getnameforidentity.rst create mode 100644 docs/nspr/reference/pr_getopenfileinfo.rst create mode 100644 docs/nspr/reference/pr_getopenfileinfo64.rst create mode 100644 docs/nspr/reference/pr_getoserror.rst create mode 100644 docs/nspr/reference/pr_getpeername.rst create mode 100644 docs/nspr/reference/pr_getprotobyname.rst create mode 100644 docs/nspr/reference/pr_getprotobynumber.rst create mode 100644 docs/nspr/reference/pr_getrandomnoise.rst create mode 100644 docs/nspr/reference/pr_getsocketoption.rst create mode 100644 docs/nspr/reference/pr_getsockname.rst create mode 100644 docs/nspr/reference/pr_getspecialfd.rst create mode 100644 docs/nspr/reference/pr_getthreadpriority.rst create mode 100644 docs/nspr/reference/pr_getthreadprivate.rst create mode 100644 docs/nspr/reference/pr_getthreadscope.rst create mode 100644 docs/nspr/reference/pr_getuniqueidentity.rst create mode 100644 docs/nspr/reference/pr_gmtparameters.rst create mode 100644 docs/nspr/reference/pr_htonl.rst create mode 100644 docs/nspr/reference/pr_htons.rst create mode 100644 docs/nspr/reference/pr_implement.rst create mode 100644 docs/nspr/reference/pr_implodetime.rst create mode 100644 docs/nspr/reference/pr_importfilemapfromstring.rst create mode 100644 docs/nspr/reference/pr_importtcpsocket.rst create mode 100644 docs/nspr/reference/pr_init.rst create mode 100644 docs/nspr/reference/pr_init_clist.rst create mode 100644 docs/nspr/reference/pr_init_static_clist.rst create mode 100644 docs/nspr/reference/pr_initialize.rst create mode 100644 docs/nspr/reference/pr_initialized.rst create mode 100644 docs/nspr/reference/pr_initializenetaddr.rst create mode 100644 docs/nspr/reference/pr_insert_after.rst create mode 100644 docs/nspr/reference/pr_insert_before.rst create mode 100644 docs/nspr/reference/pr_insert_link.rst create mode 100644 docs/nspr/reference/pr_interrupt.rst create mode 100644 docs/nspr/reference/pr_intervalnow.rst create mode 100644 docs/nspr/reference/pr_intervaltomicroseconds.rst create mode 100644 docs/nspr/reference/pr_intervaltomilliseconds.rst create mode 100644 docs/nspr/reference/pr_intervaltoseconds.rst create mode 100644 docs/nspr/reference/pr_joinjob.rst create mode 100644 docs/nspr/reference/pr_jointhread.rst create mode 100644 docs/nspr/reference/pr_jointhreadpool.rst create mode 100644 docs/nspr/reference/pr_list_head.rst create mode 100644 docs/nspr/reference/pr_list_tail.rst create mode 100644 docs/nspr/reference/pr_listen.rst create mode 100644 docs/nspr/reference/pr_loadlibrary.rst create mode 100644 docs/nspr/reference/pr_localtimeparameters.rst create mode 100644 docs/nspr/reference/pr_lock.rst create mode 100644 docs/nspr/reference/pr_malloc.rst create mode 100644 docs/nspr/reference/pr_memmap.rst create mode 100644 docs/nspr/reference/pr_microsecondstointerval.rst create mode 100644 docs/nspr/reference/pr_millisecondstointerval.rst create mode 100644 docs/nspr/reference/pr_mkdir.rst create mode 100644 docs/nspr/reference/pr_msec_per_sec.rst create mode 100644 docs/nspr/reference/pr_name.rst create mode 100644 docs/nspr/reference/pr_netaddrtostring.rst create mode 100644 docs/nspr/reference/pr_netdb_buf_size.rst create mode 100644 docs/nspr/reference/pr_new.rst create mode 100644 docs/nspr/reference/pr_newcondvar.rst create mode 100644 docs/nspr/reference/pr_newlock.rst create mode 100644 docs/nspr/reference/pr_newmonitor.rst create mode 100644 docs/nspr/reference/pr_newpollableevent.rst create mode 100644 docs/nspr/reference/pr_newprocessattr.rst create mode 100644 docs/nspr/reference/pr_newtcpsocket.rst create mode 100644 docs/nspr/reference/pr_newthreadprivateindex.rst create mode 100644 docs/nspr/reference/pr_newudpsocket.rst create mode 100644 docs/nspr/reference/pr_newzap.rst create mode 100644 docs/nspr/reference/pr_next_link.rst create mode 100644 docs/nspr/reference/pr_normalizetime.rst create mode 100644 docs/nspr/reference/pr_notify.rst create mode 100644 docs/nspr/reference/pr_notifyall.rst create mode 100644 docs/nspr/reference/pr_notifyallcondvar.rst create mode 100644 docs/nspr/reference/pr_notifycondvar.rst create mode 100644 docs/nspr/reference/pr_now.rst create mode 100644 docs/nspr/reference/pr_nsec_per_msec.rst create mode 100644 docs/nspr/reference/pr_nsec_per_sec.rst create mode 100644 docs/nspr/reference/pr_ntohl.rst create mode 100644 docs/nspr/reference/pr_ntohs.rst create mode 100644 docs/nspr/reference/pr_open.rst create mode 100644 docs/nspr/reference/pr_openanonfilemap.rst create mode 100644 docs/nspr/reference/pr_opendir.rst create mode 100644 docs/nspr/reference/pr_opensemaphore.rst create mode 100644 docs/nspr/reference/pr_opensharedmemory.rst create mode 100644 docs/nspr/reference/pr_opentcpsocket.rst create mode 100644 docs/nspr/reference/pr_openudpsocket.rst create mode 100644 docs/nspr/reference/pr_poll.rst create mode 100644 docs/nspr/reference/pr_popiolayer.rst create mode 100644 docs/nspr/reference/pr_postsemaphore.rst create mode 100644 docs/nspr/reference/pr_prev_link.rst create mode 100644 docs/nspr/reference/pr_processattrsetinheritablefilemap.rst create mode 100644 docs/nspr/reference/pr_processexit.rst create mode 100644 docs/nspr/reference/pr_pushiolayer.rst create mode 100644 docs/nspr/reference/pr_queuejob.rst create mode 100644 docs/nspr/reference/pr_queuejob_connect.rst create mode 100644 docs/nspr/reference/pr_queuejob_read.rst create mode 100644 docs/nspr/reference/pr_queuejob_timer.rst create mode 100644 docs/nspr/reference/pr_queuejob_write.rst create mode 100644 docs/nspr/reference/pr_queuejobaccept.rst create mode 100644 docs/nspr/reference/pr_read.rst create mode 100644 docs/nspr/reference/pr_readdir.rst create mode 100644 docs/nspr/reference/pr_realloc.rst create mode 100644 docs/nspr/reference/pr_recv.rst create mode 100644 docs/nspr/reference/pr_recvfrom.rst create mode 100644 docs/nspr/reference/pr_remove_and_init_link.rst create mode 100644 docs/nspr/reference/pr_remove_link.rst create mode 100644 docs/nspr/reference/pr_rename.rst create mode 100644 docs/nspr/reference/pr_rmdir.rst create mode 100644 docs/nspr/reference/pr_secondstointerval.rst create mode 100644 docs/nspr/reference/pr_seek.rst create mode 100644 docs/nspr/reference/pr_seek64.rst create mode 100644 docs/nspr/reference/pr_send.rst create mode 100644 docs/nspr/reference/pr_sendto.rst create mode 100644 docs/nspr/reference/pr_setconcurrency.rst create mode 100644 docs/nspr/reference/pr_seterror.rst create mode 100644 docs/nspr/reference/pr_seterrortext.rst create mode 100644 docs/nspr/reference/pr_setlibrarypath.rst create mode 100644 docs/nspr/reference/pr_setpollableevent.rst create mode 100644 docs/nspr/reference/pr_setsocketoption.rst create mode 100644 docs/nspr/reference/pr_setthreadpriority.rst create mode 100644 docs/nspr/reference/pr_setthreadprivate.rst create mode 100644 docs/nspr/reference/pr_shutdown.rst create mode 100644 docs/nspr/reference/pr_shutdownthreadpool.rst create mode 100644 docs/nspr/reference/pr_sleep.rst create mode 100644 docs/nspr/reference/pr_static_assert.rst create mode 100644 docs/nspr/reference/pr_stringtonetaddr.rst create mode 100644 docs/nspr/reference/pr_strtod.rst create mode 100644 docs/nspr/reference/pr_sync.rst create mode 100644 docs/nspr/reference/pr_tickspersecond.rst create mode 100644 docs/nspr/reference/pr_transmitfile.rst create mode 100644 docs/nspr/reference/pr_unblockclockinterrupts.rst create mode 100644 docs/nspr/reference/pr_unloadlibrary.rst create mode 100644 docs/nspr/reference/pr_unlock.rst create mode 100644 docs/nspr/reference/pr_unmap.rst create mode 100644 docs/nspr/reference/pr_usec_per_msec.rst create mode 100644 docs/nspr/reference/pr_usec_per_sec.rst create mode 100644 docs/nspr/reference/pr_version.rst create mode 100644 docs/nspr/reference/pr_versioncheck.rst create mode 100644 docs/nspr/reference/pr_wait.rst create mode 100644 docs/nspr/reference/pr_waitcondvar.rst create mode 100644 docs/nspr/reference/pr_waitforpollableevent.rst create mode 100644 docs/nspr/reference/pr_waitsemaphore.rst create mode 100644 docs/nspr/reference/pr_write.rst create mode 100644 docs/nspr/reference/pr_writev.rst create mode 100644 docs/nspr/reference/praccesshow.rst create mode 100644 docs/nspr/reference/prbool.rst create mode 100644 docs/nspr/reference/prcalloncefn.rst create mode 100644 docs/nspr/reference/prcalloncetype.rst create mode 100644 docs/nspr/reference/prclist.rst create mode 100644 docs/nspr/reference/prcondvar.rst create mode 100644 docs/nspr/reference/prdescidentity.rst create mode 100644 docs/nspr/reference/prdir.rst create mode 100644 docs/nspr/reference/prerrorcode.rst create mode 100644 docs/nspr/reference/prexplodedtime.rst create mode 100644 docs/nspr/reference/prfiledesc.rst create mode 100644 docs/nspr/reference/prfileinfo.rst create mode 100644 docs/nspr/reference/prfileinfo64.rst create mode 100644 docs/nspr/reference/prfilemap.rst create mode 100644 docs/nspr/reference/prfileprivate.rst create mode 100644 docs/nspr/reference/prfiletype.rst create mode 100644 docs/nspr/reference/prfloat64.rst create mode 100644 docs/nspr/reference/prhostent.rst create mode 100644 docs/nspr/reference/print16.rst create mode 100644 docs/nspr/reference/print32.rst create mode 100644 docs/nspr/reference/print64.rst create mode 100644 docs/nspr/reference/print8.rst create mode 100644 docs/nspr/reference/printervaltime.rst create mode 100644 docs/nspr/reference/printn.rst create mode 100644 docs/nspr/reference/priomethods.rst create mode 100644 docs/nspr/reference/pripv6addr.rst create mode 100644 docs/nspr/reference/prjob.rst create mode 100644 docs/nspr/reference/prjobfn.rst create mode 100644 docs/nspr/reference/prjobiodesc.rst create mode 100644 docs/nspr/reference/prlibrary.rst create mode 100644 docs/nspr/reference/prlinger.rst create mode 100644 docs/nspr/reference/prlock.rst create mode 100644 docs/nspr/reference/prlogmoduleinfo.rst create mode 100644 docs/nspr/reference/prlogmodulelevel.rst create mode 100644 docs/nspr/reference/prmcastrequest.rst create mode 100644 docs/nspr/reference/prmonitor.rst create mode 100644 docs/nspr/reference/prnetaddr.rst create mode 100644 docs/nspr/reference/process_initialization.rst create mode 100644 docs/nspr/reference/process_management_and_interprocess_communication.rst create mode 100644 docs/nspr/reference/prpackedbool.rst create mode 100644 docs/nspr/reference/prprimordialfn.rst create mode 100644 docs/nspr/reference/prprocess.rst create mode 100644 docs/nspr/reference/prprocessattr.rst create mode 100644 docs/nspr/reference/prprotoent.rst create mode 100644 docs/nspr/reference/prptrdiff.rst create mode 100644 docs/nspr/reference/prseekwhence.rst create mode 100644 docs/nspr/reference/prsize.rst create mode 100644 docs/nspr/reference/prsocketoptiondata.rst create mode 100644 docs/nspr/reference/prsockoption.rst create mode 100644 docs/nspr/reference/prstaticlinktable.rst create mode 100644 docs/nspr/reference/prstatus.rst create mode 100644 docs/nspr/reference/prthread.rst create mode 100644 docs/nspr/reference/prthreadpool.rst create mode 100644 docs/nspr/reference/prthreadpriority.rst create mode 100644 docs/nspr/reference/prthreadprivatedtor.rst create mode 100644 docs/nspr/reference/prthreadscope.rst create mode 100644 docs/nspr/reference/prthreadstack.rst create mode 100644 docs/nspr/reference/prthreadstate.rst create mode 100644 docs/nspr/reference/prthreadtype.rst create mode 100644 docs/nspr/reference/prtime.rst create mode 100644 docs/nspr/reference/prtimeparameters.rst create mode 100644 docs/nspr/reference/prtimeparamfn.rst create mode 100644 docs/nspr/reference/pruint16.rst create mode 100644 docs/nspr/reference/pruint32.rst create mode 100644 docs/nspr/reference/pruint64.rst create mode 100644 docs/nspr/reference/pruint8.rst create mode 100644 docs/nspr/reference/pruintn.rst create mode 100644 docs/nspr/reference/prunichar.rst create mode 100644 docs/nspr/reference/pruptrdiff.rst create mode 100644 docs/nspr/reference/random_number_generator.rst create mode 100644 docs/nspr/reference/string_operations.rst create mode 100644 docs/nspr/reference/thread_pools.rst create mode 100644 docs/nspr/reference/thread_synchronization_sample.rst create mode 100644 docs/nspr/reference/threads.rst create mode 100644 docs/nspr/running_nspr_tests.rst create mode 100644 docs/nspr/using_io_timeouts_and_interrupts_on_nt.rst create mode 100644 docs/performance/Benchmarking.md create mode 100644 docs/performance/GPU_performance.md create mode 100644 docs/performance/activity_monitor_and_top.md create mode 100644 docs/performance/automated_performance_testing_and_sheriffing.md create mode 100644 docs/performance/bestpractices.md create mode 100644 docs/performance/build_metrics/build_metrics.md create mode 100644 docs/performance/dtrace.md create mode 100644 docs/performance/img/ActMon-Energy.png create mode 100644 docs/performance/img/EJCrt4N.png create mode 100644 docs/performance/img/PerfDotHTMLRedLines.png create mode 100644 docs/performance/img/annotation.png create mode 100644 docs/performance/img/battery-status-menu.png create mode 100644 docs/performance/img/dominators-1.png create mode 100644 docs/performance/img/dominators-10.png create mode 100644 docs/performance/img/dominators-2.png create mode 100644 docs/performance/img/dominators-3.png create mode 100644 docs/performance/img/dominators-4.png create mode 100644 docs/performance/img/dominators-5.png create mode 100644 docs/performance/img/dominators-6.png create mode 100644 docs/performance/img/dominators-7.png create mode 100644 docs/performance/img/dominators-8.png create mode 100644 docs/performance/img/dominators-9.png create mode 100644 docs/performance/img/memory-1-small.png create mode 100644 docs/performance/img/memory-2-small.png create mode 100644 docs/performance/img/memory-3-small.png create mode 100644 docs/performance/img/memory-4-small.png create mode 100644 docs/performance/img/memory-5-small.png create mode 100644 docs/performance/img/memory-6-small.png create mode 100644 docs/performance/img/memory-7-small.png create mode 100644 docs/performance/img/memory-graph-dominator-multiple-references.svg create mode 100644 docs/performance/img/memory-graph-dominators.svg create mode 100644 docs/performance/img/memory-graph-immediate-dominator.svg create mode 100644 docs/performance/img/memory-graph-unreachable.svg create mode 100644 docs/performance/img/memory-graph.svg create mode 100644 docs/performance/img/memory-tool-aggregate-view.png create mode 100644 docs/performance/img/memory-tool-call-stack-expanded.png create mode 100644 docs/performance/img/memory-tool-call-stack.png create mode 100644 docs/performance/img/memory-tool-in-group-icon.png create mode 100644 docs/performance/img/memory-tool-in-group-retaining-paths.png create mode 100644 docs/performance/img/memory-tool-in-group.png create mode 100644 docs/performance/img/memory-tool-inverted-call-stack.png create mode 100644 docs/performance/img/memory-tool-switch-view.png create mode 100644 docs/performance/img/monsters.svg create mode 100644 docs/performance/img/pid.png create mode 100644 docs/performance/img/power-planes.jpg create mode 100644 docs/performance/img/rendering.png create mode 100644 docs/performance/img/reportingperf1.png create mode 100644 docs/performance/img/reportingperf2.png create mode 100644 docs/performance/img/reportingperf3.png create mode 100644 docs/performance/img/treemap-bbc.png create mode 100644 docs/performance/img/treemap-domnodes.png create mode 100644 docs/performance/img/treemap-monsters.png create mode 100644 docs/performance/index.md create mode 100644 docs/performance/intel_power_gadget.md create mode 100644 docs/performance/jit_profiling_with_perf.md create mode 100644 docs/performance/memory/DOM_allocation_example.md create mode 100644 docs/performance/memory/about_colon_memory.md create mode 100644 docs/performance/memory/aggregate_view.md create mode 100644 docs/performance/memory/awsy.md create mode 100644 docs/performance/memory/basic_operations.md create mode 100644 docs/performance/memory/bloatview.md create mode 100644 docs/performance/memory/dmd.md create mode 100644 docs/performance/memory/dominators.md create mode 100644 docs/performance/memory/dominators_view.md create mode 100644 docs/performance/memory/gc_and_cc_logs.md create mode 100644 docs/performance/memory/heap_scan_mode.md create mode 100644 docs/performance/memory/leak_gauge.md create mode 100644 docs/performance/memory/leak_hunting_strategies_and_tips.md create mode 100644 docs/performance/memory/memory.md create mode 100644 docs/performance/memory/monster_example.md create mode 100644 docs/performance/memory/refcount_tracing_and_balancing.md create mode 100644 docs/performance/memory/tree_map_view.md create mode 100644 docs/performance/perf.md create mode 100644 docs/performance/perfstats.md create mode 100644 docs/performance/platform_microbenchmarks/platform_microbenchmarks.md create mode 100644 docs/performance/power_profiling_overview.md create mode 100644 docs/performance/powermetrics.md create mode 100644 docs/performance/profiling_with_concurrency_visualizer.md create mode 100644 docs/performance/profiling_with_instruments.md create mode 100644 docs/performance/profiling_with_xperf.md create mode 100644 docs/performance/profiling_with_zoom.md create mode 100644 docs/performance/reporting_a_performance_problem.md create mode 100644 docs/performance/scroll-linked_effects.md create mode 100644 docs/performance/sorting_algorithms_comparison.md create mode 100644 docs/performance/timerfirings_logging.md create mode 100644 docs/performance/tools_power_rapl.md create mode 100644 docs/performance/turbostat.md create mode 100644 docs/setup/building_with_debug_symbols.rst create mode 100644 docs/setup/configuring_build_options.rst create mode 100644 docs/setup/contributing_code.rst create mode 100644 docs/setup/index.rst create mode 100644 docs/setup/linux_32bit_build_on_64bit_OS.rst create mode 100644 docs/setup/linux_build.rst create mode 100644 docs/setup/macos_build.rst create mode 100644 docs/setup/windows_build.rst create mode 100644 docs/testing-rust-code/index.md create mode 100644 docs/update-infrastructure/index.md create mode 100644 docs/writing-rust-code/basics.md create mode 100644 docs/writing-rust-code/cpp-interop.md create mode 100644 docs/writing-rust-code/index.md create mode 100644 docs/writing-rust-code/uniffi.md create mode 100644 docs/writing-rust-code/update-policy.md create mode 100644 docs/writing-rust-code/xpcom.md (limited to 'docs') diff --git a/docs/_addons/bzlink.py b/docs/_addons/bzlink.py new file mode 100644 index 0000000000..6bdbdac8c5 --- /dev/null +++ b/docs/_addons/bzlink.py @@ -0,0 +1,63 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import re + +from docutils.nodes import Text, paragraph, reference +from sphinx.transforms import SphinxTransform + + +class ConvertBugsToLinks(SphinxTransform): + # Convert text entries in paragraphs that are in the style of "bug xxxxx" + # to a hyperlink that leads to the appropriate bugzilla bug link. + + default_priority = 400 + bz_url = "https://bugzilla.mozilla.org/show_bug.cgi?id={0}" + bz_reg = r"bug[' '][0-9]\d*" + + def apply(self): + def check_if_paragraph(o): + return isinstance(o, paragraph) + + def check_if_text(o): + return ( + not isinstance(o.parent, reference) + and isinstance(o, Text) + and re.search(self.bz_reg, o, re.IGNORECASE) + ) + + changed = True + while changed: + changed = self.textToReferences(check_if_paragraph, check_if_text) + return + + def textToReferences(self, check_if_paragraph, check_if_text): + # Analyses the document and replaces from the paragraph nodes + # the Text element(s) that contain bz_reg matching strings. + # Whevever the matching strings are more than one and + # a correction is made, the function returns True. + + for node in self.document.traverse(check_if_paragraph): + for text in node.traverse(check_if_text): + bugs = re.findall(self.bz_reg, text, re.IGNORECASE) + if len(bugs) == 0: + continue + bug = bugs[0] + txtparts = text.split(bug, 1) + new_ref = reference( + bug, + bug, + refuri=self.bz_url.format(bug.split()[1]), + ) + txt_0 = Text(txtparts[0]) + txt_1 = Text(txtparts[1]) + text.parent.replace(text, [txt_0, new_ref, txt_1]) + if len(bugs) > 1: + return True + return False + + +def setup(app): + app.add_transform(ConvertBugsToLinks) + return diff --git a/docs/_search_template/searchbox.html b/docs/_search_template/searchbox.html new file mode 100644 index 0000000000..c854452119 --- /dev/null +++ b/docs/_search_template/searchbox.html @@ -0,0 +1,16 @@ + + +
+

{{ _('Quick search') }}

+ + +
diff --git a/docs/_static/custom_theme.css b/docs/_static/custom_theme.css new file mode 100644 index 0000000000..c8e34c03ca --- /dev/null +++ b/docs/_static/custom_theme.css @@ -0,0 +1,71 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Increase the size of the content */ +.wy-nav-content { + max-width: 80% !important; +} + +/* Increase the size of the tables */ +table.docutils { + width: 90%; +} + +/* Override the default values for multiline text in a table */ +table.docutils td, table.docutils th +{ + font-size: 16px !important; +} + +.rst-content .line-block { + margin-bottom: 0px !important; +} + +/* Add the strikethrough feature */ +span.strikethrough { + text-decoration: line-through; +} + +/* Better control over the table on this page */ +.matcher-cookbook td { + white-space: break-spaces !important; +} + +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: normal; +} + +img.center { + display: block; + margin: auto; +} + +img.border { + border: 1px solid black; + display: block; + margin: auto; +} + +.center { + text-align: center; +} + +/* Keyboard shortcuts styling */ +kbd { + background: linear-gradient(180deg,#f4f4f4,#d5d5d5); + background-color: #f4f4f4; + border: 1px solid #d5d5d5; + border-radius: 6px; + font-family: consolas,"Liberation Mono",courier,monospace; + font-size: .9rem; + font-weight: 700; + line-height: 2.3; + margin: 3px; + padding: 4px 6px 1px 6px; + white-space: nowrap; +} + +table.docutils { + width: 100%; +} diff --git a/docs/_static/sphinx_design.css b/docs/_static/sphinx_design.css new file mode 100644 index 0000000000..86d1ad7b08 --- /dev/null +++ b/docs/_static/sphinx_design.css @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* For Dropdown Link in panels of sphinx-panels */ +a.dropdown-link { + color: #DDD; + margin-left: 0.5em; + padding: 0.25em; + visibility: hidden; +} + +details.sd-dropdown:hover a.dropdown-link { + visibility: visible; +} + +a.dropdown-link:hover { + background-color: #36557c; + color: #ffffff; + text-decoration: none; +} diff --git a/docs/_static/sphinx_design.js b/docs/_static/sphinx_design.js new file mode 100644 index 0000000000..d080f2d634 --- /dev/null +++ b/docs/_static/sphinx_design.js @@ -0,0 +1,72 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +(function () { + "use strict"; + + var dropdownClassName = "sd-dropdown"; + + function getDropdownElement() { + var dropdownId = window.location.hash; + if (!dropdownId) { + return false; + } + + var dropdownElement = document.getElementById(dropdownId.substring(1)); + if ( + !dropdownElement || + !dropdownElement.classList.contains(dropdownClassName) + ) { + return false; + } + + return dropdownElement; + } + + function setupDropdownLink() { + var dropdowns = document.getElementsByClassName(dropdownClassName); + for (var i = 0; i < dropdowns.length; i++) { + for (var j = 0; j < dropdowns[i].classList.length; j++) { + if (dropdowns[i].classList[j].startsWith("anchor-id-")) { + dropdowns[i].id = dropdowns[i].classList[j].replace("anchor-id-", ""); + } + } + + var aTag = document.createElement("a"); + aTag.setAttribute("href", "#" + dropdowns[i].id); + aTag.classList.add("dropdown-link"); + aTag.innerHTML = "¶"; + + var summaryElement = + dropdowns[i].getElementsByClassName("sd-summary-title")[0]; + summaryElement.insertBefore( + aTag, + summaryElement.getElementsByClassName("docutils")[0] + ); + } + } + + function scrollToDropdown() { + var dropdownElement = getDropdownElement(); + if (dropdownElement) { + dropdownElement.open = true; + dropdownElement.scrollIntoView(true); + } + } + + // Initiallize dropdown link + window.addEventListener("DOMContentLoaded", () => { + if (document.getElementsByClassName(dropdownClassName).length) { + setupDropdownLink(); + window.onhashchange = scrollToDropdown; + } + }); + + // Scroll to and open the dropdown direct links + window.onload = () => { + if (document.getElementsByClassName(dropdownClassName).length) { + scrollToDropdown(); + } + }; +})(); diff --git a/docs/_templates/breadcrumbs.html b/docs/_templates/breadcrumbs.html new file mode 100644 index 0000000000..392db34504 --- /dev/null +++ b/docs/_templates/breadcrumbs.html @@ -0,0 +1,18 @@ + + +{%- extends "sphinx_rtd_theme/breadcrumbs.html" %} {% block breadcrumbs_aside %} +
  • + Report an issue + / {%- if show_source and has_source and sourcename %} + + {{ _('View page source') }} + {%- endif %} +
  • +{% endblock %} diff --git a/docs/bug-mgmt/guides/bug-pipeline.rst b/docs/bug-mgmt/guides/bug-pipeline.rst new file mode 100644 index 0000000000..a70adb0464 --- /dev/null +++ b/docs/bug-mgmt/guides/bug-pipeline.rst @@ -0,0 +1,37 @@ +Bug pipeline +============ + +For Firefox quality, Mozilla has different processes to report defects. In parallel, over the years, Mozilla developed many tools around bug management. + +.. mermaid:: + + graph TD + classDef tool fill:#f96; + + Community --> B(bugzilla.mozilla.org) + QA --> B + Foxfooding --> B + Fuzzing --> B + SA[Static/Dynamic analysis] --> B + P[Performance monitoring] --> B + Y[Test automation] --> B + Z[Crash detection] --> B + B --> C{Bug update} + C --> D[Metadata improvements] + C --> E[Component triage] + C --> F[Test case verification] + F --> BM{{Bugmon}}:::tool + F --> MR{{Mozregression}}:::tool + + D --> AN{{Autonag}}:::tool + E --> BB{{bugbug}}:::tool + D --> BB + +More details +------------ + +* :ref:`Fuzzing` +* `Autonag `_ - `Source `_ +* `Bugbug `_ - `Blog post about triage `_ / `Blog post about CI `_ +* `Bugmon `_ - `Source `_ +* `Mozregression `_ - `Source `_ diff --git a/docs/bug-mgmt/guides/bug-types.rst b/docs/bug-mgmt/guides/bug-types.rst new file mode 100644 index 0000000000..3626336de1 --- /dev/null +++ b/docs/bug-mgmt/guides/bug-types.rst @@ -0,0 +1,29 @@ +Bug Types +========= + +We organize bugs by type to make it easier to make triage decisions, get +the bug to the right person to make a decision, and understand release +quality. + +- **Defect** regression, crash, hang, security vulnerability and any + other reported issue +- **Enhancement** new feature, improvement in UI, performance, etc. and + any other request for user-facing enhancements to the product, not + engineering changes +- **Task** refactoring, removal, replacement, enabling or disabling of + functionality and any other engineering task + +All bug types need triage decisions. Engineering :ref:`triages defects and +tasks `. Product management :ref:`triages +enhancements `. + +It’s important to distinguish an enhancement from other types because +they use different triage queues. + +Distinguishing between defects and tasks is important because we want to +understand code quality and reduce the number of defects we introduce as +we work on new features and fix existing defects. + +When triaging, a task can be as important as a defect. A behind the +scenes change to how a thread is handled can affect performance as seen +by a user. diff --git a/docs/bug-mgmt/guides/other-metadata.rst b/docs/bug-mgmt/guides/other-metadata.rst new file mode 100644 index 0000000000..f1b94f16d8 --- /dev/null +++ b/docs/bug-mgmt/guides/other-metadata.rst @@ -0,0 +1,28 @@ +Other Bug Metadata +================== + +Performance +----------- + +- Use the ``perf`` keyword +- Add ``[qf:?]`` to the whiteboard if you think the Performance team + should look at this bug + +Privacy +------- + +- Use the ``privacy`` keyword + +User Security +------------- + +- Will this bug adversely affect Firefox users if left public? + + - Add to security group + +- Otherwise move bug to one of: + + - Core:: Security + - Firefox:: Security + - Toolkit:: Security + - Webkit:: Security diff --git a/docs/bug-mgmt/guides/priority.rst b/docs/bug-mgmt/guides/priority.rst new file mode 100644 index 0000000000..db0c8ee874 --- /dev/null +++ b/docs/bug-mgmt/guides/priority.rst @@ -0,0 +1,27 @@ +Priority Definitions +==================== + +We use these definitions across all components: + ++----------------------------------------+-----------------------------+ +| Priority | Description | ++========================================+=============================+ +| \- | No decision | ++----------------------------------------+-----------------------------+ +| P1 | Fix in the current release | +| | cycle | ++----------------------------------------+-----------------------------+ +| P2 | Fix in the next release | +| | cycle or the following | +| | (nightly + 1 or nightly + | +| | 2) | ++----------------------------------------+-----------------------------+ +| P3 | Backlog | ++----------------------------------------+-----------------------------+ +| P4 | Do not use, this priority | +| | is for web platform test | +| | bots | ++----------------------------------------+-----------------------------+ +| P5 | Will not fix, but will | +| | accept a patch | ++----------------------------------------+-----------------------------+ diff --git a/docs/bug-mgmt/guides/severity.rst b/docs/bug-mgmt/guides/severity.rst new file mode 100644 index 0000000000..c75870f471 --- /dev/null +++ b/docs/bug-mgmt/guides/severity.rst @@ -0,0 +1,71 @@ +Defect Severity +=============== + +Definition +---------- + +We use the ``severity`` field in Bugzilla to indicate the scope of a +bug's effect on Firefox. + +The field is display alongside the bug's priority. + +Values +------ + +Severity levels and their definitions are enumerated at https://wiki.mozilla.org/BMO/UserGuide/BugFields#bug_severity. + +By default, new bugs have a severity of ``--``. + +Examples of S1 bugs +^^^^^^^^^^^^^^^^^^^ + +- WebExtensions disabled for all users +- Web search not working from URL bar +- Crashes with data loss + +Examples of S2 bugs +^^^^^^^^^^^^^^^^^^^ + +Bugs that could reasonably be expected to cause a Firefox user to switch browsers, +either because the severity is bad enough, or the frequency of occurrence is high enough. + +- `Bug 1640441 `__ - Slack hangs + indefinitely in a onResize loop +- `Bug 1645651 `__ - Changes in + Reddit's comment section JS code makes selecting text slow on Nightly + +Bugs involving contractual partners (if not an S1) + +Bugs reported from QA + +- `Bug 1640913 `__ - because an + important message is not visible with the dark theme. It's not marked as S1 since the + issue is reproducible only on one OS and the functionality is not affected. +- `Bug 1641521 `__ - because videos + are not working on several sites with ETP on (default). This is not an S1 since turning + ETP off fixes the issue. + +Fuzzblocker bugs, which prevent fuzzing from making progress + +Examples of S3 bugs +^^^^^^^^^^^^^^^^^^^ + +Bugs filed by contributors as part of daily refactoring and maintenance of the code base. + +`Bug 1634171 `__ - Visual artifacts around circular images + +Bugs reported from QA + +- `Bug 1635105 `__ because + the associated steps to reproduce are uncommon, + and the issue is no longer reproducible after refresh. +- `Bug 1636063 `__ since it's + reproducible only on a specific web app, and only with a particular set of configurations. + + +Rules of thumb +-------------- + +- The severity of most bugs of type ``task`` and ``enhancement`` will be + ``N/A`` +- **Do not** assign bugs of type ``defect`` the severity ``N/A`` diff --git a/docs/bug-mgmt/guides/status-flags.rst b/docs/bug-mgmt/guides/status-flags.rst new file mode 100644 index 0000000000..04d252f596 --- /dev/null +++ b/docs/bug-mgmt/guides/status-flags.rst @@ -0,0 +1,33 @@ +Release Status Flags +==================== + +The flag ``status_firefoxNN`` has many values, here’s a cheat sheet. + +== ========== ========== ============ ================= +— ? unaffected affected fixed +== ========== ========== ============ ================= +? unaffected wontfix verified +\ affected fix-optional disabled +\ fixed verified disabled +== ========== ========== ============ ================= + +The headers of the table are values of the status flag. Each column are +the states reachable from the column headings. + +- ``---`` we don’t know whether Firefox N is affected +- ``?`` we don’t know whether Firefox N is affected, but we want to find + out. +- ``affected`` - present in this release +- ``unaffected`` - not present in this release +- ``fixed`` - a contributor has landed a change set in the tree + to address the issue +- ``verified`` - the fix has been verified by QA or other contributors +- ``disabled`` - the fix or the feature has been backed out or disabled +- ``verified disabled`` - QA or other contributors confirmed the fix or + the feature has been backed out or disabled +- ``wontfix`` - we have decided not to accept/uplift a fix for this + release cycle (it is not the same as the bug resolution WONTFIX). + This can also mean that we don’t know how to fix that and will ship + with this bug +- ``fix-optional`` - we would take a fix for the current release but + don’t consider it as important/blocking for the release diff --git a/docs/bug-mgmt/index.rst b/docs/bug-mgmt/index.rst new file mode 100644 index 0000000000..215b2e7317 --- /dev/null +++ b/docs/bug-mgmt/index.rst @@ -0,0 +1,40 @@ +Bug Handling +============ + +Guides +------ + +.. toctree:: + :maxdepth: 1 + :glob: + + guides/* + +Policies +-------- + +.. toctree:: + :maxdepth: 1 + :glob: + + policies/* + +Processes +--------- + +.. toctree:: + :maxdepth: 1 + :glob: + + processes/* + +Related documentation +--------------------- + +- `bugzilla.mozilla.org documentation `__ +- `bugzilla.mozilla.org field + definitions `__ +- `Lando + documentation `__ +- `Mozilla Phabricator (Code Review) + documentation `__ diff --git a/docs/bug-mgmt/policies/new-feature-triage.rst b/docs/bug-mgmt/policies/new-feature-triage.rst new file mode 100644 index 0000000000..7bc8022777 --- /dev/null +++ b/docs/bug-mgmt/policies/new-feature-triage.rst @@ -0,0 +1,55 @@ +New Feature Triage +================== + +Identifying Feature Requests +---------------------------- + +Bugs which request new features or enhancements should be of +type=\ ``enhancement``. + +Older bugs may also be feature requests if some or all of the following +are true: + +- Bugs with ``feature`` or similar in whiteboard or short description +- ``[RFE]`` in whiteboard, short description, or description +- Bugs not explicitly marked as a feature request, but appear to be + feature requests +- Bugs marked with ``feature`` keyword + +Initial Triage +-------------- + +Staff, contractors, and other contributors looking at new bugs in +*Firefox::Untriaged* and *::General* components should consider if a +bug, if not marked as a feature request, should be one, and if so: + +- Update the bug’s type to ``enhancement`` +- Determine which product and component the bug belongs to and update + it **or** + + - Use *needinfo* to ask a component’s triage owner or a module’s + owner where the request should go + +Product Manager Triage +---------------------- + +- The product manager for the component reviews bugs of type + ``enhancement`` + + - This review should be done a least weekly + +- Reassigns to another Product::Component if necessary **or** +- Determines next steps + + - Close bug as ``RESOLVED WONTFIX`` with comment as to why and + thanking submitter + - If bug is similar enough to work in roadmap, close bug as + ``RESOLVED DUPLICATE`` of the feature bug it is similar to + + - If there’s not a feature bug created already, then consider + making this bug the feature bug + + - Set type to ``enhancement`` + + - Set bug to ``P5`` priority with comment thanking submitter, and + explaining that the request will be considered for future roadmaps diff --git a/docs/bug-mgmt/policies/regressions-github.rst b/docs/bug-mgmt/policies/regressions-github.rst new file mode 100644 index 0000000000..1a3c6b2a4d --- /dev/null +++ b/docs/bug-mgmt/policies/regressions-github.rst @@ -0,0 +1,151 @@ +Regressions from GitHub +======================= + +Release Management and the weekly regression triage must be aware of the +status of all reported regressions in order to assure we are not +shipping known regressions in Firefox releases. + +If a team is using GitHub to manage their part of the Firefox project, +there’s a risk that those groups might not see a regression. + +We need an agreed to standard for how we keep track of these. + +Policy +------ + +*All Firefox components, even if their bugs are tracked off of Bugzilla, +must have a component in Bugzilla.* + +*If a regression bug is found in any of the release trains (Nightly, +Beta, Release, or ESR) and the bug is in a Firefox component which uses +an external repository, the regression must be tracked by a bug in +Bugzilla (whether or not the component in question uses an external +issue tracker).* + +*Unless approved by Release Management, any GitHub managed code with +open regressions will not be merged to mozilla-central. Even if the +regression is not code that has been previously merged into +mozilla-central.* + +*All Firefox code managed in GitHub which uses GitHub to manage +issues* `must use the shared +tags `__. + +Comments +~~~~~~~~ + +The bug **must** have the regression keyword. + +The bug **must** have release flags set. + +If the team works in an external bug tracker, then the Bugzilla bug +**must** reference, using the see-also field, the URL of the bug in the +external tracker. + +The bug **must not** be RESOLVED until the code from the external +repository containing the change set for the bug has landed in +mozilla-central. When the change set lands in mozilla-central, the +Bugzilla tracking bug should be set to RESOLVED FIXED and release status +flags should be updated to reflect the release trains the fix has been +landed or uplifted into. + +If the change set containing the patch for the regression is reverted +from mozilla-central, for any reason, then the tracking bug for the +regression **must** be set to REOPENED and the release status flags +updated accordingly. + +If the change set containing the patch for the bug is backed out, for +any reason, the bug must be reopened and the status flags on the +Bugzilla tracking bug updated. + +The team responsible for the component with the regression **should** +strive to create a patch for mozilla-central which contains the fix for +the bug alone, not a monolithic patch containing changes for several +other bugs or features. + +Landings of third-party libraries `must contain a manifest +file `__. + +Best Practices +-------------- + +You must file a regression bug in Bugzilla +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*If the code with the regression has landed in mozilla-central, you must +file a regression bug.* + +Example +^^^^^^^ + +While using a release of Firefox (Nightly, Beta, Release, ESR) you run +across a bug. Upon research using MozRegression or other tools you find +that the bug was introduced in a change set imported from a component +whose code and issues are managed in GitHub. + +Actions to take +''''''''''''''' + +- Open a new bug in Bugzilla in appropriate component and add the + REGRESSION keyword +- Set affected status for the releases where the bug appears +- Open an issue in the corresponding GitHub project, put the Bugzilla + bug number in the title with the prefix ‘Bug’ (i.e. “Bug 99999: + Regression in foo”) +- Add the REGRESSION label to the new issue +- Add the link to the GitHub issue into the ‘See Also” field in the + Bugzilla bug + +Consequences +'''''''''''' + +*Until the regression is fixed or backed out of the GitHub repo, the +project cannot merge code into mozilla-central* + +Example +^^^^^^^ + +You import a development branch of a component managed in GitHub into +your copy of master. You find a bug and isolate it to the imported +branch. The code is managed in their own GitHub project, but bugs are +managed in Bugzilla. + +Actions to take +''''''''''''''' + +- Open a new bug in Bugzilla in appropriate component and add the + REGRESSION keyword +- Set affected status for the releases where the bug appears + +Consequences +'''''''''''' + +*Until the regression is fixed or backed out of the GitHub repo, the +project cannot merge code into mozilla-central* + +Do not file a regression bug in Bugzilla +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*If the code with the regression has not landed in mozilla-central, you +do not need to file a bug.* + + +Example +^^^^^^^ + +You import a development branch of a component managed in GitHub into +your copy of master. You find a bug and isolate it to the imported +branch. The code and issues are managed in their own GitHub project. + + +Actions to take +''''''''''''''' + +- File new issue in the GitHub repository of the imported code. +- Label issue as REGRESSION + +Consequence +''''''''''' + +*Issue blocks merge of GitHub project with mozilla-central until +resolved or backed out.* diff --git a/docs/bug-mgmt/policies/triage-bugzilla.rst b/docs/bug-mgmt/policies/triage-bugzilla.rst new file mode 100644 index 0000000000..276979eaf1 --- /dev/null +++ b/docs/bug-mgmt/policies/triage-bugzilla.rst @@ -0,0 +1,276 @@ +Triage for Bugzilla +=================== + +Expectations +------------ + +All teams working on Firefox using either or both Mozilla-central and +Bugzilla are expected to follow the following process. + +What is a Triaged Bug +--------------------- + +The new definition of Triaged will be Firefox-related bugs of type +``defect`` where the component is not +``UNTRIAGED``, and a severity value not equal to ``--`` or ``N/A``. + +Bugs of type Task or Enhancement may have a severity of ``N/A``, +but defects must have a severity that is neither ``--`` or +``N/A``. + +Why Triage +---------- + +We want to make sure that we looked at every defect and a severity has +been defined. This way, we make sure that we did not miss any critical +issues during the development and stabilization cycles. + +Staying on top of the bugs in your component means: + +- You get ahead of critical regressions and crashes which could trigger + a point release if uncaught + + - And you don’t want to spend your holiday with the Release + Management team (not that they don’t like you) + +- Your bug queue is not overwhelming + + - Members of your team do not see the bug queue and get the + ‘wiggins’ + +Who Triages +----------- + +Engineering managers and directors are responsible for naming the +individuals responsible for triaging :ref:`all types of bugs ` in a component. + +We use Bugzilla to manage this. See the `list of triage +owners `__. + +If you need to change who is responsible for triaging a bug in a +component, please `file a bug against bugzilla.mozilla.org in the +Administration +component `__. +When a new component is created, a triage owner **must** be named. + +Rotating triage +~~~~~~~~~~~~~~~ + +Some components are monitored by a rotation of triagers. In those cases, +the triage owner on Bugzilla will be automatically updated to reflect the +person on the rotation. The rotations are managed as calendars. + +If you wish to set up a rotation for triaging one or more components, +add a link to your rotation calendar in the `triage rotations spreadsheet `__. + +Firefox::General and Toolkit::General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Bugs in Firefox::General are fitted with Bug Bug’s model to see if +there’s another component with a high liklihood of fit, and if a +threshold confidence is achieved, the bug is moved to that component. + +Members of the community also review bugs in this component and try to +move them. + +What Do You Triage +------------------ + +As a triage owner the queries you should be following for your component +are: + +- All open bugs, in your components without a pending ``needinfo`` flag + which do not have a valid value of severity set +- All bugs with active review requests in your component which have not + been modified in five days +- All bugs with reviewed, but unlanded patches in your components +- All bugs with a needinfo request unanswered for more than 10 days + +There’s a tool with these queries to help you find bugs +https://mozilla.github.io/triage-center/ and the source is at +https://github.com/mozilla/triage-center/. + +If a bug is an enhancement it needs a priority set and a target release +or program milestone. These bugs are normally reviewed by product +managers. Enhancements can lead to release notes and QA needed that we +also need to know about + +If a bug is a task resulting in a changeset, release managers will need +to known when this work will be done. A task such as refactoring fragile +code can be risky. + +Weekly or More Frequently (depending on the component) find un-triaged +bugs in the components you triage. + +Decide the :ref:`Severity ` for each untriaged bug +(you can override what’s already been set.) + +These bugs are reviewed in the weekly Regression Triage meeting + +- Bugs of type ``defect`` with the ``regression`` keyword without + ``status-firefoxNN`` decisions +- Bugs of type ``defect`` with the ``regression`` keyword without + a regression range + +Automatic Bug Updates +~~~~~~~~~~~~~~~~~~~~~ + +When a bug is tracked for a release, i.e. the ``tracking_firefoxNN`` +flag is set to ``+`` or ``blocking`` triage decisions will be overridden, +or made as follows: + +- If a bug is tracked for or blocking beta, release or ESR, its + priority will be set to ``P1`` +- If a bug is tracked for or blocking nightly, its priority will be set + to ``P2`` + +Because bugs can be bumped in priority it’s essential that triage owners +review their +`P1 `__ +and +`P2 `__ +bugs frequently. + +Assumptions +~~~~~~~~~~~ + +If a bug's release status in Firefox version N was ``affected`` or ``wontfix``, +its Severity is ``S3`` or ``S4`` and its Priority is ``P3`` or lower (backlog,) +then its release status in Firefox version N+1, if the bug is still open, +is considered to be ``wontfix``. + +Questions and Edge Cases +------------------------ + +This bug is a feature request +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Set the bug’s type to ``enhancement``, add the ``feature`` keyword if +relevant, and state to ``NEW``. Set the bug's Severity to ``N/A``. This +bug will be excluded from future triage queries. + +This bug is a task, not a defect +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Set the bug’s type to ``task``, and state to ``NEW``. Set the bug's +Severity to ``N/A``. This bug will be excluded from future triage queries. + + +If you are not sure of a bug’s type, check :ref:`our rules for bug +types `. + +This bug’s state is ``UNCONFIRMED`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Are there steps to reproduce? If not, needinfo the person who filed the +bug, requesting steps to reproduce. You are not obligated to wait +forever for a response, and bugs for which open requests for information +go unanswered can be ``RESOLVED`` as ``INCOMPLETE``. + +I need help reproducing the bug +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Set a needinfo for the QA managers, Softvision project managers, or the +QA owner of the component of the bug. + +I don’t have enough information to make a decision +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you don’t have a reproduction or confirmation, or have questions +about how to proceed, ``needinfo`` the person who filed the bug, or +someone who can answer. + +The ``stalled`` keyword +~~~~~~~~~~~~~~~~~~~~~~~ + +The extreme case of not-enough-information is one which cannot be +answered with a ``needinfo`` request. The reporter has shared all they +know about the bug, we are out of strategies to take to resolve it, but +the bug should be kept open. + +Mark the bug as stalled by adding the ``stalled`` keyword to it. The +keyword will remove it from the list of bugs to be triaged. + +If a patch lands on a ``stalled`` bug, automation will remove the +keyword. Otherwise, when the ``keyword`` is removed, the bug will have +its priority reset to ``--`` and the components triage owner notified by +automation. + +Bugs which remain ``stalled`` for long periods of time should be +reviewed, and closed if necessary. + +Bug is in the wrong Component +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the bug has a Severity of ``S3``, ``S4``, or ``N/A`` move the what +you think is the correct component, or needinfo the person +responsible for the component to ask them. + +If the bug has a Severity of ``S1`` or ``S2`` then notify Release Management +and contact the triage owner of the component for which you think it belongs to. +We cannot lose track of a high severity bug because it is in the wrong component. + +My project is on GitHub +~~~~~~~~~~~~~~~~~~~~~~~ + +We have :ref:`a guide for GitHub projects to follow ` when +triaging. (Note: this guide needs updating.) + +Summary +------- + +Multiple times weekly +~~~~~~~~~~~~~~~~~~~~~ + +Use queries for the components you are responsible for in +https://mozilla.github.io/triage-center/ to find bugs in +need of triage. + +For each untriaged bug: + +- Assign a Severity +- **Do not** assign a ``defect`` a Severity of + ``N/A`` + +You can, but are not required to set the bug's :ref:`Priority `. + +Watch open needinfo flags +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Don’t let open needinfo flags linger for more than two weeks. + +Close minor bugs with unresponded needinfo flags. + +Follow up on needinfo flag requests. + +The `Triage Center tool `__ will help you find these. + +End of Iteration/Release Cycle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Any open ``S1`` or ``S2`` bugs at the end of the release cycle +will require review by engineering and release management. A +policy on this is forthcoming. + +Optional +^^^^^^^^ + +(The guidelines on bug priority are under review.) + +Are there open P1s? Revisit their priority, +and move to them to the backlog (``P3``) or ``P2``. + +Are there ``P2`` bugs that should move to ``P1`` +for the next cycle? + +Are there ``P2`` you now know are lower priority, +move to ``P3``. + +Are there ``P3`` bugs you now know you won’t get to? +Either demote to ``P5`` (will accept patch) or +resolve as ``WONTFIX``. + +Getting help +------------ + +- Ask in #bug-handling on chat.mozilla.org diff --git a/docs/bug-mgmt/processes/accessibility-review.md b/docs/bug-mgmt/processes/accessibility-review.md new file mode 100644 index 0000000000..6314e9c684 --- /dev/null +++ b/docs/bug-mgmt/processes/accessibility-review.md @@ -0,0 +1,72 @@ +# Accessibility Review + +## Introduction +At Mozilla, accessibility is a fundamental part of our mission to ensure the +internet is "open and accessible to all," helping to empower people, regardless +of their abilities, to contribute to the common good. Accessibility Review is a +service provided by the Mozilla Accessibility team to review features and +changes to ensure they are accessible to and inclusive of people with +disabilities. + +## Do I Need Accessibility Review? +You should consider requesting accessibility review if you aren't certain +whether your change is accessible to people with disabilities. Accessibility +review is optional, but it is strongly encouraged if you are introducing new +user interface or are significantly redesigning existing user interface. +Review should be requested both on the design side _and_ on the engineering side. + +## When Should I Request Accessibility Review? +Generally, it's best to request accessibility review as early as possible, even +during the product requirements or UI design stage. Particularly for more +complex user interfaces, accessibility is much easier when incorporated into the +design, rather than attempting to retro-fit accessibility after the +implementation is well underway. + +The accessibility team has developed the [Mozilla Accessibility Release +Guidelines](https://wiki.mozilla.org/Accessibility/Guidelines) which outline +what is needed to make user interfaces accessible. To make accessibility review +faster, you may wish to try to verify and implement these guidelines prior to +requesting accessibility review. + +For design reviews, please allow at least a week between review request and expected-engineering-handoff. The deadline for engineering review requests is Friday of the first week of nightly builds for the release in which the feature/change is expected to ship. +This is the same date as the PI Request deadline. + +## Requesting Design Review +Design review should be requested via the #accessibility slack channel. Please post the following information to help us triage your review: + +``` +Timeline? (ie. when is engineering handoff? product approval? etc.) +Tracking/bug issue: +Product spec: +Figma file: +Engineering lead: +Product manager: +Have you completed self-review (contrast audit, focus order/role annotations, HCM mockups)? +``` + +In addition to posting this information, please complete the following self-review tasks **before requesting review**. Note: Some of the following links require SSO authentication. + +- **Perform a contrast audit**: Using a [figma plugin that audits contrast](https://www.figma.com/community/plugin/748533339900865323/Contrast), check your designs for color contrast sufficiency. Your designs should be at least "AA" rated in order to pass accessibility review. "AAA" is even better! If there are particular components that are difficult to adjust to meet "AA" standards, make a note in the figma file and the a11y team will provide specific guidance during review. +- **Add focus order and role annotations**: Focus order annotations describe the behaviour a keyboard user should expect when navigating your design. Generally this follows the reading order. Note that we only care about focusable elements here (ie. links, buttons, inputs, etc.). +Role annotations help screen readers and other assistive technologies identify the "kind" of component they're navigating through. These mappings expose semantic information to the user. You can find a [list of common roles here](https://www.codeinwp.com/blog/wai-aria-roles/). You may want to use a [figma plugin that annotates focus and roles](https://www.figma.com/community/plugin/731310036968334777/A11y---Focus-Order) for this process. You do not need to annotate every view in your design, pick those with the largest amount of new content. +- **Create Windows High-Contrast Mode (HCM) mockups**: Our designs should be accessible to users [running HCM](https://docs.google.com/document/d/1El3XJiAdA5gFcG7H9iI1dNmLbht0hXfi_oKBZPWx3t0/edit). You can read more about [how HCM affects color selection](https://firefox-source-docs.mozilla.org/accessible/ColorsAndHighContrastMode.html), and [how to design for HCM](https://wiki.mozilla.org/Accessibility/Design_Guide). Using the ["Night Sky" HCM palette](https://www.figma.com/file/XQrEePCCJebjlVBQwNggQ6/Pro-Client-Accessibility-Reviews?node-id=25%3A3848), translate your designs into High Contrast. Remember, it's important we use these colors **semantically**, not based on a desire for a particular aesthetic. Colors are labelled according to their uses -- `Background` for page background, `Button Text` for button or control text, `Selected Item Background` for backgrounds of selected or active items, etc.. You do not need to mock up every view in your design, pick those with the largest amount of new content. You can find [examples of previous HCM mock ups here](https://www.figma.com/file/XQrEePCCJebjlVBQwNggQ6/Accessibility). +Where possible, we should rely on SVG's and PNG's for image content to increase adaptability. + + +## Requesting Engineering Review +For an engineering-focused review, you submit a review request by setting the a11y-review flag to "requested" +on a bug in Bugzilla and filling in the template that appears in the comment +field. For features spanning several bugs, you may wish to file a new, dedicated +bug for the accessibility review. Otherwise, particularly for smaller changes, +you may do this on an existing bug. Note that if you file a new bug, you will +need to submit the bug and then edit it to set the flag. + +## Questions? +If you have any questions, please don't hesitate to contact the Accessibility +team: + +* \#accessibility on + [Matrix](https://matrix.to/#/!jmuErVonajdNMbgdeY:mozilla.org?via=mozilla.org&via=matrix.org) + or [Slack](https://mozilla.slack.com/archives/C4E0W8B8E) +* Email: accessibility@mozilla.com +* Please avoid reaching out to individual team members directly -- containing review requests and questions in these channels helps us balance our workload. Thank you! diff --git a/docs/bug-mgmt/processes/doc-requests.rst b/docs/bug-mgmt/processes/doc-requests.rst new file mode 100644 index 0000000000..dc390a27cb --- /dev/null +++ b/docs/bug-mgmt/processes/doc-requests.rst @@ -0,0 +1,39 @@ +User documentation requests +=========================== + +If you are working on a change (bugfix, enhancement, or feature) which +would benefit from user-facing documentation, please use the +``user-doc-firefox`` flag to request it. + +This flag can be modified by anyone with ``EDITBUGS`` privileges. + +The default value of the flag is ``---``. + +If the bug needs user-facing documentation, set the flag to +``docs-needed``. This flag will be monitored by the support.mozilla.org +(SUMO) team. + +Once the docs are ready to be published, set the flag to +``docs-completed``. + +If it’s determined that documentation is not need after setting the flag +to ``docs-needed``, update the flag to ``none-needed`` so we know that +it’s been reviewed. + +Summary +------- + +=========== == ============== +From To +=========== == ============== +— to none-needed +— to docs-needed +docs-needed to none-needed +docs-needed to docs-completed +=========== == ============== + +Notes +----- + +A flag is used instead of the old keywords because flags can be +restricted to a subset of products and components. diff --git a/docs/bug-mgmt/processes/fixing-security-bugs.rst b/docs/bug-mgmt/processes/fixing-security-bugs.rst new file mode 100644 index 0000000000..e07853ac79 --- /dev/null +++ b/docs/bug-mgmt/processes/fixing-security-bugs.rst @@ -0,0 +1,217 @@ +Fixing Security Bugs +==================== + +A bug has been reported as security-sensitive in Bugzilla and received a +security rating. + +If this bug is private - which is most likely for a reported security +bug - **the process for patching is slightly different than the usual +process for fixing a bug**. + +Here are security guidelines to follow if you’re involved in reviewing, +testing and landing a security patch. See +:ref:`Security Bug Approval Process` +for more details about how to request sec-approval and land the patch. + +Keeping private information private +----------------------------------- + +A security-sensitive bug in Bugzilla means that all information about +the bug except its ID number are hidden. This includes the title, +comments, reporter, assignee and CC’d people. + +A security-sensitive bug usually remains private until a fix is shipped +in a new release, **and after a certain amount of time to ensure that a +maximum number of users updated their version of Firefox**. Bugs are +usually made public after 6 months and a couple of releases. + +From the moment a security bug has been privately reported to the moment +a fix is shipped and the bug is set public, all information about that +bug needs to be handled carefully in order to avoid an unmitigated +vulnerability becoming known and exploited before we release a +fix (0-day). + +During a normal process, information about the nature of bug can be +accessed through: + +- Bug comments (Bugzilla, GitHub issue) +- Commit message (visible on Bugzilla, tree check-ins and test servers) +- Code comments +- Test cases +- Bug content can potentially be discussed on public IRC/Slack channels + and mailing list emails. + +When patching for a security bug, you’ll need to be mindful about what +type of information you share and where. + +In commit messages +~~~~~~~~~~~~~~~~~~ + +People are watching code check-ins, so we want to avoid sharing +information which would disclose or help finding a vulnerability too +easily before we shipped the fix to our users. This includes: + +- The **nature of the vulnerability** (overflow, use-after-free, XSS, + CSP bypass...) +- **Ways to trigger and exploit that vulnerability** + - In commit messages, code comments and test cases. +- The fact that a bug / commit is security-related: + + - **Trigger words** in the commit message or code comments such as + "security", "exploitable", or the nature of a security vulnerability + (overflow, use-after-free…) + - **Security approver’s name** in a commit message. +- The Firefox versions and components affected by the vulnerability. +- Patches with an obvious fix. + +In Bugzilla and other public channels +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to commits, you’ll need to be mindful of not disclosing +sensitive information about the bug in public places, such as Bugzilla: + +- Mention the bugs in comment of the private bug instead. +- Do not comment sensitive information in public related bugs. +- Also be careful about who you give bug access to: **double check + before CC’ing the wrong person or alias**. +- As of recently, you may now add public bugs in the “duplicate”, + “depends on”, “blocks”, “regression”, “regressed by”, or “see also” section. + Bugzilla will only reveal those relationships to people with ``editbugs`` + permission or access to the security bug. + +On IRC, Slack channels, GitHub issues, mailing lists: If you need to +discuss about a security bug, use a private channel (protected with a +password or with proper right access management) + +During Development +------------------ + +Testing security bugs +~~~~~~~~~~~~~~~~~~~~~ + +Pushing to Try servers requires Level 1 Commit access but **content +viewing is publicly accessible**. + +As much as possible, **do not push to Try servers**. Testing should be +done locally before checkin in order to prevent public disclosing of the +bug. + +Because of the public visibility, pushing to Try has all the same concerns +as committing the patch. Please heed the concerns in the +:ref:`landing-your-patch` section before thinking about it, and check with +the security team for an informal "sec-approval" before doing so. + +**Do not push the bug's own vulnerability testcase to Try.** + +If you need to push to Try servers, make sure your tests don’t disclose +what the vulnerability is about or how to trigger it. Do not mention +anywhere it is security related. + +Obfuscating a security patch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If your security patch looks obvious because of the code it contains +(e.g. a one-line fix), or if you really need to push to Try servers, +**consider integrating your security-related patch to non-security work +in the same area**. And/or pretend it is related to something else, like +some performance improvement or a correctness fix. **Definitely don't +include the bug number in the commit message.** This will help making +the security issue less easily identifiable. (The absolute ban against +"Security through Obscurity" is in relation to cryptographic systems. In +other situations you still can't *rely* on obscurity but it can +sometimes buy you a little time. In this context we need to get the +fixes into the hands of our users faster than attackers can weaponize +and deploy attacks and a little extra time can help.) + +Requesting sec-approval +~~~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`Security Bug Approval Process` +for more details + +.. _landing-your-patch: + +Landing your patch (with or without sec-approval) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Before asking for sec-approval or landing, ensure your patch does not disclose +information about the security vulnerability unnecessarily. Specifically: + +#. The patch commit message and its contents should not mention security, + security bugs, or sec-approvers. + Note that you can alter the commit message directly in phabricator, + if that's the only thing you need to do - you don't need to amend your + local commit and re-push it. + While comprehensive commit messages are generally encouraged; they + should be omitted for security bugs and instead be posted in the bug + (which will eventually become public.) +#. Separate out tests into a separate commit. + **Do not land tests when landing the patch. Remember we don’t want + to 0-day ourselves!** This includes when pushing to try. + + - Tests should only be checked in later, after an official Firefox + release that contains the fix has been live for at least + four weeks. For example, if Firefox 53 + contains a security issue that affects the world and that issue is + fixed in 54, tests for this fix should not be checked in + until four weeks after 54 goes live. + + The exception to this is if there is a security issue that doesn't + affect any release branches, only mozilla-central and/or other + development branches. Since the security problem was never + released to the world, once the bug is fixed in all affected + places, tests can be checked in to the various branches. + - There are two main techniques for remembering to check in the + tests later: + + a. clone the sec bug into a separate "task" bug **that is also + in a security-sensitive group to ensure it's not publicly visible** + called something like "land tests for bug xxxxx" and assign to + yourself. It should get a "sec-other" keyword rating. + + Tip: In phabricator, you can change the bug linked to + a commit with tests if the tests were already separate, while keeping + the previously granted review, meaning you can just land the patch + when ready, rather than having your reviewer and you have to remember + what this was about a month or two down the line. + b. Or, set the "in-testsuite" flag to "?", and later set it to "+" + when the tests get checked in. + + +Landing tests +~~~~~~~~~~~~~ + +Tests can be landed **once the release containing fixes has been live +at least 4 weeks**. + +The exception is if a security issue has never been shipped in a release +build and has been fixed in all development branches. + +Making a security bug public +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the responsibility of the security management team. + +Essentials +---------- + +- **Do not disclose any information about the vulnerability before a + release with a fix has gone live for enough time for users to update + their software**. + + - This includes code comments, commit messages, tests, public + communication channels. + +- If any doubt: '''request sec-approval? ''' +- If any doubt: **needinfo security folks**. +- **If there’s no rating, assume the worst and treat the bug as + sec-critical**. + +Documentation & Contacts +------------------------ + +- :ref:`Normal process for submitting a patch ` +- `How to file a security bug `__ +- `Handling Mozilla security bugs (policy) `__ +- :ref:`Security Bug Approval Process` +- `Contacting the Security team(s) at Mozilla: `__ diff --git a/docs/bug-mgmt/processes/labels.rst b/docs/bug-mgmt/processes/labels.rst new file mode 100644 index 0000000000..9541d9da61 --- /dev/null +++ b/docs/bug-mgmt/processes/labels.rst @@ -0,0 +1,155 @@ +GitHub Metadata Recommendations +=============================== + +To have better consistency with code and task tracking among Mozilla +Central, Bugzilla, and GitHub, we request that you use a common set of +labels in your projects. Benefits of improved consistency in our +conventions include: + +- Consistency makes measurement of processes simpler across the + organization +- Consistency makes it easier to write re-usable process tools +- Consistency increases clarity for those than need to work across + different repositories and bug trackers +- Consistency reduces friction around engineering mobility between + projects + +We recommend creating sets of labels in your project to do this. + +Bug types +--------- + +In Bugzilla bugs are distinguished by type: ``defect``, ``enhancement``, +and ``tasks``. Use a label to make this distinction in your project. + +Statuses +-------- + +Bugs in GitHub issues have two states: closed and open. Bugzilla has a +richer set of states. + +When you close a bug, add a label indicating `the +resolution `__. + +- ``fixed`` + + - A change set for the bug has been landed in Mozilla-Central + - A GitHub issue could be closed, but the change set has not + landed so it would be still considered open from the + Bugzilla point of view + +- ``invalid`` + + - The problem described is not a bug. + +- ``incomplete`` + + - The problem is vaguely described with no steps to reproduce, or is + a support request. + +- ``wontfix`` + + - The problem described is a bug which will never be fixed. + +- ``duplicate`` + + - The problem is a duplicate of an existing bug. Be sure to link the + bug this is a duplicate of. + +- ``worksforme`` + + - All attempts at reproducing this bug were futile, and reading the + code produces no clues as to why the described behavior would + occur. + +Severities (Required) +--------------------- + +The triage process for Firefox bugs in Bugzilla requires a non default +value of a bug's :ref:`Severity (definitions) `. + +Release Status Flags +-------------------- + +Open Firefox bugs may also have :ref:`status flags ` +(``status_firefoxNN``) set for Nightly, Beta, Release, or ESR. + +Priorities +---------- + +Firefox projects in Bugzilla can use the :ref:`priority field ` +to indicate when a bug will be worked on. + +Keywords +-------- + +In GitHub issues metadata is either a label or the bug’s open/closed +state. + +Some Bugzilla metadata behaves like labels, but you need to be careful +with how you use it in order not to confuse QA. + +Regressions +~~~~~~~~~~~ + +In Bugzilla, the ``regression`` keyword indicates a regression in +existing behavior introduced by a code change. + +When a bug is labeled as a regression in GitHub does it imply the +regression is in the code module in GitHub, or the module that’s landed +in Mozilla Central? Using the label ``regression-internal`` will signal +QA that the regression is internal to your development cycle, and not +one introduced into the Mozilla Central tree. + +If it is not clear which pull request caused the regression, add the +``regressionwindow-wanted`` label. + +Other Keywords +~~~~~~~~~~~~~~ + +Other useful labels include ``enhancement`` to distinguish feature +requests, and ``good first issue`` to signal to contributors (`along +with adequate +documentation `__.) + +Summary +------- + +To represent Bugzilla fields, use labels following this scheme. + +- Bug types + + - ``defect``, ``enhancement``, ``task`` + +- Resolution statuses + + - ``invalid``, ``duplicate``, ``incomplete``, ``worksforme``, + ``wontfix`` + +- Regressions + + - ``regression``, ``regressionwindow-wanted``, + ``regression-internal`` + + +- :ref:`Severity ` (required) + + - ``S1``, ``S2``, ``S3``, ``S4``, ``N/A`` (reserved for bugs + of type ``task`` or ``enhancement``) + +- :ref:`Status flags ` + + - ``status_firefoxNN:`` + (example ``status_firefox77:affected``) + +- :ref:`Priority ` + + - ``P1``, ``P2``, ``P3``, ``P5`` + +- Other keywords + + - ``good first bug``, ``perf``, &etc. + + +You may already have a set of tags, so do an edit to convert them +or use `the GitHub settings app `__. diff --git a/docs/bug-mgmt/processes/regressions.rst b/docs/bug-mgmt/processes/regressions.rst new file mode 100644 index 0000000000..991771f38d --- /dev/null +++ b/docs/bug-mgmt/processes/regressions.rst @@ -0,0 +1,64 @@ +How to Mark Regressions +======================= + +Regressions +----------- + +For regression bugs in Mozilla-Central, our policy is to tag the bug as +a regression, identify the commits which caused the regression, then +mark the bugs associated with those commits as causing the regression. + +What is a regression? +--------------------- + +A regression is a bug (in our scheme a ``defect``) introduced by a +`changeset `__. + +- Bug 101 *fixes* Bug 100 with Change Set A +- Bug 102 *reported which describes previously correct behavior now not + happening* +- Bug 102 *investigated and found to be introduced by Change Set A* + +Marking a Regression Bug +------------------------ + +These things are true about regressions: + +- **Bug Type** is ``defect`` +- **Keywords** include ``regression`` +- **Status_FirefoxNN** is ``affected`` for each version (in current + nightly, beta, and release) of Firefox in which the bug was found +- The bug’s description covers previously working behavior which is no + longer working [ed. I need a better phrase for this] + +Until the change set which caused the regression has been found through +`mozregression `__ or another +bisection tool, the bug should also have the ``regressionwindow-wanted`` +keyword. + +Once the change set which caused the regression has been identified, +remove the ``regressionwindow-wanted`` keyword and set the **Regressed +By** field to the id of the bug associated with the change set. + +Setting the **Regressed By** field will update the **Regresses** field +in the other bug. + +Set a needinfo for the author of the regressing patch asking them to fix +or revert the regression. + +Previous Method +--------------- + +Previously we over-loaded the **Blocks** and **Blocked By** fields to +track the regression, setting **Blocks** to the id of the bug associated +with the change set causing the regression, and using the +``regression``, ``regressionwindow-wanted`` keywords and the status +flags as described above. + +This made it difficult to understand what was a dependency and what was +a regression when looking at dependency trees in Bugzilla. + +FAQs +---- + +*To be written* diff --git a/docs/bug-mgmt/processes/security-approval.rst b/docs/bug-mgmt/processes/security-approval.rst new file mode 100644 index 0000000000..13f0057b98 --- /dev/null +++ b/docs/bug-mgmt/processes/security-approval.rst @@ -0,0 +1,194 @@ +Security Bug Approval Process +============================= + +How to fix a core-security bug in Firefox - developer guidelines +---------------------------------------------------------------- + +Follow these security guidelines if you’re involved in reviewing, +testing and landing a security patch: +:ref:`Fixing Security Bugs`. + +Purpose: don't 0-day ourselves +------------------------------ + +People watch our check-ins. They may be able to start exploiting our +users before we can get an update out to them if + +- the patch is an obvious security fix (bounds check, kungFuDeathGrip, + etc.) +- the check-in comment says "security fix" or includes trigger words + like "exploitable", "vulnerable", "overflow", "injection", "use after + free", etc. +- comments in the code mention those types of things or how someone + could abuse the bug +- the check-in contains testcases that show exactly how to trigger the + vulnerability + +Principle: assume the worst +--------------------------- + +- If there's no rating we assume it could be critical +- If we don't know the regression range we assume it needs porting to + all supported branches + +Process for Security Bugs (Developer Perspective) +------------------------------------------------- + +Filing / Managing Bugs +~~~~~~~~~~~~~~~~~~~~~~ + +- Try whenever possible to file security bugs marked as such when + filing, instead of filing them as open bugs and then closing later. + This is not always possible, but attention to this, especially when + filing from crash-stats, is helpful. +- It is _ok_ to link security bugs to non-security bugs with Blocks, + Depends, Regressions, or See Also. Users with the editbugs permission + will be able to see the reference, but not view a restricted bug. + Users without the permission will not be able to see the link. + +Developing the Patch +~~~~~~~~~~~~~~~~~~~~ + +- Comments in the code should not mention a security issue is being + fixed. Don’t paint a picture or an arrow pointing to security issues + any more than the code changes already do. +- Avoid linking it to non-security bugs with Blocks, Depends, or See + Also, especially if those bugs may give a hint to the sort of + security issue involved. Mention the bug in a comment on the security + bug instead. We can always fill in the links later after the fix has + shipped. +- Do not push to Try servers if possible: this exposes the security + issues for these critical and high rated bugs to public viewing. In + an ideal case, testing of patches is done locally before final + check-in to mozilla-central. +- If pushing to Try servers is necessary, **do not include the bug + number in the patch**. Ideally, do not include tests in the push as + the tests can illustrate the exact nature of the security problem + frequently. +- If you must push to Try servers, with or without tests, try to + obfuscate what this patch is for. Try to push it with other, + non-security work, in the same area. + +Request review of the patch in the same process as normal. After the +patch has been reviewed you will request sec-approval as needed. See +:ref:`Fixing Security Bugs` +for more examples/details of these points. + +Preparing the patch for landing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`Fixing Security Bugs` +for more details. + +On Requesting sec-approval +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For security bugs with no sec- severity rating assume the worst and +follow the rules for sec-critical. During the sec-approval process we +will notice it has not been rated and rate it during the process. + +Core-security bug fixes can be landed by a developer without any +explicit approval if: + +| **A)** The bug has a sec-low, sec-moderate, sec-other, or sec-want + rating. +|    **or** +| **B)** The bug is a recent regression on mozilla-central. This means + +- A specific regressing check-in has been identified +- The developer can (**and has**) marked the status flags for ESR and + Beta as "unaffected" +- We have not shipped this vulnerability in anything other than a + nightly build + +If it meets the above criteria, developers do not need to ask for sec-approval. + +In all other cases, developers should ask for sec-approval. +Set the sec-approval flag to '?' on the patch when it is ready to be landed. +You will find these flags in Bugzilla using the "Details" links in the +Bugzilla attachment table (not directly on phabricator at time of writing). + +If developers are unsure about a bug and it has a patch ready, just +request sec-approval anyway and move on. Don't overthink it! + +An automatic nomination comment will be added to bugzilla when +sec-approval is set to '?'. The questions in this need to be filled out +as best as possible when sec-approval is requested for the patch. + +It is as follows (courtesy of Dan Veditz):: + + [Security approval request comment] + How easily can the security issue be deduced from the patch? + Do comments in the patch, the check-in comment, or tests included in + the patch paint a bulls-eye on the security problem? + Which older supported branches are affected by this flaw? + If not all supported branches, which bug introduced the flaw? + Do you have backports for the affected branches? If not, how + different, hard to create, and risky will they be? + How likely is this patch to cause regressions; how much testing does + it need? + +This is similar to the ESR approval nomination form and is meant to help +us evaluate the risks around approving the patch for checkin. + +When the bug is approved for landing, the sec-approval flag will be set +to '+' with a comment from the approver to land the patch. At that +point, land it according to instructions provided.. + +This will allow us to control when we can land security bugs without +exposing them too early and to make sure they get landed on the various +branches. + +If you have any questions or are unsure about anything in this document +contact us on Slack in the #security channel or the current +sec-approvers Dan Veditz and Tom Ritter. + +Process for Security Bugs (sec-approver Perspective) +---------------------------------------------------- + +The security assurance team and release management will have their own +process for approving bugs: + +#. The Security assurance team goes through sec-approval ? bugs daily + and approves low risk fixes for central (if early in cycle). + Developers can also ping the Security Assurance Team (specifically + Tom Ritter & Dan Veditz) in #security on Slack when important. + + #. If a bug lacks a security-rating one should be assigned - possibly + in coordination with the (other member of) the Security Assurance + Team + +#. Security team marks tracking flags to ? for all affected versions + when approved for central. (This allows release management to decide + whether to uplift to branches just like always.) +#. Weekly security/release management triage meeting goes through + sec-approval + and ? bugs where beta and ESR is affected, ? bugs with + higher risk (sec-high and sec-critical), or ? bugs near end of cycle. + +Options for sec-approval including a logical combination of the +following: + +- Separate out the test and comments in the code into a followup commit + we will commit later. +- Remove the commit message and place it in the bug or comments in a + followup commit. +- Please land it bundled in with another commit +- Land today +- Land today, land the tests after +- Land closer to the release date +- Land in Nightly to assess stability +- Land today and request uplift to all branches +- Request uplift to all branches and we'll land as close to shipping as + permitted +- Chemspill time + +The decision process for which of these to choose is perceived risk on +multiple axes: + +- ease of exploitation +- reverse engineering risk +- stability risk + +The most common choice is: not much stability risk, not an immediate +reverse engineering risk, moderate to high difficulty of exploitation: +"land whenever". diff --git a/docs/bug-mgmt/processes/shared-bug-queues.rst b/docs/bug-mgmt/processes/shared-bug-queues.rst new file mode 100644 index 0000000000..dc2df9bbf9 --- /dev/null +++ b/docs/bug-mgmt/processes/shared-bug-queues.rst @@ -0,0 +1,34 @@ +Shared Bug Queues +================= + +Reviewers for change sets can be suggested at the product and component +level, but only the person who has been asked to review code will be +notified. + +Realizing that Bugzilla users can *watch* other users, `Chris +Cooper `__ came up with the idea +of having `a shared reviews alias for review +requests `__. + +If you want to watch a particular part of the tree in Mozilla Central, +then `use the Herald +tool `__. + +Process +------- + +1. Create a new bugzilla.mozilla.com account for an address which can + receive mail. + Use the ``name+extension@domain.tld`` trick such as + ``jmozillian+reviews@mozilla.com`` to create a unique address +2. Respond to the email sent by Bugzilla and set a password on the + account +3. `Open a bug `__ to convert the account to a + bot and make it the shared review queue for your component +4. BMO administrator updates the email address of the new account to the + ``@mozilla.bugs`` address +5. BMO administrator updates the default reviewer for the component + requested and sets it to the shared review account +6. Reviewers `follow the shared review account in + bugzilla `__ +7. Reviewers get notified when shared review account is ``r?``\ ed diff --git a/docs/code-quality/coding-style/about-logins-rtl.png b/docs/code-quality/coding-style/about-logins-rtl.png new file mode 100644 index 0000000000..a5d0edd4c8 Binary files /dev/null and b/docs/code-quality/coding-style/about-logins-rtl.png differ diff --git a/docs/code-quality/coding-style/about-protections-rtl.png b/docs/code-quality/coding-style/about-protections-rtl.png new file mode 100644 index 0000000000..4fbbf5e889 Binary files /dev/null and b/docs/code-quality/coding-style/about-protections-rtl.png differ diff --git a/docs/code-quality/coding-style/coding_style_cpp.rst b/docs/code-quality/coding-style/coding_style_cpp.rst new file mode 100644 index 0000000000..cb4764cea5 --- /dev/null +++ b/docs/code-quality/coding-style/coding_style_cpp.rst @@ -0,0 +1,1150 @@ +================ +C++ Coding style +================ + + +This document attempts to explain the basic styles and patterns used in +the Mozilla codebase. New code should try to conform to these standards, +so it is as easy to maintain as existing code. There are exceptions, but +it's still important to know the rules! + +This article is particularly for those new to the Mozilla codebase, and +in the process of getting their code reviewed. Before requesting a +review, please read over this document, making sure that your code +conforms to recommendations. + +.. container:: blockIndicator warning + + The Firefox code base adopts parts of the `Google Coding style for C++ + code `__, but not all of its rules. + A few rules are followed across the code base, others are intended to be + followed in new or significantly revised code. We may extend this list in the + future, when we evaluate the Google Coding Style for C++ Code further and/or update + our coding practices. However, the plan is not to adopt all rules of the Google Coding + Style for C++ Code. Some rules are explicitly unlikely to be adopted at any time. + + Followed across the code base: + + - `Formatting `__, + except for subsections noted here otherwise + - `Implicit Conversions `__, + which is enforced by a custom clang-plugin check, unless explicitly overridden using + ``MOZ_IMPLICIT`` + + Followed in new/significantly revised code: + + - `Include guards `__ + + Unlikely to be ever adopted: + + - `Forward declarations `__ + - `Formatting/Conditionals `__ + w.r.t. curly braces around inner statements, we require them in all cases where the + Google style allows to leave them out for single-line conditional statements + + This list reflects the state of the Google Google Coding Style for C++ Code as of + 2020-07-17. It may become invalid when the Google modifies its Coding Style. + + +Formatting code +--------------- + +Formatting is done automatically via clang-format, and controlled via in-tree +configuration files. See :ref:`Formatting C++ Code With clang-format` +for more information. + +Unix-style linebreaks (``\n``), not Windows-style (``\r\n``). You can +convert patches, with DOS newlines to Unix via the ``dos2unix`` utility, +or your favorite text editor. + +Static analysis +--------------- + +Several of the rules in the Google C++ coding styles and the additions mentioned below +can be checked via clang-tidy (some rules are from the upstream clang-tidy, some are +provided via a mozilla-specific plugin). Some of these checks also allow fixes to +be automatically applied. + +``mach static-analysis`` provides a convenient way to run these checks. For example, +for the check called ``google-readability-braces-around-statements``, you can run: + +.. code-block:: shell + + ./mach static-analysis check --checks="-*,google-readability-braces-around-statements" --fix + +It may be necessary to reformat the files after automatically applying fixes, see +:ref:`Formatting C++ Code With clang-format`. + +Additional rules +---------------- + +*The norms in this section should be followed for new code. For existing code, +use the prevailing style in a file or module, ask the owner if you are +in another team's codebase or it's not clear what style to use.* + + + + +Control structures +~~~~~~~~~~~~~~~~~~ + +Always brace controlled statements, even a single-line consequent of +``if else else``. This is redundant, typically, but it avoids dangling +else bugs, so it's safer at scale than fine-tuning. + +Examples: + +.. code-block:: cpp + + if (...) { + } else if (...) { + } else { + } + + while (...) { + } + + do { + } while (...); + + for (...; ...; ...) { + } + + switch (...) { + case 1: { + // When you need to declare a variable in a switch, put the block in braces. + int var; + break; + } + case 2: + ... + break; + default: + break; + } + +``else`` should only ever be followed by ``{`` or ``if``; i.e., other +control keywords are not allowed and should be placed inside braces. + +.. note:: + + For this rule, clang-tidy provides the ``google-readability-braces-around-statements`` + check with autofixes. + + +C++ namespaces +~~~~~~~~~~~~~~ + +Mozilla project C++ declarations should be in the ``mozilla`` +namespace. Modules should avoid adding nested namespaces under +``mozilla``, unless they are meant to contain names which have a high +probability of colliding with other names in the code base. For example, +``Point``, ``Path``, etc. Such symbols can be put under +module-specific namespaces, under ``mozilla``, with short +all-lowercase names. Other global namespaces besides ``mozilla`` are +not allowed. + +No ``using`` directives are allowed in header files, except inside class +definitions or functions. (We don't want to pollute the global scope of +compilation units that use the header file.) + +.. note:: + + For parts of this rule, clang-tidy provides the ``google-global-names-in-headers`` + check. It only detects ``using namespace`` directives in the global namespace. + + +``using namespace ...;`` is only allowed in ``.cpp`` files after all +``#include``\ s. Prefer to wrap code in ``namespace ... { ... };`` +instead, if possible. ``using namespace ...;``\ should always specify +the fully qualified namespace. That is, to use ``Foo::Bar`` do not +write ``using namespace Foo; using namespace Bar;``, write +``using namespace Foo::Bar;`` + +Use nested namespaces (ex: ``namespace mozilla::widget {`` + +.. note:: + + clang-tidy provides the ``modernize-concat-nested-namespaces`` + check with autofixes. + + +Anonymous namespaces +~~~~~~~~~~~~~~~~~~~~ + +We prefer using ``static``, instead of anonymous C++ namespaces. This may +change once there is better debugger support (especially on Windows) for +placing breakpoints, etc. on code in anonymous namespaces. You may still +use anonymous namespaces for things that can't be hidden with ``static``, +such as types, or certain objects which need to be passed to template +functions. + + +C++ classes +~~~~~~~~~~~~ + +.. code-block:: cpp + + namespace mozilla { + + class MyClass : public A + { + ... + }; + + class MyClass + : public X + , public Y + { + public: + MyClass(int aVar, int aVar2) + : mVar(aVar) + , mVar2(aVar2) + { + ... + } + + // Special member functions, like constructors, that have default bodies + // should use '= default' annotation instead. + MyClass() = default; + + // Unless it's a copy or move constructor or you have a specific reason to allow + // implicit conversions, mark all single-argument constructors explicit. + explicit MyClass(OtherClass aArg) + { + ... + } + + // This constructor can also take a single argument, so it also needs to be marked + // explicit. + explicit MyClass(OtherClass aArg, AnotherClass aArg2 = AnotherClass()) + { + ... + } + + int LargerFunction() + { + ... + ... + } + + private: + int mVar; + }; + + } // namespace mozilla + +Define classes using the style given above. + +.. note:: + + For the rule on ``= default``, clang-tidy provides the ``modernize-use-default`` + check with autofixes. + + For the rule on explicit constructors and conversion operators, clang-tidy + provides the ``mozilla-implicit-constructor`` check. + +Existing classes in the global namespace are named with a short prefix +(For example, ``ns``) as a pseudo-namespace. + + +Methods and functions +~~~~~~~~~~~~~~~~~~~~~ + + +C/C++ +^^^^^ + +In C/C++, method names should use ``UpperCamelCase``. + +Getters that never fail, and never return null, are named ``Foo()``, +while all other getters use ``GetFoo()``. Getters can return an object +value, via a ``Foo** aResult`` outparam (typical for an XPCOM getter), +or as an ``already_AddRefed`` (typical for a WebIDL getter, +possibly with an ``ErrorResult& rv`` parameter), or occasionally as a +``Foo*`` (typical for an internal getter for an object with a known +lifetime). See `the bug 223255 `_ +for more information. + +XPCOM getters always return primitive values via an outparam, while +other getters normally use a return value. + +Method declarations must use, at most, one of the following keywords: +``virtual``, ``override``, or ``final``. Use ``virtual`` to declare +virtual methods, which do not override a base class method with the same +signature. Use ``override`` to declare virtual methods which do +override a base class method, with the same signature, but can be +further overridden in derived classes. Use ``final`` to declare virtual +methods which do override a base class method, with the same signature, +but can NOT be further overridden in the derived classes. This should +help the person reading the code fully understand what the declaration +is doing, without needing to further examine base classes. + +.. note:: + + For the rule on ``virtual/override/final``, clang-tidy provides the + ``modernize-use-override`` check with autofixes. + + +Operators +~~~~~~~~~ + +The unary keyword operator ``sizeof``, should have its operand parenthesized +even if it is an expression; e.g. ``int8_t arr[64]; memset(arr, 42, sizeof(arr));``. + + +Literals +~~~~~~~~ + +Use ``\uXXXX`` unicode escapes for non-ASCII characters. The character +set for XUL, script, and properties files is UTF-8, which is not easily +readable. + + +Prefixes +~~~~~~~~ + +Follow these naming prefix conventions: + + +Variable prefixes +^^^^^^^^^^^^^^^^^ + +- k=constant (e.g. ``kNC_child``). Not all code uses this style; some + uses ``ALL_CAPS`` for constants. +- g=global (e.g. ``gPrefService``) +- a=argument (e.g. ``aCount``) +- C++ Specific Prefixes + + - s=static member (e.g. ``sPrefChecked``) + - m=member (e.g. ``mLength``) + - e=enum variants (e.g. ``enum Foo { eBar, eBaz }``). Enum classes + should use ``CamelCase`` instead (e.g. + ``enum class Foo { Bar, Baz }``). + + +Global functions/macros/etc +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Macros begin with ``MOZ_``, and are all caps (e.g. + ``MOZ_WOW_GOODNESS``). Note that older code uses the ``NS_`` prefix; + while these aren't being changed, you should only use ``MOZ_`` for + new macros. The only exception is if you're creating a new macro, + which is part of a set of related macros still using the old ``NS_`` + prefix. Then you should be consistent with the existing macros. + + +Error Variables +^^^^^^^^^^^^^^^ + +- Local variables that are assigned ``nsresult`` result codes should be named ``rv`` + (i.e., e.g., not ``res``, not ``result``, not ``foo``). `rv` should not be + used for bool or other result types. +- Local variables that are assigned ``bool`` result codes should be named `ok`. + + +C/C++ practices +--------------- + +- **Have you checked for compiler warnings?** Warnings often point to + real bugs. `Many of them `__ + are enabled by default in the build system. +- In C++ code, use ``nullptr`` for pointers. In C code, using ``NULL`` + or ``0`` is allowed. + +.. note:: + + For the C++ rule, clang-tidy provides the ``modernize-use-nullptr`` check + with autofixes. + +- Don't use ``PRBool`` and ``PRPackedBool`` in C++, use ``bool`` + instead. +- For checking if a ``std`` container has no items, don't use + ``size()``, instead use ``empty()``. +- When testing a pointer, use ``(!myPtr)`` or ``(myPtr)``; + don't use ``myPtr != nullptr`` or ``myPtr == nullptr``. +- Do not compare ``x == true`` or ``x == false``. Use ``(x)`` or + ``(!x)`` instead. ``if (x == true)`` may have semantics different from + ``if (x)``! + +.. note:: + + clang-tidy provides the ``readability-simplify-boolean-expr`` check + with autofixes that checks for these and some other boolean expressions + that can be simplified. + +- In general, initialize variables with ``nsFoo aFoo = bFoo,`` and not + ``nsFoo aFoo(bFoo)``. + + - For constructors, initialize member variables with : ``nsFoo + aFoo(bFoo)`` syntax. + +- To avoid warnings created by variables used only in debug builds, use + the + `DebugOnly `__ + helper when declaring them. +- You should `use the static preference + API `__ for + working with preferences. +- One-argument constructors, that are not copy or move constructors, + should generally be marked explicit. Exceptions should be annotated + with ``MOZ_IMPLICIT``. +- Use ``char32_t`` as the return type or argument type of a method that + returns or takes as argument a single Unicode scalar value. (Don't + use UTF-32 strings, though.) +- Prefer unsigned types for semantically-non-negative integer values. +- When operating on integers that could overflow, use ``CheckedInt``. +- Avoid the usage of ``typedef``, instead, please use ``using`` instead. + +.. note:: + + For parts of this rule, clang-tidy provides the ``modernize-use-using`` + check with autofixes. + + +Header files +------------ + +Since the Firefox code base is huge and uses a monolithic build, it is +of utmost importance for keeping build times reasonable to limit the +number of included files in each translation unit to the required minimum. +Exported header files need particular attention in this regard, since their +included files propagate, and many of them are directly or indirectly +included in a large number of translation units. + +- Include guards are named per the Google coding style (i.e. upper snake + case with a single trailing underscore). They should not include a + leading ``MOZ_`` or ``MOZILLA_``. For example, ``dom/media/foo.h`` + would use the guard ``DOM_MEDIA_FOO_H_``. +- Forward-declare classes in your header files, instead of including + them, whenever possible. For example, if you have an interface with a + ``void DoSomething(nsIContent* aContent)`` function, forward-declare + with ``class nsIContent;`` instead of ``#include "nsIContent.h"``. + If a "forwarding header" is provided for a type, include that instead of + putting the literal forward declaration(s) in your header file. E.g. for + some JavaScript types, there is ``js/TypeDecls.h``, for the string types + there is ``StringFwd.h``. One reason for this is that this allows + changing a type to a type alias by only changing the forwarding header. + The following uses of a type can be done with a forward declaration only: + + - Parameter or return type in a function declaration + - Member/local variable pointer or reference type + - Use as a template argument (not in all cases) in a member/local variable type + - Defining a type alias + + The following uses of a type require a full definition: + + - Base class + - Member/local variable type + - Use with delete or new + - Use as a template argument (not in all cases) + - Any uses of non-scoped enum types + - Enum values of a scoped enum type + + Use as a template argument is somewhat tricky. It depends on how the + template uses the type. E.g. ``mozilla::Maybe`` and ``AutoTArray`` + always require a full definition of ``T`` because the size of the + template instance depends on the size of ``T``. ``RefPtr`` and + ``UniquePtr`` don't require a full definition (because their + pointer member always has the same size), but their destructor + requires a full definition. If you encounter a template that cannot + be instantiated with a forward declaration only, but it seems + it should be possible, please file a bug (if it doesn't exist yet). + + Therefore, also consider the following guidelines to allow using forward + declarations as widely as possible. +- Inline function bodies in header files often pull in a lot of additional + dependencies. Be mindful when adding or extending inline function bodies, + and consider moving the function body to the cpp file or to a separate + header file that is not included everywhere. Bug 1677553 intends to provide + a more specific guideline on this. +- Consider the use of the `Pimpl idiom `__, + i.e. hide the actual implementation in a separate ``Impl`` class that is + defined in the implementation file and only expose a ``class Impl;`` forward + declaration and ``UniquePtr`` member in the header file. +- Do not use non-scoped enum types. These cannot be forward-declared. Use + scoped enum types instead, and forward declare them when possible. +- Avoid nested types that need to be referenced from outside the class. + These cannot be forward declared. Place them in a namespace instead, maybe + in an extra inner namespace, and forward declare them where possible. +- Avoid mixing declarations with different sets of dependencies in a single + header file. This is generally advisable, but even more so when some of these + declarations are used by a subset of the translation units that include the + combined header file only. Consider such a badly mixed header file like: + + .. code-block:: cpp + + /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim: set ts=8 sts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #ifndef BAD_MIXED_FILE_H_ + #define BAD_MIXED_FILE_H_ + + // Only this include is needed for the function declaration below. + #include "nsCOMPtr.h" + + // These includes are only needed for the class definition. + #include "nsIFile.h" + #include "mozilla/ComplexBaseClass.h" + + namespace mozilla { + + class WrappedFile : public nsIFile, ComplexBaseClass { + // ... class definition left out for clarity + }; + + // Assuming that most translation units that include this file only call + // the function, but don't need the class definition, this should be in a + // header file on its own in order to avoid pulling in the other + // dependencies everywhere. + nsCOMPtr CreateDefaultWrappedFile(nsCOMPtr&& aFileToWrap); + + } // namespace mozilla + + #endif // BAD_MIXED_FILE_H_ + + +An example header file based on these rules (with some extra comments): + +.. code-block:: cpp + + /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim: set ts=8 sts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #ifndef DOM_BASE_FOO_H_ + #define DOM_BASE_FOO_H_ + + // Include guards should come at the very beginning and always use exactly + // the style above. Otherwise, compiler optimizations that avoid rescanning + // repeatedly included headers might not hit and cause excessive compile + // times. + + #include + #include "nsCOMPtr.h" // This is needed because we have a nsCOMPtr data member. + + class nsIFile; // Used as a template argument only. + enum class nsresult : uint32_t; // Used as a parameter type only. + template + class RefPtr; // Used as a return type only. + + namespace mozilla::dom { + + class Document; // Used as a template argument only. + + // Scoped enum, not as a nested type, so it can be + // forward-declared elsewhere. + enum class FooKind { Small, Big }; + + class Foo { + public: + // Do not put the implementation in the header file, it would + // require including nsIFile.h + Foo(nsCOMPtr aFile, FooKind aFooKind); + + RefPtr CreateDocument(); + + void SetResult(nsresult aResult); + + // Even though we will default this destructor, do this in the + // implementation file since we would otherwise need to include + // nsIFile.h in the header. + ~Foo(); + + private: + nsCOMPtr mFile; + }; + + } // namespace mozilla::dom + + #endif // DOM_BASE_FOO_H_ + + +Corresponding implementation file: + +.. code-block:: cpp + + /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim: set ts=8 sts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "mozilla/dom/Foo.h" // corresponding header + + #include "mozilla/Assertions.h" // Needed for MOZ_ASSERT. + #include "mozilla/dom/Document.h" // Needed because we construct a Document. + #include "nsError.h" // Needed because we use NS_OK aka nsresult::NS_OK. + #include "nsIFile.h" // This is needed because our destructor indirectly calls delete nsIFile in a template instance. + + namespace mozilla::dom { + + // Do not put the implementation in the header file, it would + // require including nsIFile.h + Foo::Foo(nsCOMPtr aFile, FooKind aFooKind) + : mFile{std::move(aFile)} { + } + + RefPtr Foo::CreateDocument() { + return MakeRefPtr(); + } + + void Foo::SetResult(nsresult aResult) { + MOZ_ASSERT(aResult != NS_OK); + + // do something with aResult + } + + // Even though we default this destructor, do this in the + // implementation file since we would otherwise need to include + // nsIFile.h in the header. + Foo::~Foo() = default; + + } // namespace mozilla::dom + + +Include directives +------------------ + +- Ordering: + + - In an implementation file (cpp file), the very first include directive + should include the corresponding header file, followed by a blank line. + - Any conditional includes (depending on some ``#ifdef`` or similar) follow + after non-conditional includes. Don't mix them in. + - Don't place comments between non-conditional includes. + + Bug 1679522 addresses automating the ordering via clang-format, which + is going to enforce some stricter rules. Expect the includes to be reordered. + If you include third-party headers that are not self-contained, and therefore + need to be included in a particular order, enclose those (and only those) + between ``// clang-format off`` and ``// clang-format on``. This should not be + done for Mozilla headers, which should rather be made self-contained if they + are not. + +- Brackets vs. quotes: C/C++ standard library headers are included using + brackets (e.g. ``#include ``), all other include directives use + (double) quotes (e.g. ``#include "mozilla/dom/Document.h``). +- Exported headers should always be included from their exported path, not + from their source path in the tree, even if available locally. E.g. always + do ``#include "mozilla/Vector.h"``, not ``#include "Vector.h"``, even + from within `mfbt`. +- Generally, you should include exactly those headers that are needed, not + more and not less. Unfortunately this is not easy to see. Maybe C++20 + modules will bring improvements to this, but it will take a long time + to be adopted. +- The basic rule is that if you literally use a symbol in your file that + is declared in a header A.h, include that header. In particular in header + files, check if a forward declaration or including a forwarding header is + sufficient, see section :ref:`Header files`. + + There are cases where this basic rule is not sufficient. Some cases where + you need to include additional headers are: + + - You reference a member of a type that is not literally mentioned in your + code, but, e.g. is the return type of a function you are calling. + + There are also cases where the basic rule leads to redundant includes. Note + that "redundant" here does not refer to "accidentally redundant" headers, + e.g. at the time of writing ``mozilla/dom/BodyUtil.h`` includes + ``mozilla/dom/FormData.h``, but it doesn't need to (it only needs a forward + declaration), so including ``mozilla/dom/FormData.h`` is "accidentally + redundant" when including ``mozilla/dom/BodyUtil.h``. The includes of + ``mozilla/dom/BodyUtil.h`` might change at any time, so if a file that + includes ``mozilla/dom/BodyUtil.h`` needs a full definition of + ``mozilla::dom::FormData``, it should includes ``mozilla/dom/FormData.h`` + itself. In fact, these "accidentally redundant" headers MUST be included. + Relying on accidentally redundant includes makes any change to a header + file extremely hard, in particular when considering that the set of + accidentally redundant includes differs between platforms. + But some cases in fact are non-accidentally redundant, and these can and + typically should not be repeated: + + - The includes of the header file do not need to be repeated in its + corresponding implementation file. Rationale: the implementation file and + its corresponding header file are tightly coupled per se. + + Macros are a special case. Generally, the literal rule also applies here, + i.e. if the macro definition references a symbol, the file containing the + macro definition should include the header defining the symbol. E.g. + ``NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE`` defined in ``nsISupportsImpl.h`` + makes use of ``MOZ_ASSERT`` defined in ``mozilla/Assertions.h``, so + ``nsISupportsImpl.h`` includes ``mozilla/Assertions.h``. However, this + requires human judgment of what is intended, since technically only the + invocations of the macro reference a symbol (and that's how + include-what-you-use handles this). It might depend on the + context or parameters which symbol is actually referenced, and sometimes + this is on purpose. In these cases, the user of the macro needs to include + the required header(s). + + + +COM and pointers +---------------- + +- Use ``nsCOMPtr<>`` + If you don't know how to use it, start looking in the code for + examples. The general rule, is that the very act of typing + ``NS_RELEASE`` should be a signal to you to question your code: + "Should I be using ``nsCOMPtr`` here?". Generally the only valid use + of ``NS_RELEASE`` is when you are storing refcounted pointers in a + long-lived datastructure. +- Declare new XPCOM interfaces using :doc:`XPIDL `, so they + will be scriptable. +- Use :doc:`nsCOMPtr ` for strong references, and + ``nsWeakPtr`` for weak references. +- Don't use ``QueryInterface`` directly. Use ``CallQueryInterface`` or + ``do_QueryInterface`` instead. +- Use :ref:`Contract IDs `, + instead of CIDs with ``do_CreateInstance``/``do_GetService``. +- Use pointers, instead of references for function out parameters, even + for primitive types. + + +IDL +--- + + +Use leading-lowercase, or "interCaps" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When defining a method or attribute in IDL, the first letter should be +lowercase, and each following word should be capitalized. For example: + +.. code-block:: cpp + + long updateStatusBar(); + + +Use attributes wherever possible +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whenever you are retrieving or setting a single value, without any +context, you should use attributes. Don't use two methods when you could +use an attribute. Using attributes logically connects the getting and +setting of a value, and makes scripted code look cleaner. + +This example has too many methods: + +.. code-block:: cpp + + interface nsIFoo : nsISupports + { + long getLength(); + void setLength(in long length); + long getColor(); + }; + +The code below will generate the exact same C++ signature, but is more +script-friendly. + +.. code-block:: cpp + + interface nsIFoo : nsISupports + { + attribute long length; + readonly attribute long color; + }; + + +Use Java-style constants +~~~~~~~~~~~~~~~~~~~~~~~~ + +When defining scriptable constants in IDL, the name should be all +uppercase, with underscores between words: + +.. code-block:: cpp + + const long ERROR_UNDEFINED_VARIABLE = 1; + + +See also +~~~~~~~~ + +For details on interface development, as well as more detailed style +guides, see the `Interface development +guide `__. + + +Error handling +-------------- + + +Check for errors early and often +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Every time you make a call into an XPCOM function, you should check for +an error condition. You need to do this even if you know that call will +never fail. Why? + +- Someone may change the callee in the future to return a failure + condition. +- The object in question may live on another thread, another process, + or possibly even another machine. The proxy could have failed to make + your call in the first place. + +Also, when you make a new function which is failable (i.e. it will +return a ``nsresult`` or a ``bool`` that may indicate an error), you should +explicitly mark the return value should always be checked. For example: + +:: + + // for IDL. + [must_use] nsISupports + create(); + + // for C++, add this in *declaration*, do not add it again in implementation. + [[nodiscard]] nsresult + DoSomething(); + +There are some exceptions: + +- Predicates or getters, which return ``bool`` or ``nsresult``. +- IPC method implementation (For example, ``bool RecvSomeMessage()``). +- Most callers will check the output parameter, see below. + +.. code-block:: cpp + + nsresult + SomeMap::GetValue(const nsString& key, nsString& value); + +If most callers need to check the output value first, then adding +``[[nodiscard]]`` might be too verbose. In this case, change the return value +to void might be a reasonable choice. + +There is also a static analysis attribute ``[[nodiscard]]``, which can +be added to class declarations, to ensure that those declarations are +always used when they are returned. + + +Use the NS_WARN_IF macro when errors are unexpected. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``NS_WARN_IF`` macro can be used to issue a console warning, in debug +builds if the condition fails. This should only be used when the failure +is unexpected and cannot be caused by normal web content. + +If you are writing code which wants to issue warnings when methods fail, +please either use ``NS_WARNING`` directly, or use the new ``NS_WARN_IF`` macro. + +.. code-block:: cpp + + if (NS_WARN_IF(somethingthatshouldbefalse)) { + return NS_ERROR_INVALID_ARG; + } + + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + +Previously, the ``NS_ENSURE_*`` macros were used for this purpose, but +those macros hide return statements, and should not be used in new code. +(This coding style rule isn't generally agreed, so use of ``NS_ENSURE_*`` +can be valid.) + + +Return from errors immediately +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In most cases, your knee-jerk reaction should be to return from the +current function, when an error condition occurs. Don't do this: + +.. code-block:: cpp + + rv = foo->Call1(); + if (NS_SUCCEEDED(rv)) { + rv = foo->Call2(); + if (NS_SUCCEEDED(rv)) { + rv = foo->Call3(); + } + } + return rv; + +Instead, do this: + +.. code-block:: cpp + + rv = foo->Call1(); + if (NS_FAILED(rv)) { + return rv; + } + + rv = foo->Call2(); + if (NS_FAILED(rv)) { + return rv; + } + + rv = foo->Call3(); + if (NS_FAILED(rv)) { + return rv; + } + +Why? Error handling should not obfuscate the logic of the code. The +author's intent, in the first example, was to make 3 calls in +succession. Wrapping the calls in nested if() statements, instead +obscured the most likely behavior of the code. + +Consider a more complicated example to hide a bug: + +.. code-block:: cpp + + bool val; + rv = foo->GetBooleanValue(&val); + if (NS_SUCCEEDED(rv) && val) { + foo->Call1(); + } else { + foo->Call2(); + } + +The intent of the author, may have been, that ``foo->Call2()`` would only +happen when val had a false value. In fact, ``foo->Call2()`` will also be +called, when ``foo->GetBooleanValue(&val)`` fails. This may, or may not, +have been the author's intent. It is not clear from this code. Here is +an updated version: + +.. code-block:: cpp + + bool val; + rv = foo->GetBooleanValue(&val); + if (NS_FAILED(rv)) { + return rv; + } + if (val) { + foo->Call1(); + } else { + foo->Call2(); + } + +In this example, the author's intent is clear, and an error condition +avoids both calls to ``foo->Call1()`` and ``foo->Call2();`` + +*Possible exceptions:* Sometimes it is not fatal if a call fails. For +instance, if you are notifying a series of observers that an event has +fired, it might be trivial that one of these notifications failed: + +.. code-block:: cpp + + for (size_t i = 0; i < length; ++i) { + // we don't care if any individual observer fails + observers[i]->Observe(foo, bar, baz); + } + +Another possibility, is you are not sure if a component exists or is +installed, and you wish to continue normally, if the component is not +found. + +.. code-block:: cpp + + nsCOMPtr service = do_CreateInstance(NS_MYSERVICE_CID, &rv); + // if the service is installed, then we'll use it. + if (NS_SUCCEEDED(rv)) { + // non-fatal if this fails too, ignore this error. + service->DoSomething(); + + // this is important, handle this error! + rv = service->DoSomethingImportant(); + if (NS_FAILED(rv)) { + return rv; + } + } + + // continue normally whether or not the service exists. + + +Strings +------- + +.. note:: + + This section overlaps with the more verbose advice given in + :doc:`String guide `. + These should eventually be merged. For now, please refer to that guide for + more advice. + +- String arguments to functions should be declared as ``[const] nsA[C]String&``. +- Prefer using string literals. In particular, use empty string literals, + i.e. ``u""_ns`` or ``""_ns``, instead of ``Empty[C]String()`` or + ``const nsAuto[C]String empty;``. Use ``Empty[C]String()`` only if you + specifically need a ``const ns[C]String&``, e.g. with the ternary operator + or when you need to return/bind to a reference or take the address of the + empty string. +- For 16-bit literal strings, use ``u"..."_ns`` or, if necessary + ``NS_LITERAL_STRING_FROM_CSTRING(...)`` instead of ``nsAutoString()`` + or other ways that would do a run-time conversion. + See :ref:`Avoid runtime conversion of string literals ` below. +- To compare a string with a literal, use ``.EqualsLiteral("...")``. +- Use ``str.IsEmpty()`` instead of ``str.Length() == 0``. +- Use ``str.Truncate()`` instead of ``str.SetLength(0)``, + ``str.Assign(""_ns)`` or ``str.AssignLiteral("")``. +- Don't use functions from ``ctype.h`` (``isdigit()``, ``isalpha()``, + etc.) or from ``strings.h`` (``strcasecmp()``, ``strncasecmp()``). + These are locale-sensitive, which makes them inappropriate for + processing protocol text. At the same time, they are too limited to + work properly for processing natural-language text. Use the + alternatives in ``mozilla/TextUtils.h`` and in ``nsUnicharUtils.h`` + in place of ``ctype.h``. In place of ``strings.h``, prefer the + ``nsStringComparator`` facilities for comparing strings or if you + have to work with zero-terminated strings, use ``nsCRT.h`` for + ASCII-case-insensitive comparison. + + +Use the ``Auto`` form of strings for local values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When declaring a local, short-lived ``nsString`` class, always use +``nsAutoString`` or ``nsAutoCString``. These pre-allocate a 64-byte +buffer on the stack, and avoid fragmenting the heap. Don't do this: + +.. code-block:: cpp + + nsresult + foo() + { + nsCString bar; + .. + } + +instead: + +.. code-block:: cpp + + nsresult + foo() + { + nsAutoCString bar; + .. + } + + +Be wary of leaking values from non-XPCOM functions that return char\* or PRUnichar\* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is an easy trap to return an allocated string, from an internal +helper function, and then using that function inline in your code, +without freeing the value. Consider this code: + +.. code-block:: cpp + + static char* + GetStringValue() + { + .. + return resultString.ToNewCString(); + } + + .. + WarnUser(GetStringValue()); + +In the above example, ``WarnUser`` will get the string allocated from +``resultString.ToNewCString()`` and throw away the pointer. The +resulting value is never freed. Instead, either use the string classes, +to make sure your string is automatically freed when it goes out of +scope, or make sure that your string is freed. + +Automatic cleanup: + +.. code-block:: cpp + + static void + GetStringValue(nsAWritableCString& aResult) + { + .. + aResult.Assign("resulting string"); + } + + .. + nsAutoCString warning; + GetStringValue(warning); + WarnUser(warning.get()); + +Free the string manually: + +.. code-block:: cpp + + static char* + GetStringValue() + { + .. + return resultString.ToNewCString(); + } + + .. + char* warning = GetStringValue(); + WarnUser(warning); + nsMemory::Free(warning); + +.. _Avoid runtime conversion of string literals: + +Avoid runtime conversion of string literals +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is very common to need to assign the value of a literal string, such +as ``"Some String"``, into a unicode buffer. Instead of using ``nsString``'s +``AssignLiteral`` and ``AppendLiteral``, use a user-defined literal like `u"foo"_ns` +instead. On most platforms, this will force the compiler to compile in a +raw unicode string, and assign it directly. In cases where the literal is defined +via a macro that is used in both 8-bit and 16-bit ways, you can use +`NS_LITERAL_STRING_FROM_CSTRING` to do the conversion at compile time. + +Incorrect: + +.. code-block:: cpp + + nsAutoString warning; + warning.AssignLiteral("danger will robinson!"); + ... + foo->SetStringValue(warning); + ... + bar->SetUnicodeValue(warning.get()); + +Correct: + +.. code-block:: cpp + + constexpr auto warning = u"danger will robinson!"_ns; + ... + // if you'll be using the 'warning' string, you can still use it as before: + foo->SetStringValue(warning); + ... + bar->SetUnicodeValue(warning.get()); + + // alternatively, use the wide string directly: + foo->SetStringValue(u"danger will robinson!"_ns); + ... + + // if a macro is the source of a 8-bit literal and you cannot change it, use + // NS_LITERAL_STRING_FROM_CSTRING, but only if necessary. + #define MY_MACRO_LITERAL "danger will robinson!" + foo->SetStringValue(NS_LITERAL_STRING_FROM_CSTRING(MY_MACRO_LITERAL)); + + // If you need to pass to a raw const char16_t *, there's no benefit to + // go through our string classes at all, just do... + bar->SetUnicodeValue(u"danger will robinson!"); + + // .. or, again, if a macro is the source of a 8-bit literal + bar->SetUnicodeValue(u"" MY_MACRO_LITERAL); + + +Usage of PR_(MAX|MIN|ABS|ROUNDUP) macro calls +--------------------------------------------- + +Use the standard-library functions (``std::max``), instead of +``PR_(MAX|MIN|ABS|ROUNDUP)``. + +Use ``mozilla::Abs`` instead of ``PR_ABS``. All ``PR_ABS`` calls in C++ code have +been replaced with ``mozilla::Abs`` calls, in `bug +847480 `__. All new +code in ``Firefox/core/toolkit`` needs to ``#include "nsAlgorithm.h"`` and +use the ``NS_foo`` variants instead of ``PR_foo``, or +``#include "mozilla/MathAlgorithms.h"`` for ``mozilla::Abs``. + +Use of SpiderMonkey rooting typedefs +------------------------------------ +The rooting typedefs in ``js/public/TypeDecls.h``, such as ``HandleObject`` and +``RootedObject``, are deprecated both in and outside of SpiderMonkey. They will +eventually be removed and should not be used in new code. diff --git a/docs/code-quality/coding-style/coding_style_general.rst b/docs/code-quality/coding-style/coding_style_general.rst new file mode 100644 index 0000000000..950cd6ccd3 --- /dev/null +++ b/docs/code-quality/coding-style/coding_style_general.rst @@ -0,0 +1,18 @@ + +Mode line +~~~~~~~~~ + +Files should have Emacs and vim mode line comments as the first two +lines of the file, which should set ``indent-tabs-mode`` to ``nil``. For new +files, use the following, specifying two-space indentation: + +.. code-block:: cpp + + /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim: set ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +Be sure to use the correct ``Mode`` in the first line, don't use ``C++`` in +JavaScript files. diff --git a/docs/code-quality/coding-style/coding_style_java.rst b/docs/code-quality/coding-style/coding_style_java.rst new file mode 100644 index 0000000000..f2206d8e2d --- /dev/null +++ b/docs/code-quality/coding-style/coding_style_java.rst @@ -0,0 +1,68 @@ +================= +Java Coding style +================= + +- We use the `Java Coding + Style `__. + Quick summary: + + - FirstLetterUpperCase for class names. + - camelCase for method and variable names. + - One declaration per line: + + .. code-block:: java + + int x, y; // this is BAD! + int a; // split it over + int b; // two lines + +- Braces should be placed like so (generally, opening braces on same + line, closing braces on a new line): + + .. code-block:: java + + public void func(int arg) { + if (arg != 0) { + while (arg > 0) { + arg--; + } + } else { + arg++; + } + } + +- Places we differ from the Java coding style: + + - Start class variable names with 'm' prefix (e.g. + mSomeClassVariable) and static variables with 's' prefix (e.g. + sSomeStaticVariable) + - ``import`` statements: + + - Do not use wildcard imports like \`import java.util.*;\` + - Organize imports by blocks separated by empty line: + org.mozilla.*, android.*, com.*, net.*, org.*, then java.\* + This is basically what Android Studio does by default, except + that we place org.mozilla.\* at the front - please adjust + Settings -> Editor -> Code Style -> Java -> Imports + accordingly. + - Within each import block, alphabetize import names with + uppercase before lowercase. For example, ``com.example.Foo`` is + before ``com.example.bar`` + + - 4-space indents. + - Spaces, not tabs. + - Don't restrict yourself to 80-character lines. Google's Android + style guide suggests 100-character lines, which is also the + default setting in Android Studio. Java code tends to be long + horizontally, so use appropriate judgement when wrapping. Avoid + deep indents on wrapping. Note that aligning the wrapped part of a + line, with some previous part of the line (rather than just using + a fixed indent), may require shifting the code every time the line + changes, resulting in spurious whitespace changes. + +- For additional specifics on Firefox for Android, see the `Coding + Style guide for Firefox on + Android `__. +- The `Android Coding + Style `__ has some + useful guidelines too. diff --git a/docs/code-quality/coding-style/coding_style_js.rst b/docs/code-quality/coding-style/coding_style_js.rst new file mode 100644 index 0000000000..09d7a6fc8a --- /dev/null +++ b/docs/code-quality/coding-style/coding_style_js.rst @@ -0,0 +1,147 @@ +======================= +JavaScript Coding style +======================= + +Coding style +~~~~~~~~~~~~ + +`prettier `_ is the tool used to reformat the JavaScript code. + + +Methods and functions +~~~~~~~~~~~~~~~~~~~~~ + +In JavaScript, functions should use camelCase, but should not capitalize +the first letter. Methods should not use the named function expression +syntax, because our tools understand method names: + +.. code-block:: cpp + + doSomething: function (aFoo, aBar) { + ... + } + +In-line functions should have spaces around braces, except before commas +or semicolons: + +.. code-block:: cpp + + function valueObject(aValue) { return { value: aValue }; } + + +JavaScript objects +~~~~~~~~~~~~~~~~~~ + +.. code-block:: cpp + + var foo = { prop1: "value1" }; + + var bar = { + prop1: "value1", + prop2: "value2" + }; + +Constructors for objects should be capitalized and use Pascal Case: + +.. code-block:: cpp + + function ObjectConstructor() { + this.foo = "bar"; + } + + +Operators +~~~~~~~~~ + +In JavaScript, overlong expressions not joined by ``&&`` and +``||`` should break so the operator starts on the second line and +starting in the same column as the beginning of the expression in the +first line. This applies to ``?:``, binary arithmetic operators +including ``+``, and member-of operators. Rationale: an operator at the +front of the continuation line makes for faster visual scanning, as +there is no need to read to the end of line. Also there exists a +context-sensitive keyword hazard in JavaScript; see {{bug(442099, "bug", +19)}}, which can be avoided by putting . at the start of a continuation +line, in long member expression. + +In JavaScript, ``==`` is preferred to ``===``. + +Unary keyword operators, such as ``typeof``, should have their operand +parenthesized; e.g. ``typeof("foo") == "string"``. + +Literals +~~~~~~~~ + +Double-quoted strings (e.g. ``"foo"``) are preferred to single-quoted +strings (e.g. ``'foo'``), in JavaScript, except to avoid escaping +embedded double quotes, or when assigning inline event handlers. + + +Prefixes +~~~~~~~~ + +- k=constant (e.g. ``kNC_child``). Not all code uses this style; some + uses ``ALL_CAPS`` for constants. +- g=global (e.g. ``gPrefService``) +- a=argument (e.g. ``aCount``) + +- JavaScript Specific Prefixes + + - \_=member (variable or function) (e.g. ``_length`` or + ``_setType(aType)``) + - k=enumeration value (e.g. ``const kDisplayModeNormal = 0``) + - on=event handler (e.g. ``function onLoad()``) + - Convenience constants for interface names should be prefixed with + ``nsI``: + + .. code-block:: javascript + + const nsISupports = Components.interfaces.nsISupports; + const nsIWBN = Components.interfaces.nsIWebBrowserNavigation; + + + +Other advices +~~~~~~~~~~~~~ + +- Do not compare ``x == true`` or ``x == false``. Use ``(x)`` or + ``(!x)`` instead. ``x == true``, is certainly different from if + ``(x)``! Compare objects to ``null``, numbers to ``0`` or strings to + ``""``, if there is chance for confusion. +- Make sure that your code doesn't generate any strict JavaScript + warnings, such as: + + - Duplicate variable declaration. + - Mixing ``return;`` with ``return value;`` + - Undeclared variables or members. If you are unsure if an array + value exists, compare the index to the array's length. If you are + unsure if an object member exists, use ``"name"`` in ``aObject``, + or if you are expecting a particular type you may use + ``typeof(aObject.name) == "function"`` (or whichever type you are + expecting). + +- Use ``['value1, value2']`` to create a JavaScript array in preference + to using + ``new {{JSxRef("Array", "Array", "Syntax", 1)}}(value1, value2)`` + which can be confusing, as ``new Array(length)`` will actually create + a physically empty array with the given logical length, while + ``[value]`` will always create a 1-element array. You cannot actually + guarantee to be able to preallocate memory for an array. +- Use ``{ member: value, ... }`` to create a JavaScript object; a + useful advantage over ``new {{JSxRef("Object", "Object", "", 1)}}()`` + is the ability to create initial properties and use extended + JavaScript syntax, to define getters and setters. +- If having defined a constructor you need to assign default + properties, it is preferred to assign an object literal to the + prototype property. +- Use regular expressions, but use wisely. For instance, to check that + ``aString`` is not completely whitespace use + ``/\S/.{{JSxRef("RegExp.test", "test(aString)", "", 1)}}``. Only use + {{JSxRef("String.search", "aString.search()")}} if you need to know + the position of the result, or {{JSxRef("String.match", + "aString.match()")}} if you need to collect matching substrings + (delimited by parentheses in the regular expression). Regular + expressions are less useful if the match is unknown in advance, or to + extract substrings in known positions in the string. For instance, + {{JSxRef("String.slice", "aString.slice(-1)")}} returns the last + letter in ``aString``, or the empty string if ``aString`` is empty. diff --git a/docs/code-quality/coding-style/coding_style_python.rst b/docs/code-quality/coding-style/coding_style_python.rst new file mode 100644 index 0000000000..3a818fcfd4 --- /dev/null +++ b/docs/code-quality/coding-style/coding_style_python.rst @@ -0,0 +1,71 @@ +=================== +Python Coding style +=================== + +Coding style +~~~~~~~~~~~~ + + :ref:`black` is the tool used to reformat the Python code. + +Linting +~~~~~~~ + +The Python linting is done by :ref:`Flake8` and :ref:`pylint` +They are executed by mozlint both at review phase and in the CI. + +Indentation +~~~~~~~~~~~ + +Four spaces in Python code. + + +Makefile/moz.build practices +---------------------------- + +- Changes to makefile and moz.build variables do not require + build-config peer review. Any other build system changes, such as + adding new scripts or rules, require review from the build-config + team. +- Suffix long ``if``/``endif`` conditionals with #{ & #}, so editors + can display matched tokens enclosing a block of statements. + + :: + + ifdef CHECK_TYPE #{ + ifneq ($(flavor var_type),recursive) #{ + $(warning var should be expandable but detected var_type=$(flavor var_type)) + endif #} + endif #} + +- moz.build are python and follow normal Python style. +- List assignments should be written with one element per line. Align + closing square brace with start of variable assignment. If ordering + is not important, variables should be in alphabetical order. + + .. code-block:: python + + var += [ + 'foo', + 'bar' + ] + +- Use ``CONFIG['CPU_ARCH'] {=arm}`` to test for generic classes of + architecture rather than ``CONFIG['OS_TEST'] {=armv7}`` (re: bug 886689). + + +Other advices +~~~~~~~~~~~~~ + +- Install the + `mozext `__ + Mercurial extension, and address every issue reported on commit + or the output of ``hg critic``. +- Follow `PEP 8 `__. Please run :ref:`black` for this. +- Do not place statements on the same line as ``if/elif/else`` + conditionals to form a one-liner. +- Global vars, please avoid them at all cost. +- Exclude outer parenthesis from conditionals.Use + ``if x > 5:,``\ rather than ``if (x > 5):`` +- Use string formatters, rather than var + str(val). + ``var = 'Type %s value is %d'% ('int', 5).`` +- Testing/Unit tests, please write them and make sure that they are executed in the CI. diff --git a/docs/code-quality/coding-style/css_guidelines.rst b/docs/code-quality/coding-style/css_guidelines.rst new file mode 100644 index 0000000000..e962f24d69 --- /dev/null +++ b/docs/code-quality/coding-style/css_guidelines.rst @@ -0,0 +1,572 @@ +CSS Guidelines +============== + +This document contains guidelines defining how CSS inside the Firefox +codebase should be written, it is notably relevant for Firefox front-end +engineers. + +Basics +------ + +Here are some basic tips that can optimize reviews if you are changing +CSS: + +- Avoid ``!important`` but if you have to use it, make sure it's + obvious why you're using it (ideally with a comment). The + `Overriding CSS`_ section contains more information about this. +- Avoid magic numbers; prefer automatic sizing or alignment methods. + Some examples to avoid: + + - absolutely positioned elements + - hardcoded values such as: ``vertical-align: -2px;`` . The reason + you should avoid such "hardcoded" values is that, they don't + necessarily work for all font-size configurations. + +- Avoid setting styles in JavaScript. It's generally better to set a + class and then specify the styles in CSS. +- ``classList`` is generally better than ``className``. There's less + chance of overwriting an existing class. +- Only use generic selectors such as ``:last-child``, when it is what + you mean semantically. If not, using a semantic class name is more + descriptive and usually better. + +Boilerplate +~~~~~~~~~~~ + +Make sure each file starts with the standard copyright header (see +`License Boilerplate `__). + +Before adding more CSS +~~~~~~~~~~~~~~~~~~~~~~ + +It is good practice to check if the CSS that is being written is needed, +it can be the case that a common component has been already written +could be reused with or without changes. Most of the time, the common +component already follows the a11y/theme standards defined in this +guide. So, when possible, always prefer editing common components to +writing your own. + +Also, it is good practice to introduce a common class when the new +element you are styling reuses some styles from another element, this +allows the maintenance cost and the amount of code duplication to be +reduced. + +Formatting +---------- + +Spacing & Indentation +~~~~~~~~~~~~~~~~~~~~~ + +- 2 spaces indentation is preferred +- Add a space after each comma, **except** within color functions: + +.. code:: css + + linear-gradient(to bottom, black 1px, rgba(255,255,255,0.2) 1px) + +- Always add a space before ``!important``. + +Omit units on 0 values +~~~~~~~~~~~~~~~~~~~~~~ + +Do this: + +.. code:: css + + margin: 0; + +Not this: + +.. code:: css + + margin: 0px; + +Use expanded syntax +~~~~~~~~~~~~~~~~~~~ + +It is often harder to understand what the shorthand is doing and the +shorthand can also hide some unwanted default values. It is good to +privilege expanded syntax to make your intentions explicit. + +Do this: + +.. code:: css + + border-color: red; + +Not this: + +.. code:: css + + border: red; + +Put multiple selectors on different lines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Do this: + +.. code:: css + + h1, + h2, + h3 { + font-family: sans-serif; + text-align: center; + } + +Not this: + +.. code:: css + + h1, h2, h3 { + font-family: sans-serif; + text-align: center; + } + +Naming standards for class names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``lower-case-with-dashes`` is the most common. +- But ``camelCase`` is also used sometimes. Try to follow the style of + existing or related code. + +Other tips +~~~~~~~~~~ + +- Assume ``="true"`` in attribute selectors. + + - Example: Use ``option[checked]``, not ``option[checked="true"]``. + +- Avoid ID selectors unless it is really the wanted goal, since IDs + have higher specificity and therefore are harder to override. +- Using descendant selectors is good practice for performance when + possible: + + - For example: + ``.autocomplete-item[selected] > .autocomplete-item-title`` would + be more efficient than + ``.autocomplete-item[selected] .autocomplete-item-title`` + +Overriding CSS +-------------- + +Before overriding any CSS rules, check whether overriding is really +needed. Sometimes, when copy-pasting older code, it happens that the +code in question contains unnecessary overrides. This could be because +the CSS that it was overriding got removed in the meantime. In this +case, dropping the override should work. + +It is also good practice to look at whether the rule you are overriding +is still needed: maybe the UX spec for the component has changed and +that rule can actually be updated or removed. When this is the case, +don't be afraid to remove or update that rule. + +Once the two things above have been checked, check if the other rule you +are overriding contains ``!important``, if that is case, try putting it +in question, because it might have become obsolete. + +Afterwards, check the specificity of the other selector; if it is +causing your rule to be overridden, you can try reducing its +specificity, either by simplifying the selector or by changing where the +rule is placed in the stylesheet. If this isn't possible, you can also +try introducing a ``:not()`` to prevent the other rule from applying, +this is especially relevant for different element states (``:hover``, +``:active``, ``[checked]`` or ``[disabled]``). However, never try to +increase the selector of the rule you are adding as it can easily become +hard to understand. + +Finally, once you have checked all the things above, you can permit +yourself to use ``!important`` along with a comment why it is needed. + +Using CSS variables +------------------- + +Adding new variables +~~~~~~~~~~~~~~~~~~~~ + +Before adding new CSS variables, please consider the following +questions: + +#. **Is the variable value changed at runtime?** + *(Either from JavaScript or overridden by another CSS file)* + **If the answer is no**, consider using a preprocessor variable or + inlining the value. + +#. **Is the variable value used multiple times?** + **If the answer is no and the value isn't changed at runtime**, then + you likely don't need a CSS variable. + +#. **Is there an alternative to using the variable like inheriting or + using the ``currentcolor`` keyword?** + Using inheriting or using ``currentcolor`` will prevent repetition of + the value and it is usually good practice to do so. + +In general, it's good to first think of how some CSS could be written +cleanly without the CSS variable(s) and then think of how the CSS +variable could improve that CSS. + +Using variables +~~~~~~~~~~~~~~~ + +Use the variable according to its naming +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Do this: + +.. code:: css + + xul|tab:hover { + background-color: var(--in-content-box-background-hover); + } + +Not this: + +.. code:: css + + #certificateErrorDebugInformation { + background-color: var(--in-content-box-background-hover); + } + +Localization +------------ + +Text Direction +~~~~~~~~~~~~~~ + +- For margins, padding and borders, use + ``inline-start``/``inline-end`` rather than ``left``/``right``. + *Example:* Use ``margin-inline-start: 3px;`` instead of + ``margin-left: 3px``. +- For RTL-aware positioning (left/right), use + ``inset-inline-start``/``inset-inline-end``. +- For RTL-aware float layouts, ``float: inline-start|inline-end`` can + be used instead of ``float: left|right``. +- The RTL-aware equivalents of + ``border-{top/bottom}-{left/right}-radius`` are + ``border-{start/end}-{start/end}-radius`` +- When there is no special RTL-aware property available, use the pseudo + ``:-moz-locale-dir(ltr|rtl)`` (for XUL files) or ``:dir(ltr|rtl)`` + (for HTML files). +- Remember that while a tab content's scrollbar still shows on the + right in RTL, an overflow scrollbar will show on the left. +- Write ``padding: 0 3px 4px;`` instead of + ``padding: 0 3px 4px 3px;``. This makes it more obvious that the + padding is symmetrical (so RTL won't be an issue). + +.. note:: + + See `CSS Logical Properties and + Values `__ + for more information. + +Testing +~~~~~~~ + +To test for RTL layouts, you can go to ``about:config`` and set +``intl.uidirection`` to ``-1``. + +Writing cross-platform CSS +-------------------------- + +Firefox supports many different platforms and each of those platforms +can contain many different configurations: + +- Windows 7, 8 and 10 + + - Default theme + - Aero basic (Windows 7, 8) + - Windows classic (Windows 7) + - High contrast (All versions) + +- Linux +- macOS + +File structure +~~~~~~~~~~~~~~ + +- The ``browser/`` directory contains styles specific to Firefox +- The ``toolkit/`` directory contains styles that are shared across all + toolkit applications (Thunderbird and SeaMonkey) + +Under each of those two directories, there is a ``themes`` directory +containing 4 sub-directories: + +- ``shared`` +- ``linux`` +- ``osx`` +- ``windows`` + +The ``shared`` directories contain styles shared across all 3 platforms, +while the other 3 directories contain styles respective to their +platform. + +For new CSS, when possible try to privilege using the ``shared`` +directory, instead of writing the same CSS for the 3 platform specific +directories, especially for large blocks of CSS. + +Content CSS vs. Theme CSS +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following directories also contain CSS: + +- ``browser/base/content/`` +- ``toolkit/content/`` + +These directories contain content CSS, that applies on all platforms, +which is styling deemed to be essential for the browser to behave +correctly. To determine whether some CSS is theme-side or content-side, +it is useful to know that certain CSS properties are going to lean one +way or the other: color - 99% of the time it will be theme CSS, overflow +- 99% content. + ++-----------------+--------------+----------------+----------------+ +| 99% theme | 70% theme | 70% content | 99% content | ++=================+==============+================+================+ +| font-\*, color, | line-height, | cursor, width, | overflow, | +| \*-color, | padding, | max-width, | direction, | +| border-\*, | margin | top, | display, | +| -moz-appearance | | bottom [2]_, | \*-align, | +| [1]_ | | etc | align-\*, | +| | | | \*-box-\*, | +| | | | flex-\*, order | ++-----------------+--------------+----------------+----------------+ + +If some CSS is layout or functionality related, then it is likely +content CSS. If it is esthetics related, then it is likely theme CSS. + +When importing your stylesheets, it's best to import the content CSS +before the theme CSS, that way the theme values get to override the +content values (which is probably what you want), and you're going to +want them both after the global values, so your imports will look like +this: + +.. code:: html + + + + + +.. [1] -moz-appearance is tricky. Generally, when specifying + -moz-appearance: foo; you're giving hints as to how something should + act, however -moz-appearance: none; is probably saying 'ignore + browser preconceptions - I want a blank sheet', so that's more + visual. However -moz-appearance values aren't implemented and don't + behave consistently across platforms, so idealism aside + -moz-appearance should always be in theme CSS. + +.. [2] However there is probably a better way than using absolute + positioning. + +Colors +~~~~~~ + +For common areas of the Firefox interface (panels, toolbar buttons, +etc.), mozilla-central often comes with some useful CSS variables that +are adjusted with the correct values for different platform +configurations, so using those CSS variables can definitively save some +testing time, as you can assume they already work correctly. + +Using the ``currentcolor`` keyword or inheriting is also good practice, +because sometimes the needed value is already in the color or on the +parent element. This is especially useful in conjunction with icons +using ``-moz-context-properties: fill;`` where the icon can adjust to +the right platform color automatically from the text color. It is also +possible to use ``currentcolor`` with other properties like +``opacity`` or ``fill-opacity`` to have different +opacities of the platform color. + +High contrast mode +~~~~~~~~~~~~~~~~~~ + +Content area +^^^^^^^^^^^^ + +On Windows high contrast mode, in the content area, Gecko does some +automatic color adjustments regarding page colors. Part of those +adjustments include making all ``box-shadow`` invisible, so this is +something to be aware of if you create a focus ring or a border using +the ``box-shadow`` property: consider using a ``border`` or an +``outline`` if you want the border/focus ring to stay visible in +high-contrast mode. An example of such bug is `bug +1516767 `__. + +Another adjustment to be aware of is that Gecko removes all the +``background-image`` when high contrast mode is enabled. Consider using +an actual ```` tag (for HTML documents) or ``list-style-image`` +(for XUL documents) if rendering the image is important. + +If you are not using Windows, one way to test against those adjustments +on other platforms is: + +- Going to about:preferences +- Clicking on the "Colors..." button in the "Fonts & Colors" + sub-section of the "Language and Appearance" section +- Under "Override the colors specified by the page with your selections + above", select the "Always" option + +Chrome area +^^^^^^^^^^^ + +The automatic adjustments previously mentioned only apply to pages +rendered in the content area. The chrome area of Firefox uses colors as +authored, which is why using pre-defined variables, ``currentcolor`` or +inheritance is useful to integrate with the system theme with little +hassle. + +If not, as a last resort, using `system +colors `__ +also works for non-default Windows themes or Linux. In general, the +following colors are used: + +- ``-moz-Field``: textbox or field background colors, also used as the + background color of listboxes or trees. +- ``-moz-FieldText``: textbox or field text colors, also used as the + text color of listboxes or trees. +- ``-moz-Dialog``: window or dialog background color. +- ``-moz-DialogText``: window or dialog text color. +- ``GrayText``: used on disabled items as text color. Do not use it on + text that is not disabled to desemphsize text, because it does not + guarantee a sufficient contrast ratio for non-disabled text. +- ``ThreeDShadow``: Used as border on elements. +- ``ThreeDLightShadow``: Used as light border on elements. + +Using the background/text pairs is especially important to ensure the +contrast is respected in all situations. Never mix custom text colors +with a system background color and vice-versa. + +Note that using system colors is only useful for the chrome area, since +content area colors are overridden by Gecko anyway. + +Writing media queries +~~~~~~~~~~~~~~~~~~~~~ + +Boolean media queries +^^^^^^^^^^^^^^^^^^^^^ + +Do this: + +.. code:: css + + @media (-moz-mac-yosemite-theme: 0) { + +Not this: + +.. code:: css + + @media not all and (-moz-mac-yosemite-theme) { + +Privilege CSS for most common configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is better to put the most common configuration (latest version of an +OS, or default theme for example) outside of the media query. In the +following example, ``-moz-mac-yosemite-theme`` targets macOS 10.10 and +higher, so it should be privileged over the styling for macOS 10.9. + +Do this: + +.. code:: css + + @media (-moz-mac-yosemite-theme: 0) { + #placesList { + box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2); + } + } + +Not this: + +.. code:: css + + #placesList { + box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2); + } + + @media (-moz-mac-yosemite-theme) { + #placesList { + box-shadow: none; + } + } + +Theme support +------------- + +Firefox comes built-in with 3 themes: default, light and dark. The +built-in light/dark themes are a bit special as they load the +``compacttheme.css`` stylesheet. In addition to this, Firefox supports a +variety of WebExtension themes that can be installed from AMO. For +testing purposes, `here is an example of a WebExtension +theme. `__ + +Writing theme-friendly CSS +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Some CSS variables that are pre-adjusted for different platforms are + also pre-adjusted for themes, so it's again a good idea to use them + for theme support. +- The text color of elements often contains valuable information from + the theme colors, so ``currentcolor``/inheritance is again a good + idea for theme support. +- Never write CSS specially for the built-in light/dark theme in + ``compacttheme.css`` unless that CSS isn't supposed to affect + WebExtension themes. +- These selectors can be used to target dark areas: + + - ``:-moz-lwtheme-brighttext``: dark window frame. + - ``:root[lwt-toolbar-field-brighttext]``: dark address bar and + searchbar. + - ``:root[lwt-popup-brighttext]``: dark arrow panels and + autocomplete panels. + - ``:root[lwt-sidebar-brighttext]``: dark sidebars. + +- If you'd like a different shade of a themed area and no CSS variable + is adequate, using colors with alpha transparency is usually a good + idea, as it will preserve the original theme author's color hue. + +Variables +~~~~~~~~~ + +For clarity, CSS variables that are only used when a theme is enabled +have the ``--lwt-`` prefix. + +Layout & performance +-------------------- + +Layout +~~~~~~ + +Mixing XUL flexbox and HTML flexbox can lead to undefined behavior. + +CSS selectors +~~~~~~~~~~~~~ + +When targeting the root element of a page, using ``:root`` is the most +performant way of doing so. + +Reflows and style flushes +~~~~~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`Performance best practices for Firefox front-end engineers` +for more information about this. + +Misc +---- + +Text aliasing +~~~~~~~~~~~~~ + +When convenient, avoid setting the ``opacity`` property on +text as it will cause text to be aliased differently. + +HDPI support +~~~~~~~~~~~~ + +It's recommended to use SVG since it keeps the CSS clean when supporting +multiple resolutions. See the :ref:`SVG Guidelines` for more information +on SVG usage. + +However, if only 1x and 2x PNG assets are available, you can use this +``@media`` query to target higher density displays (HDPI): + +.. code:: css + + @media (min-resolution: 1.1dppx) diff --git a/docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst b/docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst new file mode 100644 index 0000000000..ca64835410 --- /dev/null +++ b/docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst @@ -0,0 +1,272 @@ +===================================== +Formatting C++ Code With clang-format +===================================== + +Mozilla uses the Google coding style for whitespace, which is enforced +using `clang-format `__. A +specific version of the binary will be installed when +``./mach clang-format`` or ``./mach bootstrap`` are run. We build our +own binaries and update them as needed. + +Options are explicitly defined `in clang-format +itself `__. +If the options are changed in clang upstream, this might cause some +changes in the Firefox tree. For this reason, it is best to use the +mozilla-provided binaries. + +Manual formatting +----------------- + +We provide a mach subcommand for running clang-format from the +command-line. This wrapper handles ensuring the correct version of +clang-format is installed and run. + +If clang-format isn’t installed, the binaries will be automatically +downloaded from taskcluster and installed into ~/.mozbuild. We build our +own clang-format binaries. + + +Formatting local changes +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + $ ./mach clang-format + +When run without arguments, it will run on a local diff. This could miss +some reformatting (for example, when blocks are touched). +(`searchfox `__) + + +Formatting specific paths +~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + $ ./mach clang-format -p # Format in-place + $ ./mach clang-format -p -s # Show changes + +The command also accepts a ``-p`` argument to reformat a specific +directory or file, and a ``-s`` flag to show the changes instead of +applying them to the working directory +(`searchfox `__) + + +Formatting specific commits / revisions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + $ ./mach clang-format -c HEAD # Format a single git commit + $ ./mach clang-format -c HEAD~~..HEAD # Format a range of git commits + $ ./mach clang-format -c . # Format a single mercurial revision + +The command accepts a ``-c`` argument that takes a revision number or +commit range, and will format the lines modified by those commits. +(`searchfox `__) + + +Scripting Clang-Format +~~~~~~~~~~~~~~~~~~~~~~ + +Clang format expects that the path being passed to it is the path +on-disk. If this is not the case, for example when formatting a +temporary file, the "real" path must be specified. This can be done with +the ``--assume-filename `` argument. + + +Configuring the clang-format commit hook +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To run clang-format at commit phase, run ``mach boostrap`` or just add +the following line in the ``hgrc`` file: + +.. code:: ini + + [extensions] + clang-format = ~/.mozbuild/version-control-tools/hgext/clang-format + +We use a hg extension as they are more flexible than hooks. + +With git, the configuration is the following: + +:: + + # From the root git directory: + $ ln -s $(pwd)/tools/lint/hooks_clang_format.py .git/hooks/pre-commit + +You'll likely need to install the ``python-hglib`` package for your OS, +or else you may get errors like ``abort: No module named hglib.client!`` +when you try to commit. + + +Editor integration +------------------ + +It is possible to configure many editors to support running +``clang-format`` automatically on save, or when run from within the +editor. + + +Editor plugins +~~~~~~~~~~~~~~ + +- `Atom `__ +- `BBEdit `__ + + - `clang-format-bbedit.applescript `__ + +- Eclipse + + - Install the + `CppStyle `__ + plugin + - In Preferences -> C/C++ -> CppStyle, set the clang-format path to + ~/.mozbuild/clang-tools/clang-tidy/bin/clang-format + - (Optional) check "Run clang-format on file save" + +- `Emacs `__ + + - `clang-format.el `__ + (Or install + `clang-format `__ from MELPA) + - `google-c-style `__ from MELPA + +- `Sublime Text `__ + + - `alternative + tool `__ + +- `Vim `__ + + - `clang-format.py `__ + - `vim-clang-format `__ + +- `Visual + Studio `__ + + - `llvm.org plugin `__ + - `Integrated support in Visual Studio + 2017 `__ + +- `Visual Studio + Code `__ +- `XCode `__ +- `Script for patch + reformatting `__ + + - `clang-format-diff.py `__ + + +Configuration +~~~~~~~~~~~~~ + +These tools generally run clang-format themselves, and won't use +``./mach clang-format``. The binary installed by our tooling will be +located at ``~/.mozbuild/clang-tools/clang-tidy/bin/clang-format``. + +You typically shouldn't need to specify any other special configuration +in your editor besides the clang-format binary. Most of the +configuration that clang-format relies on for formatting is stored +inside our source tree. More specifically, using the .clang-format file +located in the root of the repository. Please note that this doesn't +include the list of ignored files and directories (provided by +.clang-format-ignore which is a feature provided by the mach command +wrapper). + +Coding style configuration is done within clang-format itself. When we +change the configuration (incorrect configuration, new feature in clang, +etc), we use `local +overrides `__. + + +Ignored files & directories +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We maintain a `list of ignored directories and +files `__, +which is used by ``./mach clang-format``. This is generally only used +for code broken by clang-format, and third-party code. + + +Ignored code hunks +~~~~~~~~~~~~~~~~~~ + +Sections of code may have formatting disabled using comments. If a +section must not be formatted, the following comments will disable the +reformat: + +:: + + // clang-format off + my code which should not be reformatted + // clang-format on + +You can find an `example of code not +formatted `__. + + +Merging formatted and unformatted code +-------------------------------------- + +During the transition to using chromium style enforced by clang-format +for all code in tree, it will often be necessary to rebase non-formatted +code onto a formatted tree. + + +Mercurial +~~~~~~~~~ + +The ``format-source`` extension, now bundled with +``version-control-tools``, and installed by ``./mach bootstrap``, may be +used to seamlessly handle this situation. More details may be found in +this +`document `__. + +The parent changeset of the reformat has been tagged as +``PRE_TREEWIDE_CLANG_FORMAT``. + + +Git +~~~ + +To perform a rebase onto mozilla-central after the merge, a handy merge +driver, ``clang-format-merge``, has been written: + +.. code:: shell + + $ git clone https://github.com/emilio/clang-format-merge + $ /path/to/clang-format-merge/git-wrapper rebase + +The wrapper should clean up after itself, and the clone may be deleted +after the rebase is complete. + + +Ignore lists +------------ + +To make sure that the blame/annotate features of Mercurial or git aren't +affected. Two files are maintained to keep track of the reformatting +commits. + + +With Mercurial +~~~~~~~~~~~~~~ + +| The list is stored in + `https://searchfox.org/mozilla-central/source/.hg-annotate-ignore-revs `__ +| Commit messages should also contain the string ``# ignore-this-changeset`` + +The syntax in this file is generated using the following syntax: + +:: + + $ hg log --template '{node} - {author|person} - {desc|strip|firstline}\n' + +With git +~~~~~~~~ + +The list is stored in +`https://searchfox.org/mozilla-central/source/.git-blame-ignore-revs `__ +and contains git revisions for both gecko-dev and the git cinnabar +repository. diff --git a/docs/code-quality/coding-style/index.rst b/docs/code-quality/coding-style/index.rst new file mode 100644 index 0000000000..e62ce910ca --- /dev/null +++ b/docs/code-quality/coding-style/index.rst @@ -0,0 +1,20 @@ +Coding style +============ + +Firefox code is using different programming languages. +For each language, we are enforcing a specific coding style. + +Getting Help +------------ + +If you need help or have questions, please don’t hesitate to contact us via Matrix +in the "Lint and Formatting" room +(`#lint:mozilla.org `_). + + +.. toctree:: + :caption: Coding Style User Guide + :maxdepth: 2 + :glob: + + * diff --git a/docs/code-quality/coding-style/rtl_guidelines.rst b/docs/code-quality/coding-style/rtl_guidelines.rst new file mode 100644 index 0000000000..8b2a6bcf04 --- /dev/null +++ b/docs/code-quality/coding-style/rtl_guidelines.rst @@ -0,0 +1,356 @@ +RTL Guidelines +============== + +RTL languages such as Arabic, Hebrew, Persian and Urdu are read and +written from right-to-left, and the user interface for these languages +should be mirrored to ensure the content is easy to understand. + +When a UI is changed from LTR to RTL (or vice-versa), it’s often called +mirroring. An RTL layout is the mirror image of an LTR layout, and it +affects layout, text, and graphics. + +In RTL, anything that relates to time should be depicted as moving from +right to left. For example, forward points to the left, and backwards +points to the right. + +Mirroring layout +~~~~~~~~~~~~~~~~ + +When a UI is mirrored, these changes occur: + +- Text fields icons are displayed on the opposite side of a field +- Navigation buttons are displayed in reverse order +- Icons that communicate direction, like arrows, are mirrored +- Text is usually aligned to the right + +In CSS, while it's possible to apply a rule for LTR and a separate one +specifically for RTL, it's usually better to use CSS `Logical Properties `_ +which provide the ability to control layout through logical, rather than +physical mappings. + ++---------------------------------------------------------+--------------------------------------------------+ +| Do | Don't do | ++---------------------------------------------------------+--------------------------------------------------+ +| ``margin-inline-start: 5px`` | ``margin-left: 5px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``padding-inline-end: 5px`` | ``padding-right: 5px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``float: inline-start`` | ``float: left`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``inset-inline-start: 5px`` | ``left: 5px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``border-inline-end: 1px`` | ``border-right: 1px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``border-{start/end}-{start/end}-radius: 2px`` | ``border-{top/bottom}-{left/right}-radius: 2px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``padding: 1px 2px`` | ``padding: 1px 2px 1px 2px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``margin-block: 1px 3px`` && ``margin-inline: 4px 2px`` | ``margin: 1px 2px 3px 4px`` | ++---------------------------------------------------------+--------------------------------------------------+ +| ``text-align: start`` or ``text-align: match-parent`` | ``text-align: left`` | +| (depends on the context) | | ++---------------------------------------------------------+--------------------------------------------------+ + +When there is no special RTL-aware property available, or when +left/right properties must be used specifically for RTL, use the pseudo +``:-moz-locale-dir(rtl)`` (for XUL documents) or ``:dir(rtl)`` (for HTML +documents). + +For example, this rule covers LTR to display searchicon.svg 7 pixels +from the left: + +.. code:: css + + .search-box { + background-image: url(chrome://path/to/searchicon.svg); + background-position: 7px center; + } + +but an additional rule is necessary to cover RTL and place the search +icon on the right: + +.. code:: css + + .search-box:dir(rtl) { + background-position-x: right 7px; + } + +.. warning:: + + It may be inappropriate to use logical properties when embedding LTR + within RTL contexts. This is described further in the document. + +Mirroring elements +~~~~~~~~~~~~~~~~~~ + +RTL content also affects the direction in which some icons and images +are displayed, particularly those depicting a sequence of events. + +What to mirror +^^^^^^^^^^^^^^ + +- Icons or animations that imply directionality or motion like + back/forward buttons or progress bars +- Icons that imply text direction, like + `reader-mode.svg `__ +- Icons that imply location of UI elements in the screen, like + `sidebars-right.svg `__, + `open-in-new.svg `__, + `default theme's preview.svg `__ + or + `pane-collapse.svg `__ +- Icons representing objects that are meant to be handheld should look + like they're being right-handed, like the `magnifying glass + icon `__ +- Twisties in their collapsed state. Note that if the context in which + they appear is LTR (e.g. code in a devtools HTML view), they should + not be mirrored, even if the user might be using an RTL locale. + +What NOT to mirror +^^^^^^^^^^^^^^^^^^ + +- Text/numbers +- Icons containing text/numbers +- Icons/animations that are direction neutral +- Icons that wouldn't look differently if they'd be mirrored, like `X + buttons `__ + or the `bookmark + star `__ + icon, or any other symmetric icon +- Icons that should look the same as LTR, like icons related to code + (which is always LTR) like + `tool-webconsole.svg `__ +- Checkmark icons +- Video/audio player controls +- Product logos +- Order of size dimensions (e.g., ``1920x1080`` should not become + ``1080x1920``) +- Order of size units (e.g., ``10 px`` should not become ``px 10`` + (unless the size unit is localizable)) + +How +^^^ + +The most common way to mirror images is by flipping the X axis: + +.. code:: css + + transform: scaleX(-1); + +Or, if you're already using ``transform`` with a different value on the same +element, you can also use `scale`: + +.. code:: css + + scale: -1 1; + +Note that mirroring images that way doesn't work when the image is a part of +an element with text using ``background-image``, because then the text would +be mirrored along with the image, and the image would be positioned incorrectly. +For such cases, try to use a different method for displaying the image, +like having it as an element all on its own. +If that's not possible, add a separate pre-mirrored image asset and specify +it in a separate ``:dir(rtl)`` rule: + +.. code:: css + + .element-with-icon { + background-image: url("path/to/image/image.svg"); + } + + .element-with-icon:dir(rtl) { + background-image: url("path/to/image/image-rtl.svg"); + } + +For animations like a progress bar, when using ``@keyframes`` to change +the ``transform: translateX()`` states, make sure to add a different +``@keyframes`` suited for RTL, and target that in a separate ``:dir()`` rule: + +.. code:: css + + #progressbar { + animation: progressbar-animation 1s linear infinite; + } + + #progressbar:dir(rtl) { + animation-name: progressbar-animation-rtl; + } + + @keyframes progressbar-animation { + 0% { + transform: translateX(-100px); + } + 100% { + transform: translateX(0); + } + } + + @keyframes progressbar-animation-rtl { + 0% { + transform: translateX(100px); + } + 100% { + transform: translateX(0); + } + } + +Likewise, if you're using ``transform-origin``, make sure to specify the +correct origin for RTL: + +.. code:: css + + #progressbar { + transform-origin: 0 0; + } + + #progressbar:dir(rtl) { + transform-origin: 100% 0; + } + +LTR text inside RTL contexts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, in RTL locales, some symbols like ``/`` and ``.`` will be moved +around and won't be displayed in the order that they were typed in. This +may be problematic for URLs for instance, where you don't want dots to +change position. + +Here's a non-exhaustive list of elements that should be displayed like +they would be in LTR locales: + +- Paths (e.g., C:\\Users\\username\\Desktop) +- Full URLs +- Code and code containers (like the DevTools' Inspector or the CSS + rules panel) +- about:config preference names and values +- Telephone numbers +- Usernames & passwords (most sites on the web expect LTR + usernames/passwords, but there may be exceptions) +- Other text fields where only LTR text is expected + +To make sure these are displayed correctly, you can use one of the +following on the relevant element: + +- ``direction: ltr`` +- ``dir="ltr"`` in HTML + +Since the direction of such elements is forced to LTR, the text will +also be aligned to the left, which is undesirable from an UI +perspective, given that is inconsistent with the rest of the RTL UI +which has text usually aligned to the right. You can fix this using +``text-align: match-parent``. In the following screenshot, both text +fields (username and password) and the URL have their direction set to +LTR (to display text correctly), but the text itself is aligned to the +right for consistency with the rest of the UI: + +.. image:: about-logins-rtl.png + :alt: about:logins textboxes in RTL layout + +However, since the direction in LTR, this also means that the start/end +properties will correspond to left/right respectively, which is probably +not what you expect. This means you have to use extra rules instead of +using logical properties. + +Here's a full code example: + +.. code:: css + + .url { + direction: ltr; /* Force text direction to be LTR */ + + /* `start` (the default value) will correspond to `left`, + * so we match the parent's direction in order to align the text to the right */ + text-align: match-parent; + } + + /* :dir(ltr/rtl) isn't meaningful on .url, since it has direction: ltr, hence + * why it is matched on .container. */ + .container:dir(ltr) .url { + padding-left: 1em; + } + + .container:dir(rtl) .url { + padding-right: 1em; + } + +.. note:: + + The LTR rule is separate from the global rule to avoid having the + left padding apply on RTL without having to reset it in the RTL rule. + +Auto-directionality +^^^^^^^^^^^^^^^^^^^ + +Sometimes, the text direction on an element should vary dynamically +depending on the situation. This can be the case for a search input for +instance, a user may input a query in an LTR language, but may also +input a query in a RTL language. In this case, the search input has to +dynamically pick the correct directionality based on the first word, in +order to display the query text correctly. The typical way to do this is +to use ``dir="auto"`` in HTML. It is essential that +``text-align: match-parent`` is set, to avoid having the text alignment +change based on the query, and logical properties also cannot be used on +the element itself given they can change meaning depending on the query. + +Testing +~~~~~~~ + +To test for RTL layouts in Firefox, you can go to about:config and +set ``intl.l10n.pseudo`` to ``bidi``, or select the ``Enable "bidi" locale`` +option in the 3-dots menu in the :doc:`Browser Toolbox `. +The Firefox UI should immediately flip, but a restart may be required +to take effect in some Firefox features and interactions. + +.. note:: + + When testing with ``intl.l10n.pseudo`` set to ``bidi``, you may see some + oddities regarding text ordering due to the nature of displaying LTR + text in RTL layout. + + .. image:: about-protections-rtl.png + :alt: about:protections in RTL layout- English vs. Hebrew + + This shouldn't be an issue when using an actual RTL build or language pack. + +How to spot RTL-related issues +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Punctuation marks should appear on the left side of a + word/sentence/paragraph on RTL, so if a *localizable* string appears + in the UI with a dot, colon, ellipsis, question or exclamation mark + on the right side of the text, this probably means that the text + field is forced to be displayed as LTR. +- If icons/images/checkmarks do not appear on the opposite side of + text, when compared to LTR. +- If buttons (like the close button, "OK" and "Cancel" etc.) do not + appear on the opposite side of the UI and not in the opposite order, + when compared to LTR. +- If paddings/margins/borders are not the same from the opposite side, + when compared to LTR. +- Although Hebrew uses ``1 2 3``, all the other RTL locales we support + should use ``١ ٢ ٣`` as digits. So if you see ``1 2 3`` on any such + locale, that likely indicates a bug. +- If navigating in the UI using the left/right arrow keys does not + select the correct element (i.e., pressing Left selects an item on + the right). +- If navigating in the UI using the Tab key does not focus elements + from right to left, in an RTL context. +- If code is displayed as RTL (e.g., ``;padding: 20px`` - the semicolon + should appear on the right side of the code). Code can still be + aligned to the right if it appears in an RTL context. + +See also +~~~~~~~~ + +- `RTL Best + Practices `__ +- Building RTL-Aware Web Apps & Websites: `Part + 1 `__, + `Part + 2 `__ + +Credits +~~~~~~~ + +Google's `Material Design guide for +RTL `__ diff --git a/docs/code-quality/coding-style/svg_guidelines.rst b/docs/code-quality/coding-style/svg_guidelines.rst new file mode 100644 index 0000000000..f34317c91a --- /dev/null +++ b/docs/code-quality/coding-style/svg_guidelines.rst @@ -0,0 +1,347 @@ +SVG Guidelines +============== + +Pros and cons of SVG for images +------------------------------- + +When used as a document format there is usually a compelling reason that +makes SVG the only solution. When used as an `image +format `__, +it is sometimes less obvious whether it would be best to use SVG or a +raster image format for any given image. The vector format SVG and +raster formats like PNG both have their place. When choosing whether or +not to use SVG it is best to understand the advantages and disadvantages +of both. + +File size + Whether SVG or a raster format will produce a smaller file for a + given image depends very much on the image. For example, consider an + image of a path with a gradient fill. The size of an SVG of this + image will be the same regardless of the dimensions of the image. On + the other hand the size of a raster file of the same image will + likely vary tremendously depending on the dimensions of the image + since the larger the dimensions the more pixel data the file needs to + store. At very small dimensions (the extreme case being 1px x 1px) + the raster file will likely be much smaller than the SVG file since + it only needs to store one pixel of data. At large dimensions the + raster file may be much larger than the SVG file. +Scalability, with caveats + One of the primary advantages of SVG is that as it is scaled it does + not pixelate. However, this is not to say that it always does away + with the need to have a collection of raster images for display at + different scales. This can be particularly true for icons. While SVG + may scale well enough for flat-ish icons without a lot of detail, for + icons that try to pack in a lot of detail graphic artists generally + `want to be able to pixel + tweak `__. +Performance + While SVG provides a lot of flexibility in terms of scaling, + themability, etc. this flexibility depends on doing computations for + SVG images at the time they're displayed, rather than at the time the + author creates them. Consider an image that involves some complex + gradients and filters. If saved as a raster image then the work to + rasterize the gradients and filters takes place on the authors + computer before the result is stored in the raster file. This work + doesn't need to be redone when the image is displayed on someone + else's computer. On the other hand, if the image is saved as an SVG + image then all this work needs to be done each time the SVG is + displayed on someone else's computer. This isn't to say that SVG + images are always slower than raster equivalents. In fact it can be + faster to send vector information from an SVG to a user's GPU than it + is to extract raster data from an equivalent raster image. And even + when an SVG image is slower than a raster equivalent, the difference + is usually not noticeable. However, just don't fall into the trap of + thinking that SVGs are faster than equivalent raster images, or vice + versa. Once again, "it depends". + +Authoring guidelines +-------------------- + +A lot of SVG files (particularly those generated by SVG editors) ship +without being cleaned up and can contain a ton of junk that bloats the +file size and slows down rendering. In general the best way to combat +this is to first run SVG files through a linter such as +`svgo `__ (see the Tools section below). +However, when authoring SVGs by hand here are some best practices to +help keep them lightweight. These rules are based on some real examples +seen in Mozilla's code. + +Basics +~~~~~~ + +- Two spaces indenting +- No useless whitespaces or line breaks (see below for more details) +- Adding a license header +- Use double quotes + +Whitespace and line breaks +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whitespace +^^^^^^^^^^ + +In addition to trailing whitespace at the end of lines, there are a few +more cases more specific to SVGs: + +- Trailing whitespaces in attribute values (usually seen in path + definitions) +- Excessive whitespace in path or polygon points definition + +Whitespace examples +^^^^^^^^^^^^^^^^^^^ + +This path: + +.. code:: html + + + +can be cut down to this: + +.. code:: html + + + +Similarly, this polygon: + +.. code:: html + + + +can be cut down to this: + +.. code:: html + + + +Line breaks +^^^^^^^^^^^ + +You should only use line breaks for logical separation or if they help +make the file readable. You should avoid line breaks between every +single element or within attribute values. It's recommended to put the +attributes on the same line as their tag names, if possible. You should +also put the shortest attributes first, so they are easier to spot. + +Unused tags and attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Editor metadata +^^^^^^^^^^^^^^^ + +Vector editors (Inkscape, Adobe Illustrator, Sketch) usually add a bunch +of metadata in SVG files while saving them. Metadata can mean many +things, including: + +- The typical "Created with *editor*" comments +- Non-standard editor specific tags and attributes (``sketch:foo``, + ``illustrator:foo``, ``sopodi:foo``, …) +- The `XML + namespace `__ + definition that comes with the latter (``xmlns:sketch``, + ``xmlns:sopodi``, …) + +Other metadata +^^^^^^^^^^^^^^ + +In addition to non-standard editor metadata, standard compliant metadata +also exists. Typical examples of this are ```` and ``<desc>`` +tags. Although this kind of data is supported by the browser, it can +only be displayed when the SVG is opened in a new tab. Plus, in most of +the cases, the filename is quite descriptive So it's recommended to +remove that kind of metadata since it doesn't bring much value. + +You shouldn't include DOCTYPEs in your SVGs either; they are a source of +many issues, and the SVG WG recommends not to include them. See `SVG +Authoring +guidelines <https://jwatt.org/svg/authoring/#doctype-declaration>`__. + +Avoid the use of CDATA sections +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +`CDATA +sections <https://developer.mozilla.org/en-US/docs/Web/API/CDATASection>`__ +are used to avoid parsing some text as HTML. Most of time, CDATA isn't +needed, for example, the content in ``<style>`` tags doesn't need to be +wrapped in a CDATA section as the content inside the tag is already +correctly parsed as CSS. + +Invisible shapes +^^^^^^^^^^^^^^^^ + +There are two kinds of invisible shapes: The off-screen ones and the +uncolored ones. + +The offscreen shapes are hard to spot, even with an automated tool, and +are usually context aware. Those kinds of shapes are visible but off the +`SVG view +box <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox>`__. +Here's `an +example <https://hg.mozilla.org/mozilla-central/diff/9fb143f3b36a/browser/themes/shared/heartbeat-star-lit.svg>`__ +of a file with offscreen shapes. + +On the other hand, the uncolored ones are easier to spot, since they +usually come with styles making them invisible. They must meet two +conditions: they must be devoid of any fill (or a transparent one) or +stroke. + +Unused attributes on root ``<svg>`` element +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The root ``<svg>`` element can also host many useless attributes. Here's +an +`example <https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/components/loop/content/shared/img/icons-10x10.svg>`__ +taking into account the list below: + +- ``version`` +- ``x="0"`` and ``y="0"`` +- ``enable-background`` (unsupported by Gecko and now deprecated by the + Filter Effects specification) +- ``id`` (id on root element has no effect) +- ``xmlns:xlink`` attribute when there are no ``xlink:href`` attributes + used throughout the file +- Other unused `XML + Namespace <https://developer.mozilla.org/en-US/docs/Web/SVG/Namespaces_Crash_Course>`__ + definitions +- ``xml:space`` when there is no text used in the file + +Other +^^^^^ + +- Empty tags, this may be obvious, but those are sometimes found in + SVGs +- Unreferenced ids (usually on gradient stops, but also on shapes or + paths) +- ``clip-rule`` attribute when the element *is not* a descendant of a + ``<clipPath>`` +- ``fill-rule`` attribute when the element *is* a descendant of a + ``<clipPath>`` +- Unreferenced/Unused clip paths, masks or defs + (`example <https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/toolkit/themes/shared/reader/RM-Plus-24x24.svg>`__) + +Styling +~~~~~~~ + +Styling basics +^^^^^^^^^^^^^^ + +- Privilege short lowercase hex for colors +- Don't use excessive precision for numeric values (usually comes from + illustrator) +- Use descriptive IDs +- Avoid inline styles and use class names or SVG attributes + +Styling examples +'''''''''''''''' + +Here are some examples for excessive number precision: + +- 5.000000e-02 → 0.05 (as seen + `here <https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/devtools/images/tool-network.svg#l1.31>`__) +- -3.728928e-10 → 0 (as seen + `here <https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/aboutNetError_alert.svg#l1.12>`__) +- translate(0.000000, -1.000000) → translate(0, -1) (as seen + `here <https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/heartbeat-icon.svg#l1.13>`__) + +As for descriptive IDs: + +- For gradients: SVG_ID1 → gradient1 (as seen + `here <https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/aboutNetError_alert.svg#l1.12>`__) + +Use of class names +^^^^^^^^^^^^^^^^^^ + +- Avoid using a class if that class is only used once in the file +- If that class only sets a fill or a stroke, it's better to set the + fill/stroke directly on the actual shape, instead of introducing a + class just for that shape. You can also use SVG grouping to avoid + duplicating those attributes +- Avoid introducing variants of the same file (color/style variants), + and use sprites instead (with class names) + +Default style values +^^^^^^^^^^^^^^^^^^^^ + +There's usually no need to set the default style value unless you're +overriding a style. Here are some commonly seen examples: + +- ``style="display: none;"`` on ``<defs>`` elements (a ``<defs>`` + element is hidden by default) +- ``type="text/css"`` on ``<style>`` elements +- ``stroke: none`` or ``stroke-width: 0`` + +SVG grouping +~~~~~~~~~~~~ + +Style grouping +^^^^^^^^^^^^^^ + +Group similarly styled shapes under one ``<g>`` tag; this avoids having +to set the same class/styles on many shapes. + +Avoid excessive grouping +^^^^^^^^^^^^^^^^^^^^^^^^ + +Editors can sometimes do excessive grouping while exporting SVGs. This +is due to the way editors work. + +Nested groups +''''''''''''' + +Avoid multiple-level nesting of groups, these make the SVG less +readable. + +Nested transforms +''''''''''''''''' + +Some editors use ``<g>`` tags to do nested transforms, which is usually +not needed. You can avoid this by doing basic algebra, for example: + +.. code:: xml + + <g transform="translate(-62, -310)"><shape transform="translate(60, 308)"/></g> + +can be cut down to: + +.. code:: xml + + <shape transform="translate(-2,-2)"/> + +because: -62+60 = -310+308 = -2 + +Performance tips +~~~~~~~~~~~~~~~~ + +These rules are optional, but they help speeding up the SVG. + +- Avoid using a ``<use>`` tag when that ``<use>`` tag is being + referenced only once in the whole file. +- Instead of using CSS/SVG + `transforms <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform>`__, + apply directly the transform on the path/shape definition. + +Tools +~~~~~ + +Tools can help to clean SVG files. Note, however that some of the rules +stated above can be hard to detect with automated tools since they +require too much context-awareness. To this date, there doesn't seem to +be a tool that handles all of the above. However, there are some +utilities that cover parts of this document: + +- Mostly complete command line tool: https://github.com/svg/svgo +- Alternatives to SVGO: + + - https://github.com/RazrFalcon/svgcleaner + - https://github.com/scour-project/scour + +- GUI for command line tool (use with "Prettify code" and "Remove + ``<title>``" options on): https://jakearchibald.github.io/svgomg/ +- Good alternative to SVGO/SVGOMG: + https://petercollingridge.appspot.com/svg-editor +- Fixes the excessive number precision: + https://simon.html5.org/tools/js/svg-optimizer/ +- Converts inline styles to SVG + attributes: https://www.w3.org/wiki/SvgTidy +- RaphaelJS has a couple of utilities that may be useful: + `raphael.js <https://dmitrybaranovskiy.github.io/raphael/>`__ diff --git a/docs/code-quality/coding-style/using_cxx_in_firefox_code.rst b/docs/code-quality/coding-style/using_cxx_in_firefox_code.rst new file mode 100644 index 0000000000..92decbdf1e --- /dev/null +++ b/docs/code-quality/coding-style/using_cxx_in_firefox_code.rst @@ -0,0 +1,1075 @@ +Using C++ in Mozilla code +========================= + +C++ language features +--------------------- + +Mozilla code only uses a subset of C++. Runtime type information (RTTI) +is disabled, as it tends to cause a very large increase in codesize. +This means that ``dynamic_cast``, ``typeid()`` and ``<typeinfo>`` cannot +be used in Mozilla code. Also disabled are exceptions; do not use +``try``/``catch`` or throw any exceptions. Libraries that throw +exceptions may be used if you are willing to have the throw instead be +treated as an abort. + +On the side of extending C++, we compile with ``-fno-strict-aliasing``. +This means that when reinterpreting a pointer as a differently-typed +pointer, you don't need to adhere to the "effective type" (of the +pointee) rule from the standard (aka. "the strict aliasing rule") when +dereferencing the reinterpreted pointer. You still need make sure that +you don't violate alignment requirements and need to make sure that the +data at the memory location pointed to forms a valid value when +interpreted according to the type of the pointer when dereferencing the +pointer for reading. Likewise, if you write by dereferencing the +reinterpreted pointer and the originally-typed pointer might still be +dereferenced for reading, you need to make sure that the values you +write are valid according to the original type. This value validity +issue is moot for e.g. primitive integers for which all bit patterns of +their size are valid values. + +- As of Mozilla 59, C++14 mode is required to build Mozilla. +- As of Mozilla 67, MSVC can no longer be used to build Mozilla. +- As of Mozilla 73, C++17 mode is required to build Mozilla. + +This means that C++17 can be used where supported on all platforms. The +list of acceptable features is given below: + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 3 + + * - + - GCC + - Clang + - + * - Current minimal requirement + - 8.1 + - 7.0 + - + * - Feature + - GCC + - Clang + - Can be used in code + * - ``type_t &&`` + - 4.3 + - 2.9 + - Yes (see notes) + * - ref qualifiers on methods + - 4.8.1 + - 2.9 + - Yes + * - default member-initializers (except for bit-fields) + - 4.7 + - 3.0 + - Yes + * - default member-initializers (for bit-fields) + - 8 + - 6 + - **No** + * - variadic templates + - 4.3 + - 2.9 + - Yes + * - Initializer lists + - 4.4 + - 3.1 + - Yes + * - ``static_assert`` + - 4.3 + - 2.9 + - Yes + * - ``auto`` + - 4.4 + - 2.9 + - Yes + * - lambdas + - 4.5 + - 3.1 + - Yes + * - ``decltype`` + - 4.3 + - 2.9 + - Yes + * - ``Foo<Bar<T>>`` + - 4.3 + - 2.9 + - Yes + * - ``auto func() -> int`` + - 4.4 + - 3.1 + - Yes + * - Templated aliasing + - 4.7 + - 3.0 + - Yes + * - ``nullptr`` + - 4.6 + - 3.0 + - Yes + * - ``enum foo : int16_t`` {}; + - 4.4 + - 2.9 + - Yes + * - ``enum class foo {}``; + - 4.4 + - 2.9 + - Yes + * - ``enum foo;`` + - 4.6 + - 3.1 + - Yes + * - ``[[attributes]]`` + - 4.8 + - 3.3 + - **No** (see notes) + * - ``constexpr`` + - 4.6 + - 3.1 + - Yes + * - ``alignas`` + - 4.8 + - 3.3 + - Yes + * - ``alignof`` + - 4.8 + - 3.3 + - Yes, but see notes ; only clang 3.6 claims as_feature(cxx_alignof) + * - Delegated constructors + - 4.7 + - 3.0 + - Yes + * - Inherited constructors + - 4.8 + - 3.3 + - Yes + * - ``explicit operator bool()`` + - 4.5 + - 3.0 + - Yes + * - ``char16_t/u"string"`` + - 4.4 + - 3.0 + - Yes + * - ``R"(string)"`` + - 4.5 + - 3.0 + - Yes + * - ``operator""()`` + - 4.7 + - 3.1 + - Yes + * - ``=delete`` + - 4.4 + - 2.9 + - Yes + * - ``=default`` + - 4.4 + - 3.0 + - Yes + * - unrestricted unions + - 4.6 + - 3.1 + - Yes + * - ``for (auto x : vec)`` (`be careful about the type of the iterator <https://stackoverflow.com/questions/15176104/c11-range-based-loop-get-item-by-value-or-reference-to-const>`__) + - 4.6 + - 3.0 + - Yes + * - ``override``/``final`` + - 4.7 + - 3.0 + - Yes + * - ``thread_local`` + - 4.8 + - 3.3 + - **No** (see notes) + * - function template default arguments + - 4.3 + - 2.9 + - Yes + * - local structs as template parameters + - 4.5 + - 2.9 + - Yes + * - extended friend declarations + - 4.7 + - 2.9 + - Yes + * - ``0b100`` (C++14) + - 4.9 + - 2.9 + - Yes + * - `Tweaks to some C++ contextual conversions` (C++14) + - 4.9 + - 3.4 + - Yes + * - Return type deduction (C++14) + - 4.9 + - 3.4 + - Yes (but only in template code when you would have used ``decltype (complex-expression)``) + * - Generic lambdas (C++14) + - 4.9 + - 3.4 + - Yes + * - Initialized lambda captures (C++14) + - 4.9 + - 3.4 + - Yes + * - Digit separator (C++14) + - 4.9 + - 3.4 + - Yes + * - Variable templates (C++14) + - 5.0 + - 3.4 + - Yes + * - Relaxed constexpr (C++14) + - 5.0 + - 3.4 + - Yes + * - Aggregate member initialization (C++14) + - 5.0 + - 3.3 + - Yes + * - Clarifying memory allocation (C++14) + - 5.0 + - 3.4 + - Yes + * - [[deprecated]] attribute (C++14) + - 4.9 + - 3.4 + - **No** (see notes) + * - Sized deallocation (C++14) + - 5.0 + - 3.4 + - **No** (see notes) + * - Concepts (Concepts TS) + - 6.0 + - — + - **No** + * - Inline variables (C++17) + - 7.0 + - 3.9 + - Yes + * - constexpr_if (C++17) + - 7.0 + - 3.9 + - Yes + * - constexpr lambdas (C++17) + - — + - — + - **No** + * - Structured bindings (C++17) + - 7.0 + - 4.0 + - Yes + * - Separated declaration and condition in ``if``, ``switch`` (C++17) + - 7.0 + - 3.9 + - Yes + * - `Fold expressions <https://en.cppreference.com/w/cpp/language/fold>`__ (C++17) + - 6.0 + - 3.9 + - Yes + * - [[fallthrough]], [[maybe_unused]], [[nodiscard]] (C++17) + - 7.0 + - 3.9 + - Yes + * - Aligned allocation/deallocation (C++17) + - 7.0 + - 4.0 + - **No** (see notes) + * - Designated initializers (C++20) + - 8.0 (4.7) + - 10.0 (3.0) + - Yes [*sic*] (see notes) + * - #pragma once + - 3.4 + - Yes + - **Not** until we `normalize headers <https://groups.google.com/d/msg/mozilla.dev.platform/PgDjWw3xp8k/eqCFlP4Kz1MJ>`__ + * - `Source code information capture <https://en.cppreference.com/w/cpp/experimental/lib_extensions_2#Source_code_information_capture>`__ + - 8.0 + - — + - **No** + +Sources +~~~~~~~ + +* GCC: https://gcc.gnu.org/projects/cxx-status.html +* Clang: https://clang.llvm.org/cxx_status.html + +Notes +~~~~~ + +rvalue references + Implicit move method generation cannot be used. + +Attributes + Several common attributes are defined in + `mozilla/Attributes.h <https://searchfox.org/mozilla-central/source/mfbt/Attributes.h>`__ + or nscore.h. + +Alignment + Some alignment utilities are defined in `mozilla/Alignment.h + <https://searchfox.org/mozilla-central/source/mfbt/Alignment.h>`__. + + .. caution:: + ``MOZ_ALIGNOF`` and ``alignof`` don't have the same semantics. Be careful of what you + expect from them. + +``[[deprecated]]`` + If we have deprecated code, we should be removing it rather than marking it as + such. Marking things as ``[[deprecated]]`` also means the compiler will warn + if you use the deprecated API, which turns into a fatal error in our + automation builds, which is not helpful. + +Sized deallocation + Our compilers all support this (custom flags are required for GCC and Clang), + but turning it on breaks some classes' ``operator new`` methods, and `some + work <https://bugzilla.mozilla.org/show_bug.cgi?id=1250998>`__ would need to + be done to make it an efficiency win with our custom memory allocator. + +Aligned allocation/deallocation + Our custom memory allocator doesn't have support for these functions. + +Thread locals + ``thread_local`` is not supported on Android. + +Designated initializers + Despite their late addition to C++ (and lack of *official* support by + compilers until relatively recently), `C++20's designated initializers + <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf>`__ are + merely a subset of `a feature originally introduced in C99 + <https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html>`__ -- and this + subset has been accepted without comment in C++ code since at least GCC 4.7 + and Clang 3.0. + + +C++ and Mozilla standard libraries +---------------------------------- + +The Mozilla codebase contains within it several subprojects which follow +different rules for which libraries can and can't be used it. The rules +listed here apply to normal platform code, and assume unrestricted +usability of MFBT or XPCOM APIs. + +.. warning:: + + The rest of this section is a draft for expository and exploratory + purposes. Do not trust the information listed here. + +What follows is a list of standard library components provided by +Mozilla or the C++ standard. If an API is not listed here, then it is +not permissible to use it in Mozilla code. Deprecated APIs are not +listed here. In general, prefer Mozilla variants of data structures to +standard C++ ones, even when permitted to use the latter, since Mozilla +variants tend to have features not found in the standard library (e.g., +memory size tracking) or have more controllable performance +characteristics. + +A list of approved standard library headers is maintained in +`config/stl-headers.mozbuild <https://searchfox.org/mozilla-central/source/config/stl-headers.mozbuild>`__. + + +Data structures +~~~~~~~~~~~~~~~ + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 1 + + * - Name + - Header + - STL equivalent + - Notes + * - ``nsAutoTArray`` + - ``nsTArray.h`` + - + - Like ``nsTArray``, but will store a small amount as stack storage + * - ``nsAutoTObserverArray`` + - ``nsTObserverArray.h`` + - + - Like ``nsTObserverArray``, but will store a small amount as stack storage + * - ``mozilla::BloomFilter`` + - ``mozilla/BloomFilter.h`` + - + - Probabilistic set membership (see `Wikipedia <https://en.wikipedia.org/wiki/Bloom_filter#Counting_filters>`__) + * - ``nsClassHashtable`` + - ``nsClassHashtable.h`` + - + - Adaptation of nsTHashtable, see :ref:`XPCOM Hashtable Guide` + * - ``nsCOMArray`` + - ``nsCOMArray.h`` + - + - Like ``nsTArray<nsCOMPtr<T>>`` + * - ``nsDataHashtable`` + - ``nsClassHashtable.h`` + - ``std::unordered_map`` + - Adaptation of ``nsTHashtable``, see :ref:`XPCOM Hashtable Guide` + * - ``nsDeque`` + - ``nsDeque.h`` + - ``std::deque<void *>`` + - + * - ``mozilla::EnumSet`` + - ``mozilla/EnumSet.h`` + - + - Like ``std::set``, but for enum classes. + * - ``mozilla::Hash{Map,Set}`` + - `mozilla/HashTable.h <https://searchfox.org/mozilla-central/source/mfbt/HashTable.h>`__ + - ``std::unordered_{map,set}`` + - A general purpose hash map and hash set. + * - ``nsInterfaceHashtable`` + - ``nsInterfaceHashtable.h`` + - ``std::unordered_map`` + - Adaptation of ``nsTHashtable``, see :ref:`XPCOM Hashtable Guide` + * - ``mozilla::LinkedList`` + - ``mozilla/LinkedList.h`` + - ``std::list`` + - Doubly-linked list + * - ``nsRef PtrHashtable`` + - ``nsRefPtrHashtable.h`` + - ``std::unordered_map`` + - Adaptation of ``nsTHashtable``, see :ref:`XPCOM Hashtable Guide` + * - ``mozilla::SegmentedVector`` + - ``mozilla/SegmentedVector.h`` + - ``std::deque`` w/o O(1) pop_front + - Doubly-linked list of vector elements + * - ``mozilla::SplayTree`` + - ``mozilla/SplayTree.h`` + - + - Quick access to recently-accessed elements (see `Wikipedia <https://en.wikipedia.org/wiki/Splay_tree>`__) + * - ``nsTArray`` + - ``nsTArray.h`` + - ``std::vector`` + - + * - ``nsTHashtable`` + - ``nsTHashtable.h`` + - ``std::unordered_{map,set}`` + - See :ref:`XPCOM Hashtable Guide`, you probably want a subclass + * - ``nsTObserverArray`` + - ``nsTObserverArray.h`` + - + - Like ``nsTArray``, but iteration is stable even through mutation + * - ``nsTPriorityQueue`` + - ``nsTPriorityQueue.h`` + - ``std::priority_queue`` + - Unlike the STL class, not a container adapter + * - ``mozilla::Vector`` + - ``mozilla/Vector.h`` + - ``std::vector`` + - + * - ``mozilla::Buffer`` + - ``mozilla/Buffer.h`` + - + - Unlike ``Array``, has a run-time variable length. Unlike ``Vector``, does not have capacity and growth mechanism. Unlike ``Span``, owns its buffer. + + +Safety utilities +~~~~~~~~~~~~~~~~ + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 1 + + * - Name + - Header + - STL equivalent + - Notes + * - ``mozilla::Array`` + - ``mfbt/Array.h`` + - + - safe array index + * - ``mozilla::AssertedCast`` + - ``mfbt/Casting.h`` + - + - casts + * - ``mozilla::CheckedInt`` + - ``mfbt/CheckedInt.h`` + - + - avoids overflow + * - ``nsCOMPtr`` + - ``xpcom/base/nsCOMPtr.h`` + - ``std::shared_ptr`` + - + * - ``mozilla::EnumeratedArray`` + - ``mfbt/EnumeratedArray.h`` + - ``mozilla::Array`` + - + * - ``mozilla::Maybe`` + - ``mfbt/Maybe.h`` + - ``std::optional`` + - + * - ``mozilla::RangedPtr`` + - ``mfbt/RangedPtr.h`` + - + - like ``mozilla::Span`` but with two pointers instead of pointer and length + * - ``mozilla::RefPtr`` + - ``mfbt/RefPtr.h`` + - ``std::shared_ptr`` + - + * - ``mozilla::Span`` + - ``mozilla/Span.h`` + - ``gsl::span``, ``absl::Span``, ``std::string_view``, ``std::u16string_view`` + - Rust's slice concept for C++ (without borrow checking) + * - ``StaticRefPtr`` + - ``xpcom/base/StaticPtr.h`` + - + - ``nsRefPtr`` w/o static constructor + * - ``mozilla::UniquePtr`` + - ``mfbt/UniquePtr.h`` + - ``std::unique_ptr`` + - + * - ``mozilla::WeakPtr`` + - ``mfbt/WeakPtr.h`` + - ``std::weak_ptr`` + - + * - ``nsWeakPtr`` + - ``xpcom/base/nsWeakPtr.h`` + - ``std::weak_ptr`` + - + + +Strings +~~~~~~~ + +See the :doc:`Mozilla internal string guide </xpcom/stringguide>` for +usage of ``nsAString`` (our copy-on-write replacement for +``std::u16string``) and ``nsACString`` (our copy-on-write replacement +for ``std::string``). + +Be sure not to introduce further uses of ``std::wstring``, which is not +portable! (Some uses exist in the IPC code.) + + +Algorithms +~~~~~~~~~~ + +.. list-table:: + :widths: 25 25 + + * - ``mozilla::BinarySearch`` + - ``mfbt/BinarySearch.h`` + * - ``mozilla::BitwiseCast`` + - ``mfbt/Casting.h`` (strict aliasing-safe cast) + * - ``mozilla/MathAlgorithms.h`` + - (rotate, ctlz, popcount, gcd, abs, lcm) + * - ``mozilla::RollingMean`` + - ``mfbt/RollingMean.h`` () + + +Concurrency +~~~~~~~~~~~ + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 1 + + * - Name + - Header + - STL/boost equivalent + - Notes + * - ``mozilla::Atomic`` + - mfbt/Atomic.h + - ``std::atomic`` + - + * - ``mozilla::CondVar`` + - xpcom/threads/CondVar.h + - ``std::condition_variable`` + - + * - ``mozilla::DataMutex`` + - xpcom/threads/DataMutex.h + - ``boost::synchronized_value`` + - + * - ``mozilla::Monitor`` + - xpcom/threads/Monitor.h + - + - + * - ``mozilla::Mutex`` + - xpcom/threads/Mutex.h + - ``std::mutex`` + - + * - ``mozilla::ReentrantMonitor`` + - xpcom/threads/ReentrantMonitor.h + - + - + * - ``mozilla::StaticMutex`` + - xpcom/base/StaticMutex.h + - ``std::mutex`` + - Mutex that can (and in fact, must) be used as a global/static variable. + + +Miscellaneous +~~~~~~~~~~~~~ + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 1 + + * - Name + - Header + - STL/boost equivalent + - Notes + * - ``mozilla::AlignedStorage`` + - mfbt/Alignment.h + - ``std::aligned_storage`` + - + * - ``mozilla::MaybeOneOf`` + - mfbt/MaybeOneOf.h + - ``std::optional<std::variant<T1, T2>>`` + - ~ ``mozilla::Maybe<union {T1, T2}>`` + * - ``mozilla::Pair`` + - mfbt/Pair.h + - ``std::tuple<T1, T2>`` + - minimal space! + * - ``mozilla::TimeStamp`` + - xpcom/ds/TimeStamp.h + - ``std::chrono::time_point`` + - + * - + - mozilla/PodOperations.h + - + - C++ versions of ``memset``, ``memcpy``, etc. + * - + - mozilla/ArrayUtils.h + - + - + * - + - mozilla/Compression.h + - + - + * - + - mozilla/Endian.h + - + - + * - + - mozilla/FloatingPoint.h + - + - + * - + - mozilla/HashFunctions.h + - ``std::hash`` + - + * - + - mozilla/Move.h + - ``std::move``, ``std::swap``, ``std::forward`` + - + + +Mozilla data structures and standard C++ ranges and iterators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some Mozilla-defined data structures provide STL-style +`iterators <https://en.cppreference.com/w/cpp/named_req/Iterator>`__ and +are usable in `range-based for +loops <https://en.cppreference.com/w/cpp/language/range-for>`__ as well +as STL `algorithms <https://en.cppreference.com/w/cpp/algorithm>`__. + +Currently, these include: + +.. list-table:: + :widths: 16 16 16 16 16 + :header-rows: 1 + + * - Name + - Header + - Bug(s) + - Iterator category + - Notes + * - ``nsTArray`` + - ``xpcom/ds/n sTArray.h`` + - `1126552 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126552>`__ + - Random-access + - Also reverse-iterable. Also supports remove-erase pattern via RemoveElementsAt method. Also supports back-inserting output iterators via ``MakeBackInserter`` function. + * - ``nsBaseHashtable`` and subclasses: ``nsClassHashtable`` ``nsDataHashtable`` ``nsInterfaceHashtable`` ``nsJSThingHashtable`` ``nsRefPtrHashtable`` + - ``xpcom/ds/nsBaseHashtable.h`` ``xpcom/ds/nsClassHashtable.h`` ``xpcom/ds/nsDataHashtable.h`` ``xpcom/ds/nsInterfaceHashtable.h`` ``xpcom/ds/nsJSThingHashtable.h`` ``xpcom/ds/nsRefPtrHashtable.h`` + - `1575479 <https://bugzilla.mozilla.org/show_bug.cgi?id=1575479>`__ + - Forward + - + * - ``nsCOMArray`` + - ``xpcom/ds/nsCOMArray.h`` + - `1342303 <https://bugzilla.mozilla.org/show_bug.cgi?id=1342303>`__ + - Random-access + - Also reverse-iterable. + * - ``Array`` ``EnumerationArray`` ``RangedArray`` + - ``mfbt/Array.h`` ``mfbt/EnumerationArray.h`` ``mfbt/RangedArray.h`` + - `1216041 <https://bugzilla.mozilla.org/show_bug.cgi?id=1216041>`__ + - Random-access + - Also reverse-iterable. + * - ``Buffer`` + - ``mfbt/Buffer.h`` + - `1512155 <https://bugzilla.mozilla.org/show_bug.cgi?id=1512155>`__ + - Random-access + - Also reverse-iterable. + * - ``DoublyLinkedList`` + - ``mfbt/DoublyLinkedList.h`` + - `1277725 <https://bugzilla.mozilla.org/show_bug.cgi?id=1277725>`__ + - Forward + - + * - ``EnumeratedRange`` + - ``mfbt/EnumeratedRange.h`` + - `1142999 <https://bugzilla.mozilla.org/show_bug.cgi?id=1142999>`__ + - *Missing* + - Also reverse-iterable. + * - ``IntegerRange`` + - ``mfbt/IntegerRange.h`` + - `1126701 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126701>`__ + - *Missing* + - Also reverse-iterable. + * - ``SmallPointerArray`` + - ``mfbt/SmallPointerArray.h`` + - `1331718 <https://bugzilla.mozilla.org/show_bug.cgi?id=1331718>`__ + - Random-access + - + * - ``Span`` + - ``mfbt/Span.h`` + - `1295611 <https://bugzilla.mozilla.org/show_bug.cgi?id=1295611>`__ + - Random-access + - Also reverse-iterable. + +Note that if the iterator category is stated as "missing", the type is +probably only usable in range-based for. This is most likely just an +omission, which could be easily fixed. + +Useful in this context are also the class template ``IteratorRange`` +(which can be used to construct a range from any pair of iterators) and +function template ``Reversed`` (which can be used to reverse any range), +both defined in ``mfbt/ReverseIterator.h`` + + +Further C++ rules +----------------- + + +Don't use static constructors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(You probably shouldn't be using global variables to begin with. Quite +apart from the weighty software-engineering arguments against them, +globals affect startup time! But sometimes we have to do ugly things.) + +Non-portable example: + +.. code-block:: c++ + + FooBarClass static_object(87, 92); + + void + bar() + { + if (static_object.count > 15) { + ... + } + } + +Once upon a time, there were compiler bugs that could result in +constructors not being called for global objects. Those bugs are +probably long gone by now, but even with the feature working correctly, +there are so many problems with correctly ordering C++ constructors that +it's easier to just have an init function: + +.. code-block:: c++ + + static FooBarClass* static_object; + + FooBarClass* + getStaticObject() + { + if (!static_object) + static_object = + new FooBarClass(87, 92); + return static_object; + } + + void + bar() + { + if (getStaticObject()->count > 15) { + ... + } + } + + +Don't use exceptions +~~~~~~~~~~~~~~~~~~~~ + +See the introduction to the "C++ language features" section at the start +of this document. + + +Don't use Run-time Type Information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See the introduction to the "C++ language features" section at the start +of this document. + +If you need runtime typing, you can achieve a similar result by adding a +``classOf()`` virtual member function to the base class of your +hierarchy and overriding that member function in each subclass. If +``classOf()`` returns a unique value for each class in the hierarchy, +you'll be able to do type comparisons at runtime. + + +Don't use the C++ standard library (including iostream and locale) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See the section "C++ and Mozilla standard libraries". + + +Use C++ lambdas, but with care +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C++ lambdas are supported across all our compilers now. Rejoice! We +recommend explicitly listing out the variables that you capture in the +lambda, both for documentation purposes, and to double-check that you're +only capturing what you expect to capture. + + +Use namespaces +~~~~~~~~~~~~~~ + +Namespaces may be used according to the style guidelines in :ref:`C++ Coding style`. + + +Don't mix varargs and inlines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +What? Why are you using varargs to begin with?! Stop that at once! + + +Make header files compatible with C and C++ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Non-portable example: + +.. code-block:: c++ + + /*oldCheader.h*/ + int existingCfunction(char*); + int anotherExistingCfunction(char*); + + /* oldCfile.c */ + #include "oldCheader.h" + ... + + // new file.cpp + extern "C" { + #include "oldCheader.h" + }; + ... + +If you make new header files with exposed C interfaces, make the header +files work correctly when they are included by both C and C++ files. + +(If you need to include a C header in new C++ files, that should just +work. If not, it's the C header maintainer's fault, so fix the header if +you can, and if not, whatever hack you come up with will probably be +fine.) + +Portable example: + +.. code-block:: c++ + + /* oldCheader.h*/ + PR_BEGIN_EXTERN_C + int existingCfunction(char*); + int anotherExistingCfunction(char*); + PR_END_EXTERN_C + + /* oldCfile.c */ + #include "oldCheader.h" + ... + + // new file.cpp + #include "oldCheader.h" + ... + +There are number of reasons for doing this, other than just good style. +For one thing, you are making life easier for everyone else, doing the +work in one common place (the header file) instead of all the C++ files +that include it. Also, by making the C header safe for C++, you document +that "hey, this file is now being included in C++". That's a good thing. +You also avoid a big portability nightmare that is nasty to fix... + + +Use override on subclass virtual member functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``override`` keyword is supported in C++11 and in all our supported +compilers, and it catches bugs. + + +Always declare a copy constructor and assignment operator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many classes shouldn't be copied or assigned. If you're writing one of +these, the way to enforce your policy is to declare a deleted copy +constructor as private and not supply a definition. While you're at it, +do the same for the assignment operator used for assignment of objects +of the same class. Example: + +.. code-block:: c++ + + class Foo { + ... + private: + Foo(const Foo& x) = delete; + Foo& operator=(const Foo& x) = delete; + }; + +Any code that implicitly calls the copy constructor will hit a +compile-time error. That way nothing happens in the dark. When a user's +code won't compile, they'll see that they were passing by value, when +they meant to pass by reference (oops). + + +Be careful of overloaded methods with like signatures +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's best to avoid overloading methods when the type signature of the +methods differs only by one "abstract" type (e.g. ``PR_Int32`` or +``int32``). What you will find as you move that code to different +platforms, is suddenly on the Foo2000 compiler your overloaded methods +will have the same type-signature. + + +Type scalar constants to avoid unexpected ambiguities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Non-portable code: + +.. code-block:: c++ + + class FooClass { + // having such similar signatures + // is a bad idea in the first place. + void doit(long); + void doit(short); + }; + + void + B::foo(FooClass* xyz) + { + xyz->doit(45); + } + +Be sure to type your scalar constants, e.g., ``uint32_t(10)`` or +``10L``. Otherwise, you can produce ambiguous function calls which +potentially could resolve to multiple methods, particularly if you +haven't followed (2) above. Not all of the compilers will flag ambiguous +method calls. + +Portable code: + +.. code-block:: c++ + + class FooClass { + // having such similar signatures + // is a bad idea in the first place. + void doit(long); + void doit(short); + }; + + void + B::foo(FooClass* xyz) + { + xyz->doit(45L); + } + + +Use nsCOMPtr in XPCOM code +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See the ``nsCOMPtr`` `User +Manual <https://developer.mozilla.org/en-US/docs/Using_nsCOMPtr>`__ for +usage details. + + +Don't use identifiers that start with an underscore +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This rule occasionally surprises people who've been hacking C++ for +decades. But it comes directly from the C++ standard! + +According to the C++ Standard, 17.4.3.1.2 Global Names +[lib.global.names], paragraph 1: + +Certain sets of names and function signatures are always reserved to the +implementation: + +- Each name that contains a double underscore (__) or begins with an + underscore followed by an uppercase letter (2.11) is reserved to the + implementation for any use. +- **Each name that begins with an underscore is reserved to the + implementation** for use as a name in the global namespace. + + +Stuff that is good to do for C or C++ +------------------------------------- + + +Avoid conditional #includes when possible +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Don't write an ``#include`` inside an ``#ifdef`` if you could instead +put it outside. Unconditional includes are better because they make the +compilation more similar across all platforms and configurations, so +you're less likely to cause stupid compiler errors on someone else's +favorite platform that you never use. + +Bad code example: + +.. code-block:: c++ + + #ifdef MOZ_ENABLE_JPEG_FOUR_BILLION + #include <stdlib.h> // <--- don't do this + #include "jpeg4e9.h" // <--- only do this if the header really might not be there + #endif + +Of course when you're including different system files for different +machines, you don't have much choice. That's different. + + +Every .cpp source file should have a unique name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Every object file linked into libxul needs to have a unique name. Avoid +generic names like nsModule.cpp and instead use nsPlacesModule.cpp. + + +Turn on warnings for your compiler, and then write warning free code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +What generates a warning on one platform will generate errors on +another. Turn warnings on. Write warning-free code. It's good for you. +Treat warnings as errors by adding +``ac_add_options --enable-warnings-as-errors`` to your mozconfig file. + + +Use the same type for all bitfields in a ``struct`` or ``class`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some compilers do not pack the bits when different bitfields are given +different types. For example, the following struct might have a size of +8 bytes, even though it would fit in 1: + +.. code-block:: c++ + + struct { + char ch: 1; + int i: 1; + }; + + +Don't use an enum type for a bitfield +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The classic example of this is using ``PRBool`` for a boolean bitfield. +Don't do that. ``PRBool`` is a signed integer type, so the bitfield's +value when set will be ``-1`` instead of ``+1``, which---I know, +*crazy*, right? The things C++ hackers used to have to put up with... + +You shouldn't be using ``PRBool`` anyway. Use ``bool``. Bitfields of +type ``bool`` are fine. + +Enums are signed on some platforms (in some configurations) and unsigned +on others and therefore unsuitable for writing portable code when every +bit counts, even if they happen to work on your system. diff --git a/docs/code-quality/index.rst b/docs/code-quality/index.rst new file mode 100644 index 0000000000..e8336b7948 --- /dev/null +++ b/docs/code-quality/index.rst @@ -0,0 +1,185 @@ +Code quality +============ + +Because Firefox is a complex piece of software, a lot of tools are +executed to identify issues at development phase. +In this document, we try to list these all tools. + + +.. toctree:: + :maxdepth: 1 + :glob: + + static-analysis/index.rst + lint/index.rst + coding-style/index.rst + +.. list-table:: C/C++ + :header-rows: 1 + :widths: 20 20 20 20 20 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - Custom clang checker + - + - + - `Source <https://searchfox.org/mozilla-central/source/build/clang-plugin>`_ + - + * - Clang-Tidy + - Yes + - `bug 712350 <https://bugzilla.mozilla.org/show_bug.cgi?id=712350>`__ + - :ref:`Static analysis <Static Analysis>` + - https://clang.llvm.org/extra/clang-tidy/checks/list.html + * - Clang analyzer + - + - `bug 712350 <https://bugzilla.mozilla.org/show_bug.cgi?id=712350>`__ + - + - https://clang-analyzer.llvm.org/ + * - cpp virtual final + - + - + - :ref:`cpp virtual final` + - + * - Semmle/LGTM + - + - `bug 1458117 <https://bugzilla.mozilla.org/show_bug.cgi?id=1458117>`__ + - + - + * - clang-format + - Yes + - `bug 1188202 <https://bugzilla.mozilla.org/show_bug.cgi?id=1188202>`__ + - :ref:`Formatting C++ Code With clang-format` + - https://clang.llvm.org/docs/ClangFormat.html + +.. list-table:: CSS + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - Stylelint + - Yes + - `bug 1762027 <https://bugzilla.mozilla.org/show_bug.cgi?id=1762027>`__ + - :ref:`Stylelint` + - https://stylelint.io/ + +.. list-table:: JavaScript + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - Eslint + - Yes + - `bug 1229856 <https://bugzilla.mozilla.org/show_bug.cgi?id=1229856>`__ + - :ref:`ESLint` + - https://eslint.org/ + * - Mozilla ESLint + - + - `bug 1229856 <https://bugzilla.mozilla.org/show_bug.cgi?id=1229856>`__ + - :ref:`Mozilla ESLint Plugin` + - + * - Prettier + - Yes + - `bug 1558517 <https://bugzilla.mozilla.org/show_bug.cgi?id=1558517>`__ + - :ref:`JavaScript Coding style` + - https://prettier.io/ + +.. list-table:: Python + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - ruff + - Yes + - `bug 1811850 <https://bugzilla.mozilla.org/show_bug.cgi?id=1811850>`__ + - :ref:`ruff` + - https://github.com/charliermarsh/ruff + * - black + - Yes + - `bug 1555560 <https://bugzilla.mozilla.org/show_bug.cgi?id=1555560>`__ + - :ref:`black` + - https://black.readthedocs.io/en/stable + +.. list-table:: Rust + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - Rustfmt + - Yes + - `bug 1454764 <https://bugzilla.mozilla.org/show_bug.cgi?id=1454764>`__ + - :ref:`Rustfmt` + - https://github.com/rust-lang/rustfmt + * - Clippy + - + - `bug 1361342 <https://bugzilla.mozilla.org/show_bug.cgi?id=1361342>`__ + - :ref:`clippy` + - https://github.com/rust-lang/rust-clippy + +.. list-table:: Java/Kotlin + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - Spotless + - Yes + - `bug 1571899 <https://bugzilla.mozilla.org/show_bug.cgi?id=1571899>`__ + - :ref:`Spotless` + - https://github.com/diffplug/spotless + +.. list-table:: Others + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Tools + - Has autofixes + - Meta bug + - More info + - Upstream + * - shellcheck + - + - + - + - https://www.shellcheck.net/ + * - rstchecker + - + - + - :ref:`RST Linter` + - https://github.com/myint/rstcheck + * - Typo detection + - Yes + - + - :ref:`Codespell` + - https://github.com/codespell-project/codespell + * - Fluent Lint + - No + - + - :ref:`Fluent Lint` + - + * - YAML linter + - No + - + - :ref:`yamllint` + - https://github.com/adrienverge/yamllint diff --git a/docs/code-quality/lint/create.rst b/docs/code-quality/lint/create.rst new file mode 100644 index 0000000000..2efdf742f5 --- /dev/null +++ b/docs/code-quality/lint/create.rst @@ -0,0 +1,368 @@ +Adding a New Linter to the Tree +=============================== + +Linter Requirements +------------------- + +For a linter to be integrated into the mozilla-central tree, it needs to have: + +* Any required dependencies should be installed as part of ``./mach bootstrap`` +* A ``./mach lint`` interface +* Running ``./mach lint`` command must pass (note, linters can be disabled for individual directories) +* Taskcluster/Treeherder integration +* In tree documentation (under ``docs/code-quality/lint``) to give a basic summary, links and any other useful information +* Unit tests (under ``tools/lint/test``) to make sure that the linter works as expected and we don't regress. + +The review group in Phabricator is ``#linter-reviewers``. + +Linter Basics +------------- + +A linter is a yaml file with a ``.yml`` extension. Depending on how the type of linter, there may +be python code alongside the definition, pointed to by the 'payload' attribute. + +Here's a trivial example: + +no-eval.yml + +.. code-block:: yaml + + EvalLinter: + description: Ensures the string eval doesn't show up. + extensions: ['js'] + type: string + payload: eval + +Now ``no-eval.yml`` gets passed into :func:`LintRoller.read`. + + +Linter Types +------------ + +There are four types of linters, though more may be added in the future. + +1. string - fails if substring is found +2. regex - fails if regex matches +3. external - fails if a python function returns a non-empty result list +4. structured_log - fails if a mozlog logger emits any lint_error or lint_warning log messages + +As seen from the example above, string and regex linters are very easy to create, but they +should be avoided if possible. It is much better to use a context aware linter for the language you +are trying to lint. For example, use eslint to lint JavaScript files, use flake8 to lint python +files, etc. + +Which brings us to the third and most interesting type of linter, +external. External linters call an arbitrary python function which is +responsible for not only running the linter, but ensuring the results +are structured properly. For example, an external type could shell out +to a 3rd party linter, collect the output and format it into a list of +:class:`Issue` objects. The signature for this python +function is ``lint(files, config, **kwargs)``, where ``files`` is a list of +files to lint and ``config`` is the linter definition defined in the ``.yml`` +file. + +Structured log linters are much like external linters, but suitable +for cases where the linter code is using mozlog and emits +``lint_error`` or ``lint_warning`` logging messages when the lint +fails. This is recommended for writing novel gecko-specific lints. In +this case the signature for lint functions is ``lint(files, config, logger, +**kwargs)``. + + +Linter Definition +----------------- + +Each ``.yml`` file must have at least one linter defined in it. Here are the supported keys: + +* description - A brief description of the linter's purpose (required) +* type - One of 'string', 'regex' or 'external' (required) +* payload - The actual linting logic, depends on the type (required) +* include - A list of file paths that will be considered (optional) +* exclude - A list of file paths or glob patterns that must not be matched (optional) +* extensions - A list of file extensions to be considered (optional) +* setup - A function that sets up external dependencies (optional) +* support-files - A list of glob patterns matching configuration files (optional) +* find-dotfiles - If set to ``true``, run on dot files (.*) (optional) +* ignore-case - If set to ``true`` and ``type`` is regex, ignore the case (optional) + +In addition to the above, some ``.yml`` files correspond to a single lint rule. For these, the +following additional keys may be specified: + +* message - A string to print on infraction (optional) +* hint - A string with a clue on how to fix the infraction (optional) +* rule - An id string for the lint rule (optional) +* level - The severity of the infraction, either 'error' or 'warning' (optional) + +For structured_log lints the following additional keys apply: + +* logger - A StructuredLog object to use for logging. If not supplied + one will be created (optional) + + +Example +------- + +Here is an example of an external linter that shells out to the python flake8 linter, +let's call the file ``flake8_lint.py`` (`in-tree version <https://searchfox.org/mozilla-central/source/tools/lint/python/flake8.py>`__): + +.. code-block:: python + + import json + import os + import subprocess + from collections import defaultdict + from shutil import which + + from mozlint import result + + + FLAKE8_NOT_FOUND = """ + Could not find flake8! Install flake8 and try again. + """.strip() + + + def lint(files, config, **lintargs): + binary = os.environ.get('FLAKE8') + if not binary: + binary = which('flake8') + if not binary: + print(FLAKE8_NOT_FOUND) + return 1 + + # Flake8 allows passing in a custom format string. We use + # this to help mold the default flake8 format into what + # mozlint's Issue object expects. + cmdargs = [ + binary, + '--format', + '{"path":"%(path)s","lineno":%(row)s,"column":%(col)s,"rule":"%(code)s","message":"%(text)s"}', + ] + files + + proc = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, env=os.environ) + output = proc.communicate()[0] + + # all passed + if not output: + return [] + + results = [] + for line in output.splitlines(): + # res is a dict of the form specified by --format above + res = json.loads(line) + + # parse level out of the id string + if 'code' in res and res['code'].startswith('W'): + res['level'] = 'warning' + + # result.from_linter is a convenience method that + # creates a Issue using a LINTER definition + # to populate some defaults. + results.append(result.from_config(config, **res)) + + return results + +Now here is the linter definition that would call it: + +.. code-block:: yaml + + flake8: + description: Python linter + include: ['.'] + extensions: ['py'] + type: external + payload: py.flake8:lint + support-files: + - '**/.flake8' + +Notice the payload has two parts, delimited by ':'. The first is the module +path, which ``mozlint`` will attempt to import. The second is the object path +within that module (e.g, the name of a function to call). It is up to consumers +of ``mozlint`` to ensure the module is in ``sys.path``. Structured log linters +use the same import mechanism. + +The ``support-files`` key is used to list configuration files or files related +to the running of the linter itself. If using ``--outgoing`` or ``--workdir`` +and one of these files was modified, the entire tree will be linted instead of +just the modified files. + +Result definition +----------------- + +When generating the list of results, the following values are available. + +.. csv-table:: + :header: "Name", "Description", "Optional" + :widths: 20, 40, 10 + + "linter", "Name of the linter that flagged this error", "" + "path", "Path to the file containing the error", "" + "message", "Text describing the error", "" + "lineno", "Line number that contains the error", "" + "column", "Column containing the error", "" + "level", "Severity of the error, either 'warning' or 'error' (default 'error')", "Yes" + "hint", "Suggestion for fixing the error", "Yes" + "source", "Source code context of the error", "Yes" + "rule", "Name of the rule that was violated", "Yes" + "lineoffset", "Denotes an error spans multiple lines, of the form (<lineno offset>, <num lines>)", "Yes" + "diff", "A diff describing the changes that need to be made to the code", "Yes" + + +Automated testing +----------------- + +Every new checker must have tests associated. + +They should be pretty easy to write as most of the work is managed by the Mozlint +framework. The key declaration is the ``LINTER`` variable which must match +the linker declaration. + +As an example, the `Flake8 test <https://searchfox.org/mozilla-central/source/tools/lint/test/test_flake8.py>`_ looks like the following snippet: + +.. code-block:: python + + import mozunit + LINTER = 'flake8' + + def test_lint_single_file(lint, paths): + results = lint(paths('bad.py')) + assert len(results) == 2 + assert results[0].rule == 'F401' + assert results[1].rule == 'E501' + assert results[1].lineno == 5 + + if __name__ == '__main__': + mozunit.main() + +As always with tests, please make sure that enough positive and negative cases are covered. + +To run the tests: + +.. code-block:: shell + + $ ./mach python-test --subsuite mozlint + +To run a specific test: + +.. code-block:: shell + + ./mach python-test --subsuite mozlint tools/lint/test/test_black.py + +More tests can be `found in-tree <https://searchfox.org/mozilla-central/source/tools/lint/test>`_. + +Tracking fixed issues +--------------------- + +All the linters that provide ``fix support`` returns a dictionary instead of a list. + +``{"results":result,"fixed":fixed}`` + +* results - All the linting errors it was not able to fix +* fixed - Count of fixed errors (for ``fix=False`` this is 0) + +Some linters (example: `codespell <https://searchfox.org/mozilla-central/rev/0379f315c75a2875d716b4f5e1a18bf27188f1e6/tools/lint/spell/__init__.py#145-163>`_) might require two passes to count the number of fixed issues. +Others might just need `some tuning <https://searchfox.org/mozilla-central/rev/0379f315c75a2875d716b4f5e1a18bf27188f1e6/tools/lint/file-whitespace/__init__.py#28,60,85,112>`_. + +For adding tests to check your fixed count, add a global variable ``fixed = 0`` +and write a function to add your test as mentioned under ``Automated testing`` section. + + +Here's an example + +.. code-block:: python + + fixed = 0 + + + def test_lint_codespell_fix(lint, create_temp_file): + # Typo has been fixed in the contents to avoid triggering warning + # 'informations' ----> 'information' + contents = """This is a file with some typos and information. + But also testing false positive like optin (because this isn't always option) + or stuff related to our coding style like: + aparent (aParent). + but detects mistakes like mozilla + """.lstrip() + + path = create_temp_file(contents, "ignore.rst") + lint([path], fix=True) + + assert fixed == 2 + + +Bootstrapping Dependencies +-------------------------- + +Many linters, especially 3rd party ones, will require a set of dependencies. It +could be as simple as installing a binary from a package manager, or as +complicated as pulling a whole graph of tools, plugins and their dependencies. + +Either way, to reduce the burden on users, linters should strive to provide +automated bootstrapping of all their dependencies. To help with this, +``mozlint`` allows linters to define a ``setup`` config, which has the same +path object format as an external payload. For example (`in-tree version <https://searchfox.org/mozilla-central/source/tools/lint/flake8.yml>`__): + +.. code-block:: yaml + + flake8: + description: Python linter + include: ['.'] + extensions: ['py'] + type: external + payload: py.flake8:lint + setup: py.flake8:setup + +The setup function takes a single argument, the root of the repository being +linted. In the case of ``flake8``, it might look like: + +.. code-block:: python + + import subprocess + from distutils.spawn import find_executable + + def setup(root, **lintargs): + # This is a simple example. Please look at the actual source for better examples. + if not find_executable('flake8'): + subprocess.call(['pip', 'install', 'flake8']) + +The setup function will be called implicitly before running the linter. This +means it should return fast and not produce any output if there is no setup to +be performed. + +The setup functions can also be called explicitly by running ``mach lint +--setup``. This will only perform setup and not perform any linting. It is +mainly useful for other tools like ``mach bootstrap`` to call into. + + +Adding the linter to the CI +--------------------------- + +First, the job will have to be declared in Taskcluster. + +This should be done in the `mozlint Taskcluster configuration <https://searchfox.org/mozilla-central/source/taskcluster/ci/source-test/mozlint.yml>`_. +You will need to define a symbol, how it is executed and on what kind of change. + +For example, for flake8, the configuration is the following: + +.. code-block:: yaml + + py-flake8: + description: flake8 run over the gecko codebase + treeherder: + symbol: py(f8) + run: + mach: lint -l flake8 -f treeherder -f json:/builds/worker/mozlint.json + when: + files-changed: + - '**/*.py' + - '**/.flake8' + # moz.configure files are also Python files. + - '**/*.configure' + +If the linter requires an external program, you will have to install it in the `setup script <https://searchfox.org/mozilla-central/source/taskcluster/docker/lint/system-setup.sh>`_ +and maybe install the necessary files in the `Docker configuration <https://searchfox.org/mozilla-central/source/taskcluster/docker/lint/Dockerfile>`_. + +.. note:: + + If the defect found by the linter is minor, make sure that it is run as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_. + This prevents the tree from closing because of a tiny issue. + For example, the typo detection is run as tier-2. diff --git a/docs/code-quality/lint/index.rst b/docs/code-quality/lint/index.rst new file mode 100644 index 0000000000..2b2cfdefbd --- /dev/null +++ b/docs/code-quality/lint/index.rst @@ -0,0 +1,33 @@ +Linting +======= + +Linters are used in mozilla-central to help enforce coding style and avoid bad practices. +They cover a wide variety of languages and checks. + +Getting Help +------------ + +If you need help or have questions, please don’t hesitate to contact us via Matrix +in the "Lint and Formatting" room +(`#lint:mozilla.org <https://chat.mozilla.org/#/room/#lint:mozilla.org>`_). + + +.. toctree:: + :caption: Getting Started + :maxdepth: 2 + + usage + +.. toctree:: + :caption: Linter Implementations + :maxdepth: 1 + :glob: + + linters/* + +.. toctree:: + :caption: Linter Specifics + :maxdepth: 1 + + mozlint + create diff --git a/docs/code-quality/lint/linters/android-format.rst b/docs/code-quality/lint/linters/android-format.rst new file mode 100644 index 0000000000..ed23ac64de --- /dev/null +++ b/docs/code-quality/lint/linters/android-format.rst @@ -0,0 +1,31 @@ +Spotless +======== + +`Spotless <https://github.com/diffplug/spotless>`__ is a pluggable formatter +for Gradle and Android. + +In our current configuration, Spotless includes the +`Google Java Format plug-in <https://github.com/google/google-java-format>`__ +which formats all our Java code using the Google Java coding style guidelines, +and `ktlint <https://ktlint.github.io/>`__ which formats all +our Kotlin code using the official Kotlin coding convention and Android Kotlin +Style Guide. + + +Run Locally +----------- + +The mozlint integration of spotless can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter android-format + +Alternatively, omit the ``--linter android-format`` and run all configured linters, which will include +spotless. + + +Autofix +------- + +The spotless linter provides a ``--fix`` option. diff --git a/docs/code-quality/lint/linters/black.rst b/docs/code-quality/lint/linters/black.rst new file mode 100644 index 0000000000..60a06ce95b --- /dev/null +++ b/docs/code-quality/lint/linters/black.rst @@ -0,0 +1,36 @@ +Black +===== + +`Black <https://black.readthedocs.io/en/stable/>`__ is a opinionated python code formatter. + + +Run Locally +----------- + +The mozlint integration of black can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter black <file paths> + +Alternatively, omit the ``--linter black`` and run all configured linters, which will include +black. + + +Configuration +------------- + +To enable black on new directory, add the path to the include +section in the :searchfox:`black.yml <tools/lint/black.yml>` file. + +Autofix +------- + +The black linter provides a ``--fix`` option. + + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/black.yml>` +* :searchfox:`Source <tools/lint/python/black.py>` diff --git a/docs/code-quality/lint/linters/clang-format.rst b/docs/code-quality/lint/linters/clang-format.rst new file mode 100644 index 0000000000..a528af4358 --- /dev/null +++ b/docs/code-quality/lint/linters/clang-format.rst @@ -0,0 +1,35 @@ +clang-format +============ + +`clang-format <https://clang.llvm.org/docs/ClangFormat.html>`__ is a tool to reformat C/C++ to the right coding style. + +Run Locally +----------- + +The mozlint integration of clang-format can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter clang-format <file paths> + + +Configuration +------------- + +To enable clang-format on new directory, add the path to the include +section in the :searchfox:`clang-format.yml <tools/lint/clang-format.yml>` file. + +While excludes: will work, this linter will read the ignore list from :searchfox:`.clang-format-ignore file <.clang-format-ignore>` +at the root directory. This because it is also used by the ./mach clang-format -p command. + +Autofix +------- + +clang-format can reformat the code with the option `--fix` (based on the upstream option `-i`). +To highlight the results, we are using the ``--dry-run`` option (from clang-format 10). + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/clang-format.yml>` +* :searchfox:`Source <tools/lint/clang-format/__init__.py>` diff --git a/docs/code-quality/lint/linters/clippy.rst b/docs/code-quality/lint/linters/clippy.rst new file mode 100644 index 0000000000..40db532b88 --- /dev/null +++ b/docs/code-quality/lint/linters/clippy.rst @@ -0,0 +1,36 @@ +clippy +====== + +`clippy`_ is the tool for Rust static analysis. + +Run Locally +----------- + +The mozlint integration of clippy can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter clippy <file paths> + +.. note:: + + clippy expects a path or a .rs file. It doesn't accept Cargo.toml + as it would break the mozlint workflow. + +Configuration +------------- + +To enable clippy on new directory, add the path to the include +section in the `clippy.yml <https://searchfox.org/mozilla-central/source/tools/lint/clippy.yml>`_ file. + +Autofix +------- + +This linter provides a ``--fix`` option. +Please note that this option does not fix all detected issues. + +Sources +------- + +* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/clippy.yml>`_ +* `Source <https://searchfox.org/mozilla-central/source/tools/lint/clippy/__init__.py>`_ diff --git a/docs/code-quality/lint/linters/codespell.rst b/docs/code-quality/lint/linters/codespell.rst new file mode 100644 index 0000000000..9299a81b6e --- /dev/null +++ b/docs/code-quality/lint/linters/codespell.rst @@ -0,0 +1,36 @@ +Codespell +========= + +`codespell <https://github.com/codespell-project/codespell/>`__ is a popular tool to look for typical typos in the source code. + +It is enabled mostly for the documentation and English locale files. + +Run Locally +----------- + +The mozlint integration of codespell can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter codespell <file paths> + + +Configuration +------------- + +To enable codespell on new directory, add the path to the include +section in the :searchfox:`codespell.yml <tools/lint/codespell.yml>` file. + +This job is configured as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_. + +Autofix +------- + +Codespell provides a ``--fix`` option. It is based on the ``-w`` option provided by upstream. + + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/codespell.yml>` +* :searchfox:`Source <tools/lint/spell/__init__.py>` diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst new file mode 100644 index 0000000000..d1d60c963c --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst @@ -0,0 +1,114 @@ +===================== +Mozilla ESLint Plugin +===================== + +This is the documentation of Mozilla ESLint PLugin. + +Environments +============ + +The plugin implements the following environments: + + +.. toctree:: + :maxdepth: 2 + + eslint-plugin-mozilla/environment + +Rules +===== + +The plugin implements the following rules: + +.. toctree:: + :maxdepth: 1 + + eslint-plugin-mozilla/avoid-Date-timing + eslint-plugin-mozilla/avoid-removeChild + eslint-plugin-mozilla/balanced-listeners + eslint-plugin-mozilla/balanced-observers + eslint-plugin-mozilla/consistent-if-bracing + eslint-plugin-mozilla/import-browser-window-globals + eslint-plugin-mozilla/import-content-task-globals + eslint-plugin-mozilla/import-globals + eslint-plugin-mozilla/import-globals-from + eslint-plugin-mozilla/import-headjs-globals + eslint-plugin-mozilla/lazy-getter-object-name + eslint-plugin-mozilla/mark-exported-symbols-as-used + eslint-plugin-mozilla/mark-test-function-used + eslint-plugin-mozilla/no-aArgs + eslint-plugin-mozilla/no-addtask-setup + eslint-plugin-mozilla/no-arbitrary-setTimeout + eslint-plugin-mozilla/no-compare-against-boolean-literals + eslint-plugin-mozilla/no-cu-reportError + eslint-plugin-mozilla/no-define-cc-etc + eslint-plugin-mozilla/no-redeclare-with-import-autofix + eslint-plugin-mozilla/no-throw-cr-literal + eslint-plugin-mozilla/no-useless-parameters + eslint-plugin-mozilla/no-useless-removeEventListener + eslint-plugin-mozilla/no-useless-run-test + eslint-plugin-mozilla/prefer-boolean-length-check + eslint-plugin-mozilla/prefer-formatValues + eslint-plugin-mozilla/reject-addtask-only + eslint-plugin-mozilla/reject-chromeutils-import-params + eslint-plugin-mozilla/reject-eager-module-in-lazy-getter + eslint-plugin-mozilla/reject-global-this + eslint-plugin-mozilla/reject-globalThis-modification + eslint-plugin-mozilla/reject-importGlobalProperties + eslint-plugin-mozilla/reject-lazy-imports-into-globals + eslint-plugin-mozilla/reject-mixing-eager-and-lazy + eslint-plugin-mozilla/reject-multiple-getters-calls + eslint-plugin-mozilla/reject-relative-requires + eslint-plugin-mozilla/reject-requires-await + eslint-plugin-mozilla/reject-scriptableunicodeconverter + eslint-plugin-mozilla/reject-some-requires + eslint-plugin-mozilla/reject-top-level-await + eslint-plugin-mozilla/reject-import-system-module-from-non-system + eslint-plugin-mozilla/use-cc-etc + eslint-plugin-mozilla/use-chromeutils-generateqi + eslint-plugin-mozilla/use-chromeutils-import + eslint-plugin-mozilla/use-default-preference-values + eslint-plugin-mozilla/use-includes-instead-of-indexOf + eslint-plugin-mozilla/use-isInstance + eslint-plugin-mozilla/use-ownerGlobal + eslint-plugin-mozilla/use-returnValue + eslint-plugin-mozilla/use-services + eslint-plugin-mozilla/use-static-import + eslint-plugin-mozilla/valid-ci-uses + eslint-plugin-mozilla/valid-lazy + eslint-plugin-mozilla/valid-services + eslint-plugin-mozilla/valid-services-property + eslint-plugin-mozilla/var-only-at-top-level + +Tests +===== + +The tests for eslint-plugin-mozilla are run via `mochajs`_ on top of node. Most +of the tests use the `ESLint Rule Unit Test framework`_. + +.. _mochajs: https://mochajs.org/ +.. _ESLint Rule Unit Test Framework: http://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests + +Running Tests +------------- + +The tests for eslint-plugin-mozilla are run via `mochajs`_ on top of node. Most +of the tests use the `ESLint Rule Unit Test framework`_. + +The rules have some self tests, these can be run via: + +.. code-block:: shell + + $ cd tools/lint/eslint/eslint-plugin-mozilla + $ npm install + $ npm run test + +Disabling tests +--------------- + +In the unlikely event of needing to disable a test, currently the only way is +by commenting-out. Please file a bug if you have to do this. Bugs should be filed +in the *Testing* product under *Lint*. + +.. _mochajs: https://mochajs.org/ +.. _ESLint Rule Unit Test Framework: http://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst new file mode 100644 index 0000000000..b01b568a28 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst @@ -0,0 +1,30 @@ +avoid-Date-timing +================= + +Rejects grabbing the current time via Date.now() or new Date() for timing +purposes when the less problematic performance.now() can be used instead. + +The performance.now() function returns milliseconds since page load. To +convert that to milliseconds since the epoch, use: + +.. code-block:: js + + performance.timing.navigationStart + performance.now() + +Often timing relative to the page load is adequate and that conversion may not +be necessary. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Date.now() + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + new Date('2017-07-11'); + performance.now() diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst new file mode 100644 index 0000000000..15ece94d0d --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst @@ -0,0 +1,20 @@ +avoid-removeChild +================= + +Rejects using ``element.parentNode.removeChild(element)`` when ``element.remove()`` +can be used instead. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + elt.parentNode.removeChild(elt); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + elt.remove(); + elt.parentNode.removeChild(elt2); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst new file mode 100644 index 0000000000..f53c11e7aa --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst @@ -0,0 +1,20 @@ +balanced-listeners +================== + +Checks that for every occurrence of 'addEventListener' or 'on' there is an +occurrence of 'removeEventListener' or 'off' with the same event name. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + elt.addEventListener('click', handler, false); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + elt.addEventListener('event', handler); + elt.removeEventListener('event', handler); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst new file mode 100644 index 0000000000..b169a520a3 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst @@ -0,0 +1,20 @@ +balanced-observers +================== + +Checks that for every occurrence of ``addObserver`` there is an +occurrence of ``removeObserver`` with the same topic. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Services.obs.addObserver(observer, 'observable'); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + Services.obs.addObserver(observer, 'observable'); + Services.obs.removeObserver(observer, 'observable'); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst new file mode 100644 index 0000000000..7bf6b796ef --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst @@ -0,0 +1,23 @@ +consistent-if-bracing +===================== + +Checks that if/elseif/else bodies are braced consistently, so either all bodies +are braced or unbraced. Doesn't enforce either of those styles though. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + if (true) {1} else 0 + if (true) 1; else {0} + if (true) {1} else if (true) 2; else {0} + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + if (true) {1} else {0} + if (false) 1; else 0 + if (true) {1} else if (true) {2} else {0} diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst new file mode 100644 index 0000000000..2c779410d6 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst @@ -0,0 +1,76 @@ +Environment +=========== + +These environments are available by specifying a comment at the top of the file, +e.g. + +.. code-block:: js + + /* eslint-env mozilla/chrome-worker */ + +There are also built-in ESLint environments available as well. Find them here: http://eslint.org/docs/user-guide/configuring#specifying-environments + +browser-window +-------------- + +Defines the environment for scripts that are in the main browser.xhtml scope. + +chrome-script +------------- + +Defines the environment for scripts loaded by +``SpecialPowers.loadChromeScript``. + +chrome-worker +------------- + +Defines the environment for chrome workers. This differs from normal workers by +the fact that `ctypes` can be accessed as well. + +frame-script +------------ + +Defines the environment for scripts loaded by ``Services.mm.loadFrameScript``. + +jsm +--- + +Defines the environment for jsm files (javascript modules). + +privileged +---------- + +Defines the environment for privileged JS files. + +process-script +-------------- + +Defines the environment for scripts loaded by +``Services.ppmm.loadProcessScript``. + +remote-page +----------- + +Defines the environment for scripts loaded with ``<script src="...">`` in +``about:`` pages. + +simpletest +---------- + +Defines the environment for scripts that use the SimpleTest mochitest harness. + +sjs +--- + +Defines the environment for sjs files. + +special-powers-sandbox +---------------------- + +Defines the environment for scripts evaluated inside ``SpecialPowers`` sandbox +with the default options. + +xpcshell +-------- + +Defines the environment for xpcshell test files. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst new file mode 100644 index 0000000000..35c09cc8fd --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst @@ -0,0 +1,8 @@ +import-browser-window-globals +============================= + +For scripts included in browser-window, this will automatically inject the +browser-window global scopes into the file. + +This is a rule rather than an environment, as it allowed us to automatically +select the files to include. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst new file mode 100644 index 0000000000..f2550a1412 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst @@ -0,0 +1,14 @@ +import-content-task-globals +=========================== + +For files containing ContentTask.spawn calls, this will automatically declare +the frame script variables in the global scope. ContentTask is only available +to test files, so by default the configs only specify it for the mochitest based +configurations. + +This saves setting the file as a mozilla/frame-script environment. + +Note: due to the way ESLint works, it appears it is only easy to declare these +variables on a file global scope, rather than function global. This may mean that +they are incorrectly allowed, but given they are test files, this should be +detected during testing. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst new file mode 100644 index 0000000000..c2956ba05a --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst @@ -0,0 +1,18 @@ +import-globals-from +=================== + +Parses a file for globals defined in various unique Mozilla ways. + +When a ``/* import-globals-from <path> */`` comment is found in a file, then all +globals from the file at <path> will be imported in the current scope. This will +also operate recursively. + +This is useful for scripts that are loaded as <script> tag in a window and rely +on each other's globals. + +If <path> is a relative path, then it must be relative to the file being +checked by the rule. + +Note: ``import-globals-from`` does not support loading globals from ES modules. +These should be imported as variable definitions directly, or the file where +they are imported should be referenced. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst new file mode 100644 index 0000000000..2c47a5210f --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst @@ -0,0 +1,5 @@ +import-globals +============== + +Checks ``XPCOMUtils.defineLazyGetter`` etc and adds the name to the global +scope. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst new file mode 100644 index 0000000000..a754bd7985 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst @@ -0,0 +1,28 @@ +import-headjs-globals +===================== + +Import globals from head.js and from any files that were imported by +head.js (as far as we can correctly resolve the path). + +This rule is included in the test configurations. + +The following file import patterns are supported: + +- ``Services.scriptloader.loadSubScript(path)`` +- ``loader.loadSubScript(path)`` +- ``loadSubScript(path)`` +- ``loadHelperScript(path)`` +- ``import-globals-from path`` + +If path does not exist because it is generated e.g. +``testdir + "/somefile.js"`` we do our best to resolve it. + +The following patterns are supported: + +- ``Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm");`` +- ``loader.lazyRequireGetter(this, "name2"`` +- ``loader.lazyServiceGetter(this, "name3"`` +- ``XPCOMUtils.defineLazyModuleGetter(this, "setNamedTimeout", ...)`` +- ``loader.lazyGetter(this, "toolboxStrings"`` +- ``XPCOMUtils.defineLazyGetter(this, "clipboardHelper"`` +- ``ChromeUtils.defineLazyGetter(this, "clipboardHelper"`` diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst new file mode 100644 index 0000000000..090f445b69 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst @@ -0,0 +1,25 @@ +lazy-getter-object-name +============================= + +Enforce the standard object variable name ``lazy`` for +``ChromeUtils.defineESModuleGetters`` + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + const obj = {}; + ChromeUtils.defineESModuleGetters(obj, { + AppConstants: “resource://gre/modules/AppConstants.sys.mjs”, + }); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const lazy = {}; + ChromeUtils.defineESModuleGetters(lazy, { + AppConstants: “resource://gre/modules/AppConstants.sys.mjs”, + }); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst new file mode 100644 index 0000000000..92e315a249 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst @@ -0,0 +1,23 @@ +mark-exported-symbols-as-used +============================= + +Marks variables listed in ``EXPORTED_SYMBOLS`` as used so that ``no-unused-vars`` +does not complain about them. + +This rule also checks that ``EXPORTED_SYMBOLS`` is not defined using ``let`` as +``let`` isn't allowed as the lexical scope may die after the script executes. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + let EXPORTED_SYMBOLS = ["foo"]; + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + var EXPORTED_SYMBOLS = ["foo"]; + const EXPORTED_SYMBOLS = ["foo"]; diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst new file mode 100644 index 0000000000..a518d7415b --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst @@ -0,0 +1,8 @@ +mark-test-function-used +======================= + +Simply marks ``test`` (the test method) or ``run_test`` as used when in mochitests +or xpcshell tests respectively. This avoids ESLint telling us that the function +is never called. + +This rule is included in the test configurations. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst new file mode 100644 index 0000000000..7e398bcbbe --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst @@ -0,0 +1,22 @@ +no-aArgs +======== + +Checks that function argument names don't start with lowercase 'a' followed by +a capital letter. This is to prevent the use of Hungarian notation whereby the +first letter is a prefix that indicates the type or intended use of a variable. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + function(aFoo, aBar) {} + (aFoo, aBar) => {} + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + function(foo, bar) {} + (foo, bar) => {}) diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst new file mode 100644 index 0000000000..f26a869371 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst @@ -0,0 +1,27 @@ +no-addtask-setup +================ + +Reject using ``add_task(async function setup() { ... })`` in favour of +``add_setup(async function() { ... })``. + +Using semantically separate setup functions makes ``.only`` work correctly +and will allow for future improvements to setup/cleanup abstractions. + +This option can be autofixed (``--fix``). + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + add_task(async function setup() { ... }); + add_task(function setup() { ... }); + add_task(function init() { ... }); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + add_setup(async function() { ... }); + add_setup(function() { ... }); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst new file mode 100644 index 0000000000..a7d62e74ba --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst @@ -0,0 +1,23 @@ +no-arbitrary-setTimeout +======================= + +Disallows setTimeout with non-zero values in tests. Using arbitrary times for +setTimeout may cause intermittent failures in tests. A value of zero is allowed +as this is letting the event stack unwind, however also consider the use +of ``TestUtils.waitForTick``. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + function(aFoo, aBar) {} + (aFoo, aBar) => {} + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + function(foo, bar) {} + (foo, bar) => {}) diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst new file mode 100644 index 0000000000..b7785f2fc2 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst @@ -0,0 +1,23 @@ +no-compare-against-boolean-literals +=================================== + +Checks that boolean expressions do not compare against literal values +of ``true`` or ``false``. This is to prevent overly verbose code such as +``if (isEnabled == true)`` when ``if (isEnabled)`` would suffice. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + if (foo == true) {} + if (foo != false) {} + if (false == foo) {} + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + if (!foo) {} + if (!!foo) {} diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst new file mode 100644 index 0000000000..9f5a0def27 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst @@ -0,0 +1,23 @@ +no-cu-reportError +================= + +Disallows Cu.reportError. This has been deprecated and should be replaced by +console.error. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Cu.reportError("message"); + Cu.reportError("message", stack); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + console.error("message"); + let error = new Error("message"); + error.stack = stack; + console.error(error); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst new file mode 100644 index 0000000000..4421f4dd54 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst @@ -0,0 +1,23 @@ +no-define-cc-etc +================ + +Disallows old-style definitions for ``Cc``/``Ci``/``Cu``/``Cr``. These are now +defined globally for all chrome contexts. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + var Cc = Components.classes; + var Ci = Components.interfaces; + var {Ci: interfaces, Cc: classes, Cu: utils} = Components; + var Cr = Components.results; + + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const CC = Components.Constructor; diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst new file mode 100644 index 0000000000..d7d4edab50 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst @@ -0,0 +1,21 @@ +no-redeclare-with-import-autofix +================================ + +This is the +`builtin eslint rule no-redeclare <https://eslint.org/docs/latest/rules/no-redeclare>`_, +but with an additional fixer that can automatically remove superfluous +(duplicate) imports. + +For redeclarations that are not imports, there is no automatic fix, as +the author will likely have to rename variables so that they do not +redeclare existing variables or conflict with the name of a builtin +property or global variable. + +Typical duplicate imports happen when a `head.js` file, imports +a module and a test then subsequently also attempts to import the same +module. + +In browser mochitests, an additional typical scenario is importing +modules that are already imported in the main browser window. Because +these tests run in a scope that inherits from the main browser window +one, there is no need to re-import such modules. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst new file mode 100644 index 0000000000..0f9222de30 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst @@ -0,0 +1,38 @@ +no-throw-cr-literal +=================== + +This is similar to the ESLint built-in rule no-throw-literal. It disallows +throwing Components.results code directly. + +Throwing bare literals is inferior to throwing Exception objects, which provide +stack information. Cr.ERRORs should be be passed as the second argument to +``Components.Exception()`` to create an Exception object with stack info, and +the correct result property corresponding to the NS_ERROR that other code +expects. +Using a regular ``new Error()`` to wrap just turns it into a string and doesn't +set the result property, so the errors can't be recognised. + +This option can be autofixed (``--fix``). + +.. code-block:: js + + performance.timing.navigationStart + performance.now() + +Often timing relative to the page load is adequate and that conversion may not +be necessary. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + throw Cr.NS_ERROR_UNEXPECTED; + throw Components.results.NS_ERROR_ABORT; + throw new Error(Cr.NS_ERROR_NO_INTERFACE); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + throw Components.Exception("Not implemented", Cr.NS_ERROR_NOT_IMPLEMENTED); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst new file mode 100644 index 0000000000..485caf6522 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst @@ -0,0 +1,26 @@ +no-useless-parameters +===================== + +Reject common XPCOM methods called with useless optional parameters (eg. +``Services.io.newURI(url, null, null)``, or non-existent parameters (eg. +``Services.obs.removeObserver(name, observer, false)``). + +This option can be autofixed (``--fix``). + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + elt.addEventListener('click', handler, false); + Services.io.newURI('http://example.com', null, null); + Services.obs.notifyObservers(obj, 'topic', null); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + elt.addEventListener('click', handler); + Services.io.newURI('http://example.com'); + Services.obs.notifyObservers(obj, 'topic'); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst new file mode 100644 index 0000000000..ce314ab58d --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst @@ -0,0 +1,20 @@ +no-useless-removeEventListener +============================== + +Reject calls to removeEventListener where ``{once: true}`` could be used instead. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + elt.addEventListener('click', function listener() { + elt.removeEventListener('click', listener); + }); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + elt.addEventListener('click', handler, {once: true}); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst new file mode 100644 index 0000000000..a079405696 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst @@ -0,0 +1,6 @@ +no-useless-run-test +=================== + +Designed for xpcshell-tests. Rejects definitions of ``run_test()`` where the +function only contains a single call to ``run_next_test()``. xpcshell's head.js +already defines a utility function so there is no need for duplication. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst new file mode 100644 index 0000000000..cd6ee4e544 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst @@ -0,0 +1,24 @@ +prefer-boolean-length-check +=========================== + +Prefers using a boolean length check rather than comparing against zero. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + if (foo.length == 0) {} + if (foo.length > 0) {} + if (foo && foo.length == 0) {} + function bar() { return foo.length > 0 } + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + if (foo.length && foo.length) {} + if (!foo.length) {} + var a = foo.length > 0 + function bar() { return !!foo.length } diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst new file mode 100644 index 0000000000..88eedee792 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst @@ -0,0 +1,23 @@ +prefer-formatValues +=================== + +Rejects multiple calls to document.l10n.formatValue in the same code block, to +reduce localization overheads. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + { + document.l10n.formatValue('foobar'); + document.l10n.formatValue('foobaz'); + } + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + document.l10n.formatValue('foobar'); + document.l10n.formatValues(['foobar', 'foobaz']); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst new file mode 100644 index 0000000000..e540b24416 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst @@ -0,0 +1,6 @@ +reject-addtask-only +=================== + +Designed for JavaScript tests using the add_task pattern. Rejects chaining +.only() to an add_task() call, which is useful for local testing to run a +single task in isolation but is easy to land into the tree by accident. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst new file mode 100644 index 0000000000..4710878f8d --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst @@ -0,0 +1,22 @@ +reject-chromeutils-import-params +================================ + +``ChromeUtils.import`` used to be able to be called with two arguments, however +the second argument is no longer supported. Exports from modules should now be +explicit, and the imported symbols being accessed from the returned object. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this); + ChromeUtils.import("resource://gre/modules/AppConstants.jsm", null); + ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {}); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst new file mode 100644 index 0000000000..fd81793690 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst @@ -0,0 +1,35 @@ +reject-eager-module-in-lazy-getter +================================== + +Rejects defining a lazy getter for module that's known to be loaded early in the +startup process and it is not necessary to lazy load it. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + ChromeUtils.defineESModuleGetters(lazy, { + AppConstants: "resource://gre/modules/AppConstants.sys.mjs", + }); + XPCOMUtils.defineLazyModuleGetters(lazy, { + XPCOMUtils: "resource://gre/modules/XPCOMUtils.jsm", + }); + XPCOMUtils.defineLazyModuleGetter( + lazy, + "AppConstants", + "resource://gre/modules/AppConstants.jsm", + }); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; + const { XPCOMUtils } = ChromeUtils.import( + "resource://gre/modules/XPCOMUtils.jsm" + ); + const { AppConstants } = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" + ); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst new file mode 100644 index 0000000000..b3d94321f5 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst @@ -0,0 +1,29 @@ +reject-global-this +====================== + +Rejects global ``this`` usage in JSM files. The global ``this`` is not +available in ESM, and this is a preparation for the migration. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + this.EXPORTED_SYMBOLS = ["foo"]; + + XPCOMUtils.defineLazyModuleGetters(this, { + AddonManager: "resource://gre/modules/AddonManager.jsm", + }); + + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const EXPORTED_SYMBOLS = ["foo"]; + + const lazy = {}; + XPCOMUtils.defineLazyModuleGetters(lazy, { + AddonManager: "resource://gre/modules/AddonManager.jsm", + }); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst new file mode 100644 index 0000000000..dd4fc4b2af --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst @@ -0,0 +1,19 @@ +reject-globalThis-modification +============================== + +Reject any modification to ``globalThis`` inside the system modules. + +``globalThis`` is the shared global inside the system modules, and modification +on it is visible from all modules, and it shouldn't be done unless it's really +necessary. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + globalThis.foo = 10; + Object.defineProperty(globalThis, "bar", { value: 20}); + ChromeUtils.defineESModuleGetters(globalThis, { + AppConstants: "resource://gre/modules/AppConstants.sys.mjs", + }); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst new file mode 100644 index 0000000000..d168676745 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst @@ -0,0 +1,36 @@ +reject-import-system-module-from-non-system +=========================================== + +Rejects static import declaration for system modules (``.sys.mjs``) from non-system +modules. + +Using static import for a system module into a non-system module would create a separate instance of the imported object(s) that is not shared with the other system modules and would break the per-process singleton expectation. + +The reason for this is that inside system modules, a static import will load the module into the shared global. Inside non-system modules, the static import will load into a different global (e.g. window). This will cause the module to be loaded into different scopes, and hence create separate instances. The fix is to use ``ChromeUtils.importESModule`` which will import the object via the system module shared global scope. + + +Examples of incorrect code for this rule: +----------------------------------------- + +Inside a non-system module: + +.. code-block:: js + + import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; + +Examples of correct code for this rule: +--------------------------------------- + +Inside a non-system module: + +.. code-block:: js + + const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" + ); + +Inside a system module: + +.. code-block:: js + + import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst new file mode 100644 index 0000000000..68b2e46928 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst @@ -0,0 +1,45 @@ +reject-importGlobalProperties +============================= + +Rejects calls to ``Cu.importGlobalProperties`` or +``XPCOMUtils.defineLazyGlobalGetters``. + +In system modules all the required properties should already be available. In +non-module code or non-system modules, webidl defined interfaces should already +be available and hence do not need importing. + +Options +------- + +* "everything": Disallows using the import/getters completely. +* "allownonwebidl": Disallows using the import functions for webidl symbols. Allows + other symbols. + +everything +---------- + +Incorrect code for this option: + +.. code-block:: js + + Cu.importGlobalProperties(['TextEncoder']); + XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder']); + +allownonwebidl +-------------- + +Incorrect code for this option: + +.. code-block:: js + + // AnimationEffect is a webidl property. + Cu.importGlobalProperties(['AnimationEffect']); + XPCOMUtils.defineLazyGlobalGetters(this, ['AnimationEffect']); + +Correct code for this option: + +.. code-block:: js + + // TextEncoder is not defined by webidl. + Cu.importGlobalProperties(['TextEncoder']); + XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder']); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst new file mode 100644 index 0000000000..64230ab6f1 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst @@ -0,0 +1,36 @@ +reject-lazy-imports-into-globals +================================ + +Rejects importing lazy items into ``window`` or ``globalThis`` when in a +non-system module scope. + +Importing into the ``window`` scope (or ``globalThis``) will share the imported +global with everything else in the same window. In modules, this is generally +unnecessary and undesirable because each module imports what it requires. +Additionally, sharing items via the global scope makes it more difficult for +linters to determine the available globals. + +Instead, the globals should either be imported directly, or into a lazy object. +If there is a good reason for sharing the globals via the ``window`` scope, then +this rule may be disabled as long as a comment is added explaining the reasons. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + XPCOMUtils.defineLazyModuleGetter(globalThis, "foo", "foo.jsm"); + XPCOMUtils.defineLazyModuleGetter(window, "foo", "foo.jsm"); + XPCOMUtils.defineLazyGetter(globalThis, "foo", () => {}); + XPCOMUtils.defineLazyGetter(window, "foo", () => {}); + ChromeUtils.defineLazyGetter(globalThis, "foo", () => {}); + ChromeUtils.defineLazyGetter(window, "foo", () => {}); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const lazy = {}; + XPCOMUtils.defineLazyGetter(lazy, "foo", () => {}); + ChromeUtils.defineLazyGetter(lazy, "bar", () => {}); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst new file mode 100644 index 0000000000..1bf5100901 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst @@ -0,0 +1,22 @@ +reject-mixing-eager-and-lazy +================================== + +Rejects defining a lazy getter for a module that's eagerly imported at +top-level script unconditionally. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + const { SomeProp } = ChromeUtils.import("resource://gre/modules/Foo.jsm"); + XPCOMUtils.defineLazyModuleGetter(lazy, { + OtherProp: "resource://gre/modules/Foo.jsm", + }); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const { SomeProp, OtherProp } = ChromeUtils.import("resource://gre/modules/Foo.jsm"); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst new file mode 100644 index 0000000000..7ea048402b --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst @@ -0,0 +1,27 @@ +reject-multiple-getters-calls +============================= + +Rejects multiple calls on ``ChromeUtils.defineESModuleGetters`` for the same +target in the same context. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + ChromeUtils.defineESModuleGetters(lazy, { + AppConstants: "resource://gre/modules/AppConstants.sys.mjs", + }); + ChromeUtils.defineESModuleGetters(lazy, { + PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", + }); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + ChromeUtils.defineESModuleGetters(lazy, { + AppConstants: "resource://gre/modules/AppConstants.sys.mjs", + PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", + }); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst new file mode 100644 index 0000000000..4387041b26 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst @@ -0,0 +1,22 @@ +reject-relative-requires +======================== + +Rejects calls to require which use relative directories. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + require("./relative/path") + require("../parent/folder/path") + loader.lazyRequireGetter(this, "path", "../parent/folder/path", true) + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + require("devtools/absolute/path") + require("resource://gre/modules/SomeModule.jsm") + loader.lazyRequireGetter(this, "path", "devtools/absolute/path", true) diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst new file mode 100644 index 0000000000..2a8618939f --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst @@ -0,0 +1,20 @@ +reject-requires-await +===================== + +`Assert.rejects` must be preceded by an `await`, otherwise the assertion +may not be completed before the test finishes, might not be caught +and might cause intermittent issues in other tests. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Assert.rejects(myfunc(), /startup failed/, "Should reject"); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + await Assert.rejects(myfunc(), /startup failed/, "Should reject"); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst new file mode 100644 index 0000000000..8f6ae39060 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst @@ -0,0 +1,13 @@ +reject-scriptableunicodeconverter +================================================ + +Rejects calls into ``Ci.nsIScriptableUnicodeConverter``. This is configured as a warning. +You should use |TextEncoder|_ or |TextDecoder|_ for new code. +If modifying old code, please consider swapping it in if possible; if this is tricky please ensure +a bug is on file. + +.. |TextEncoder| replace:: ``TextEncoder`` +.. _TextEncoder: https://searchfox.org/mozilla-central/source/dom/webidl/TextEncoder.webidl + +.. |TextDecoder| replace:: ``TextDecoder`` +.. _TextDecoder: https://searchfox.org/mozilla-central/source/dom/webidl/TextDecoder.webidl diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst new file mode 100644 index 0000000000..476dcbcb94 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst @@ -0,0 +1,6 @@ +reject-some-requires +==================== + +This takes an option, a regular expression. Invocations of +``require`` with a string literal argument are matched against this +regexp; and if it matches, the ``require`` use is flagged. diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst new file mode 100644 index 0000000000..38be0b2d22 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst @@ -0,0 +1,26 @@ +reject-top-level-await +====================== + +Rejects ``await`` at the top-level of code in modules. Top-level ``await`` is +not currently support in Gecko's component modules, so this is rejected. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + await foo; + + if (expr) { + await foo; + } + + for await (let x of [1, 2, 3]) { } + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + async function() { await foo; } + async function() { for await (let x of [1, 2, 3]) { } } diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst new file mode 100644 index 0000000000..902b4a630c --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst @@ -0,0 +1,26 @@ +use-cc-etc +====================== + +This requires using ``Cc`` rather than ``Components.classes``, and the same for +``Components.interfaces``, ``Components.results`` and ``Components.utils``. +This has a slight performance advantage by avoiding the use of the dot. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + let foo = Components.classes['bar']; + let bar = Components.interfaces.bar; + Components.results.NS_ERROR_ILLEGAL_INPUT; + Components.utils.reportError('fake'); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + let foo = Cc['bar']; + let bar = Ci.bar; + Cr.NS_ERROR_ILLEGAL_INPUT; + Cu.reportError('fake'); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst new file mode 100644 index 0000000000..3da22e139a --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst @@ -0,0 +1,33 @@ +use-chromeutils-generateqi +========================== + +Reject use of ``XPCOMUtils.generateQI`` and JS-implemented QueryInterface +methods in favor of ``ChromeUtils``. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + X.prototype.QueryInterface = XPCOMUtils.generateQI(["nsIMeh"]); + X.prototype = { QueryInterface: XPCOMUtils.generateQI(["nsIMeh"]) }; + X.prototype = { QueryInterface: function QueryInterface(iid) { + if ( + iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIMeh) || + iid.equals(nsIFlug) || + iid.equals(Ci.amIFoo) + ) { + return this; + } + throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE); + } }; + + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + X.prototype.QueryInterface = ChromeUtils.generateQI(["nsIMeh"]); + X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh"]) } diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst new file mode 100644 index 0000000000..c38304193a --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst @@ -0,0 +1,24 @@ +use-chromeutils-import +====================== + +Require use of ``ChromeUtils.import`` and ``ChromeUtils.defineModuleGetter`` +rather than ``Components.utils.import`` and +``XPCOMUtils.defineLazyModuleGetter``. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Components.utils.import("resource://gre/modules/AppConstants.jsm", this); + XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this); + ChromeUtils.defineModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); + // 4 argument version of defineLazyModuleGetter is allowed. + XPCOMUtils.defineLazyModuleGetter(this, "AppConstants","resource://gre/modules/AppConstants.jsm","Foo"); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst new file mode 100644 index 0000000000..2392709e89 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst @@ -0,0 +1,19 @@ +use-default-preference-values +============================= + +Require providing a second parameter to ``get*Pref`` methods instead of +using a try/catch block. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + try { blah = branch.getCharPref('blah'); } catch(e) {} + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + blah = branch.getCharPref('blah', true); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst new file mode 100644 index 0000000000..bb65ebea2c --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst @@ -0,0 +1,21 @@ +use-includes-instead-of-indexOf +=============================== + +Use ``.includes`` instead of ``.indexOf`` to check if something is in an array +or string. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + let a = foo.indexOf(bar) >= 0; + let a = foo.indexOf(bar) == -1; + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + let a = foo.includes(bar); + let a = foo.indexOf(bar) > 0; diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst new file mode 100644 index 0000000000..dca1e51c82 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst @@ -0,0 +1,42 @@ +use-isInstance +============== + +Prefer ``.isInstance()`` in chrome scripts over the standard ``instanceof`` +operator for DOM interfaces, since the latter will return false when the object +is created from a different context. + +These files are covered: + +- ``*.sys.mjs`` +- ``*.jsm`` +- ``*.jsm.js`` +- ``*.xhtml`` with ``there.is.only.xul`` +- ``*.js`` with a heuristic + +Since there is no straightforward way to detect chrome scripts, currently the +linter assumes that any script including the following words are chrome +privileged. This of course may not be sufficient and is open for change: + +- ``ChromeUtils``, but not ``SpecialPowers.ChromeUtils`` +- ``BrowserTestUtils``, ``PlacesUtils`` +- ``document.createXULElement`` +- ``loader.lazyRequireGetter`` +- ``Services.foo``, but not ``SpecialPowers.Services.foo`` + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + node instanceof Node + text instanceof win.Text + target instanceof this.contentWindow.HTMLAudioElement + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + Node.isInstance(node) + win.Text.isInstance(text) + this.contentWindow.HTMLAudioElement.isInstance(target) diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst new file mode 100644 index 0000000000..5d9905fc9f --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst @@ -0,0 +1,20 @@ +use-ownerGlobal +=============== + +Require ``.ownerGlobal`` instead of ``.ownerDocument.defaultView``. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + aEvent.target.ownerDocument.defaultView; + this.DOMPointNode.ownerDocument.defaultView.getSelection(); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + aEvent.target.ownerGlobal; + this.DOMPointNode.ownerGlobal.getSelection(); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst new file mode 100644 index 0000000000..1280703747 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst @@ -0,0 +1,20 @@ +use-returnValue +=============== + +Warn when idempotent methods are called and their return value is unused. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + foo.concat(bar) + baz.concat() + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + a = foo.concat(bar) + b = baz.concat() diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst new file mode 100644 index 0000000000..1a57e3da10 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst @@ -0,0 +1,21 @@ +use-services +============ + +Requires the use of ``Services`` rather than ``Cc[].getService()`` where a +service is already defined in ``Services``. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); + Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + Services.wm.addListener() + Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator) diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst new file mode 100644 index 0000000000..9090dd80b7 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst @@ -0,0 +1,21 @@ +use-static-import +================= + +Requires the use of static imports in system ES module files (``.sys.mjs``) +where possible. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs"); + const { XPCOMUtils: foo } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs"); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; + import { XPCOMUtils as foo } from "resource://gre/modules/XPCOMUtils.sys.mjs"; diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst new file mode 100644 index 0000000000..440d730e05 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst @@ -0,0 +1,42 @@ +valid-ci-uses +============= + +Ensures that interface accesses on ``Ci`` are valid, and property accesses on +``Ci.<interface>`` are also valid. + +This rule requires a full build to run, and is not turned on by default. To run +this rule manually, use: + +.. code-block:: console + + MOZ_OBJDIR=objdir-ff-opt ./mach eslint --rule="mozilla/valid-ci-uses: error" * + +Examples of incorrect code for this rule: +----------------------------------------- + +``nsIFoo`` does not exist. + +.. code-block:: js + + Ci.nsIFoo + +``UNKNOWN_CONSTANT`` does not exist on nsIURIFixup. + +.. code-block:: js + + Ci.nsIURIFixup.UNKNOWN_CONSTANT + +Examples of correct code for this rule: +--------------------------------------- + +``nsIFile`` does exist. + +.. code-block:: js + + Ci.nsIFile + +``FIXUP_FLAG_NONE`` does exist on nsIURIFixup. + +.. code-block:: js + + Ci.nsIURIFixup.FIXUP_FLAG_NONE diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst new file mode 100644 index 0000000000..fcbe5d064e --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst @@ -0,0 +1,55 @@ +valid-lazy +========== + +Ensures that definitions and uses of properties on the ``lazy`` object are valid. +This rule checks for using unknown properties, duplicated symbols, unused +symbols, and also lazy getter used at top-level unconditionally. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + const lazy = {}; + if (x) { + // Unknown lazy member property {{name}} + lazy.bar.foo(); + } + +.. code-block:: js + + const lazy = {}; + XPCOMUtils.defineLazyGetter(lazy, "foo", "foo.jsm"); + + // Duplicate symbol foo being added to lazy. + XPCOMUtils.defineLazyGetter(lazy, "foo", "foo1.jsm"); + if (x) { + lazy.foo3.bar(); + } + +.. code-block:: js + + const lazy = {}; + // Unused lazy property foo + XPCOMUtils.defineLazyGetter(lazy, "foo", "foo.jsm"); + +.. code-block:: js + + const lazy = {}; + XPCOMUtils.defineLazyGetter(lazy, "foo", "foo.jsm"); + // Used at top-level unconditionally. + lazy.foo.bar(); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + const lazy = {}; + XPCOMUtils.defineLazyGetter(lazy, "foo1", () => {}); + XPCOMUtils.defineLazyModuleGetters(lazy, { foo2: "foo2.jsm" }); + + if (x) { + lazy.foo1.bar(); + lazy.foo2.bar(); + } diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst new file mode 100644 index 0000000000..c6c61abac2 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst @@ -0,0 +1,30 @@ +valid-services-property +======================= + +Ensures that accesses of properties of items accessed via the ``Services`` +object are valid. + +This rule requires a full build to run, and is not turned on by default. To run +this rule manually, use: + +.. code-block:: console + + MOZ_OBJDIR=objdir-ff-opt ./mach eslint --rule="mozilla/valid-services-property: error" * + +Examples of incorrect code for this rule: +----------------------------------------- + +Assuming ``foo`` is not defined within ``Ci.nsISearchService``. + +.. code-block:: js + + Services.search.foo(); + +Examples of correct code for this rule: +--------------------------------------- + +Assuming ``bar`` is defined within ``Ci.nsISearchService``. + +.. code-block:: js + + Services.search.bar(); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst new file mode 100644 index 0000000000..bd76cb52ac --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst @@ -0,0 +1,24 @@ +valid-services +============== + +Ensures that accesses of the ``Services`` object are valid. +``Services`` are defined in ``tools/lint/eslint/eslint-plugin-mozilla/lib/services.json`` and can be added by copying from +``<objdir>/xpcom/components/services.json`` after a build. + +Examples of incorrect code for this rule: +----------------------------------------- + +Assuming ``foo`` is not defined within Services. + +.. code-block:: js + + Services.foo.fn(); + +Examples of correct code for this rule: +--------------------------------------- + +Assuming ``bar`` is defined within Services. + +.. code-block:: js + + Services.bar.fn(); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst new file mode 100644 index 0000000000..d21fc1b299 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst @@ -0,0 +1,21 @@ +var-only-at-top-level +===================== + +Marks all var declarations that are not at the top level invalid. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + { var foo; } + function() { var bar; } + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + var foo; + { let foo; } + function () { let bar; } diff --git a/docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst b/docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst new file mode 100644 index 0000000000..e20c8562b6 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst @@ -0,0 +1,18 @@ +============================== +Mozilla ESLint SpiderMonkey JS +============================== + +This plugin adds a processor and an environment for the SpiderMonkey JS code. + +Processors +========== + +The processor is used to pre-process all `*.js` files and deals with the macros +that SpiderMonkey uses. + +Environments +============ + +The plugin provides a custom environment for SpiderMonkey's self-hosted code. It +adds all self-hosting functions, error message numbers, and other self-hosting +definitions as global, read-only identifiers. diff --git a/docs/code-quality/lint/linters/eslint.rst b/docs/code-quality/lint/linters/eslint.rst new file mode 100644 index 0000000000..3f3e33467b --- /dev/null +++ b/docs/code-quality/lint/linters/eslint.rst @@ -0,0 +1,211 @@ +ESLint +====== + +`ESLint`__ is a popular linter for JavaScript. The ESLint integration also uses +`Prettier`_ to enforce code formatting. + +Run Locally +----------- + +The mozlint integration of ESLint can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter eslint <file paths> + +Alternatively, omit the ``--linter eslint`` and run all configured linters, which will include +ESLint. + +ESLint also supports the ``--fix`` option to autofix most errors raised from most of the rules. + +See the `Usage guide`_ for more options. + +Understanding Rules and Errors +------------------------------ + +* Only some files are linted, see the :searchfox:`configuration <tools/lint/eslint.yml>` for details. + + * By design we do not lint/format reftests not crashtests as these are specially crafted tests. + +* If you don't understand a rule, you can look it in `eslint.org's rule list`_ for more + information about it. +* For Mozilla specific rules (with the mozilla/ prefix), see these for more details: + + * `eslint-plugin-mozilla`_ + * `eslint-plugin-spidermonkey-js`_ + +Common Issues and How To Solve Them +----------------------------------- + +My editor says that ``mozilla/whatever`` is unknown +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Run ``./mach eslint --setup``, and restart your editor. + +My editor doesn't understand a new global I've just added (e.g. to a content file or head.js file) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* This is a limitation which is a mixture of our ESLint setup and how we share globals across files. +* Restarting your editor should pick up the new globals. +* You can always double check via ``./mach lint --linter eslint <file path>`` on the command line. + +I am getting a linter error "Unknown Services member property" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Make sure to add any new Services to ``tools/lint/eslint/eslint-plugin-mozilla/lib/services.json``. For example by copying from +``<objdir>/xpcom/components/services.json`` after a build. + +.. _adding-tests: + +I'm adding tests, how do I set up the right configuration? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Please note we prefer the tests to be in named directories as this makes it +easier to identify the types of tests developers are working with. Additionally, +it is not possible to scope ESLint rules to individual files based on .ini +files without a build step that would break editors, or an expensive loading +cycle. + +* If the directory path of the tests is one of the `known ones`_, then ESLint will + do the right thing for that test type. This is the preferred option. + + * For example placing xpcshell-tests in ``browser/components/foo/test/unit/`` + will set up ESLint correctly. + +* If you really can't match the directory name, e.g. like the + ``browser/base/content/tests/*``, then you'll need to add a new entry in + :searchfox:`.eslintrc-test-paths.js <.eslintrc-test-paths.js>`. + +Please do not add new cases of multiple types of tests within a single directory, +this is `difficult for ESLint to handle`_. Currently this may cause: + +* Rules to be incorrectly applied to the wrong types of test file. +* Extra definitions for globals in tests which means that the no undefined variables + rule does not get triggered in some cases. + +I'm using an ES module +^^^^^^^^^^^^^^^^^^^^^^ + +* Use a ``.mjs`` extension for the file. ESLint will pick this up and automatically + treat it as a module. +* If it is a system module (e.g. component definition or other non-frontend code), + use a ``.sys.mjs`` extension. + +This code should neither be linted nor formatted +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* If it is a third-party piece of code, please add it to :searchfox:`ThirdPartyPaths.txt <tools/rewriting/ThirdPartyPaths.txt>`. +* If it is a generated file, please add it to :searchfox:`Generated.txt <tools/rewriting/Generated.txt>`. +* If intentionally invalid, please add it to :searchfox:`.eslintignore <.eslintignore>`. + +This code shouldn't be formatted +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The vast majority of code should be formatted, however we allow some limited +cases where it makes sense, for example: + +* A table in an array where laying it out in a table fashion makes it more readable. +* Other structures or function calls where layout is more readable in a particular format. + +To disable prettier for code like this, ``// prettier-ignore`` may be used on +the line previous to where you want it disabled. +See the `prettier ignore docs`_ for more information. + +I have valid code that is failing the ``no-undef`` rule or can't be parsed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Please do not add this to :searchfox:`.eslintignore <.eslintignore>`. Generally + this can be fixed, if the following tips don't help, please `seek help`_. +* If you are adding a new test directory, see the :ref:`section above <adding-tests>` + +* If you are writing a script loaded into special environment (e.g. frame script) you may need to tell ESLint to use the `environment definitions`_ for each case: + + * ``/* eslint-env mozilla/frame-script */`` + +* If you are writing a worker, then you may need to use the worker or chrome-worker environment: + + * ``/* eslint-env worker */`` + * ``/* eslint-env mozilla/chrome-worker */`` + +* I use ``Services.scriptloader.loadSubScript``: + + * ``/* import-globals-from relative/path/to/file.js`` + +Configuration +------------- + +The global configuration file lives in ``topsrcdir/.eslintrc``. This global configuration can be +overridden by including an ``.eslintrc`` in the appropriate subdirectory. For an overview of the +supported configuration, see `ESLint's documentation`_. + +Please keep differences in rules across the tree to a minimum. We want to be consistent to +make it easier for developers. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/eslint.yml>` +* :searchfox:`Source <tools/lint/eslint/__init__.py>` + +Builders +-------- + +`Mark Banner (standard8) <https://people.mozilla.org/s?query=standard8>`__ owns +the builders. Questions can also be asked on #lint:mozilla.org on Matrix. + +ESLint (ES) +^^^^^^^^^^^ + +This is a tier-1 task. For test failures the patch causing the +issue should be backed out or the issue fixed. + +Some failures can be fixed with ``./mach eslint --fix path/to/file``. + +For test harness issues, file bugs in Developer Infrastructure :: Lint and Formatting. + +ESLint-build (ES-B) +^^^^^^^^^^^^^^^^^^^ + +This is a tier-2 task that is run once a day at midnight UTC via a cron job. + +It currently runs the ESLint rules plus two additional rules: + +* `valid-ci-uses <eslint-plugin-mozilla/valid-ci-uses.html>`__ +* `valid-services-property <eslint-plugin-mozilla/valid-services-property.html>`__ + +These are two rules that both require build artifacts. + +To run them manually, you can run: + +``MOZ_OBJDIR=objdir-ff-opt ./mach eslint --rule "mozilla/valid-ci-uses: error" --rule "mozilla/valid-services-property: error" *`` + +For test failures, the regression causing bug may be able to be found by: + + * Determining if the file where the error is reported has been changed recently. + * Seeing if an associated ``.idl`` file has been changed. + +If no regressing bug can easily be found, file a bug in the relevant +product/component for the file where the failure is and cc :standard8. + +For test harness issues, file bugs in Developer Infrastructure :: Lint and Formatting. + +.. toctree:: + :hidden: + + eslint-plugin-mozilla + eslint-plugin-spidermonkey-js + +.. __: https://eslint.org/ +.. _Prettier: https://prettier.io/ +.. _Usage guide: ../usage.html +.. _ESLint's documentation: https://eslint.org/docs/user-guide/configuring +.. _eslint.org's rule list: https://eslint.org/docs/rules/ +.. _eslint-plugin-mozilla: eslint-plugin-mozilla.html +.. _eslint-plugin-spidermonkey-js: eslint-plugin-spidermonkey-js.html +.. _informed that it is a module: https://searchfox.org/mozilla-central/rev/9399e5832979755cd340383f4ca4069dd5fc7774/browser/base/content/.eslintrc.js +.. _seek help: ../index.html#getting-help +.. _patterns in .eslintrc.js: https://searchfox.org/mozilla-central/rev/9399e5832979755cd340383f4ca4069dd5fc7774/.eslintrc.js#24-38 +.. _environment definitions: ./eslint-plugin-mozilla/environment.html +.. _known ones: https://searchfox.org/mozilla-central/rev/287583a4a605eee8cd2d41381ffaea7a93d7b987/.eslintrc.js#24-40 +.. _difficult for ESLint to handle: https://bugzilla.mozilla.org/show_bug.cgi?id=1379669 +.. _prettier ignore docs: https://prettier.io/docs/en/ignore.html diff --git a/docs/code-quality/lint/linters/file-perm.rst b/docs/code-quality/lint/linters/file-perm.rst new file mode 100644 index 0000000000..5c3a02fa1b --- /dev/null +++ b/docs/code-quality/lint/linters/file-perm.rst @@ -0,0 +1,42 @@ +File permission +=============== + +This linter verifies if a file has unnecessary permissions. +If a file has execution permissions (+x), file-perm will +generate a warning. + +It will ignore files starting with ``#!`` for types of files +that typically have shebang lines (such as python, node or +shell scripts). + +This linter does not have any affect on Windows. + + +Run Locally +----------- + +This mozlint linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter file-perm <file paths> + + +Configuration +------------- + +This linter is enabled on the whole code base. + +This job is configured as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_. + +Autofix +------- + +This linter provides a ``--fix`` option. The python script is doing the change itself. + + +Sources +------- + +* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/file-perm.yml>`_ +* `Source <https://searchfox.org/mozilla-central/source/tools/lint/file-perm/__init__.py>`_ diff --git a/docs/code-quality/lint/linters/file-whitespace.rst b/docs/code-quality/lint/linters/file-whitespace.rst new file mode 100644 index 0000000000..201f10d123 --- /dev/null +++ b/docs/code-quality/lint/linters/file-whitespace.rst @@ -0,0 +1,38 @@ +Trailing whitespaces +==================== + +This linter verifies if a file has: + +* unnecessary trailing whitespaces, +* Windows carriage return, +* empty lines at the end of file, +* if file ends with a newline or not + + +Run Locally +----------- + +This mozlint linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter file-whitespace <file paths> + + +Configuration +------------- + +This linter is enabled on most of the code base. + +This job is configured as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_. + +Autofix +------- + +This linter provides a ``--fix`` option. The python script is doing the change itself. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/file-whitespace.yml>` +* :searchfox:`Source <tools/lint/file-whitespace/__init__.py>` diff --git a/docs/code-quality/lint/linters/fluent-lint.rst b/docs/code-quality/lint/linters/fluent-lint.rst new file mode 100644 index 0000000000..809adb4a5e --- /dev/null +++ b/docs/code-quality/lint/linters/fluent-lint.rst @@ -0,0 +1,47 @@ +Fluent Lint +=========== + +Fluent lint is a linter for Fluent files (.ftl). Currently, it includes: + +* Checks for invalid typography in messages (e.g. straight single or double quotes). +* Checks for comments layout. +* Checks for identifiers (minimum length, allowed characters). +* Hard-coded brand names. + + +Run Locally +----------- + +The mozlint integration of fluent-lint can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter fluent-lint <file paths> + +Alternatively, omit the ``--linter fluent-lint`` and run all configured linters, which will include +fluent-lint. + + +Run on Taskcluster +------------------ + +The fluent-lint job shows up as text(fluent) in the linting job. It should run automatically if +changes are made to fluent (ftl) files. + + +Configuration +------------- + +The main configuration file is found in :searchfox:`tools/lint/fluent-lint/exclusions.yml`. This provides +a way of excluding identifiers or files from checking. In general, exclusions are only to be +used for identifiers that are generated programmatically, but unfortunately, there are other +exclusions that are required for historical reasons. In almost all cases, it should *not* be +necessary to add new exclusions to this file. + + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/fluent-lint.yml>` +* :searchfox:`Source <tools/lint/fluent-lint/__init__.py>` +* :searchfox:`Test <tools/lint/test/test_fluent_lint.py>` diff --git a/docs/code-quality/lint/linters/l10n.rst b/docs/code-quality/lint/linters/l10n.rst new file mode 100644 index 0000000000..de4ce990c8 --- /dev/null +++ b/docs/code-quality/lint/linters/l10n.rst @@ -0,0 +1,45 @@ +L10n +==== + +The l10n linter checks for mistakes and problems in the localizable files. +Most of the code lives inside the +`compare-locales <https://pypi.org/project/compare-locales/>`_ +package, and is shipping as the ``moz-l10n-lint`` command. + +The linter checks for fundamental issues like parsing errors, but it also +finds more subtle mistakes like duplicated messages. It also warns if you're +trying to change a string without changing the ID, or to add a string that's +still in use in a stable channel with a different value. + +The warnings on string ID changes get reported on phabricator, but they're +not making the build fail. To find out when to change IDs and when not to, +read the :ref:`Lifecycle & Workflow <Localization>` section in the +localization documentation. + +Run Locally +----------- + +The can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter l10n <file paths> + +Alternatively, omit the ``--linter l10n`` and run all configured linters, which +will include the l10n linter. + + +Updating the Reference +---------------------- + +The linter checks out the cross-channel localization files into your +``.mozbuild`` state directory. By default this is updated automatically after +48 hours. There might be new strings anyway, if you want to ensure an +updated clone, remove the marker file in +``~/.mozbuild/gecko-strings/.hg/l10n_pull_marker``. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/l10n.yml>` +* :searchfox:`Source <tools/lint/python/l10n_lint.py>` diff --git a/docs/code-quality/lint/linters/license.rst b/docs/code-quality/lint/linters/license.rst new file mode 100644 index 0000000000..0533333218 --- /dev/null +++ b/docs/code-quality/lint/linters/license.rst @@ -0,0 +1,39 @@ +License +======= + +This linter verifies if a file has a known license header. + +By default, Firefox uses MPL-2 license with the `appropriate headers <https://www.mozilla.org/en-US/MPL/headers/>`_. +In some cases (thirdpardy code), a file might have a different header file. +If this is the case, one of the significant line of the header should be listed in the list `of valid licenses +<https://searchfox.org/mozilla-central/source/tools/lint/license/valid-licenses.txt>`_. + +Run Locally +----------- + +This mozlint linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter license <file paths> + + +Configuration +------------- + +This linter is enabled on most of the whole code base. + +Autofix +------- + +This linter provides a ``--fix`` option. The python script is doing the change itself +and will use the right header MPL-2 header depending on the language. +It will add the license at the right place in case the file is a script (ie starting with ``!#`` +or a XML file ``<?xml>``). + + +Sources +------- + +* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/license.yml>`_ +* `Source <https://searchfox.org/mozilla-central/source/tools/lint/license/__init__.py>`_ diff --git a/docs/code-quality/lint/linters/lintpref.rst b/docs/code-quality/lint/linters/lintpref.rst new file mode 100644 index 0000000000..ca19089172 --- /dev/null +++ b/docs/code-quality/lint/linters/lintpref.rst @@ -0,0 +1,32 @@ +Lintpref +======== + +The lintpref linter is a simple linter for libpref files to check for duplicate +entries between :searchfox:`modules/libpref/init/all.js` and +:searchfox:`modules/libpref/init/StaticPrefList.yaml`. If a duplicate is found, +lintpref will raise an error and emit the ``all.js`` line where you can find +the duplicate entry. + + +Running Locally +--------------- + +The linter can be run using mach: + + .. parsed-literal:: + + $ mach lint --linter lintpref + + +Fixing Lintpref Errors +---------------------- + +In most cases, duplicate entries should be avoided and the duplicate removed +from ``all.js``. If for any reason a pref should exist in both files, the pref +should be added to ``IGNORE_PREFS`` in :searchfox:`tools/lint/libpref/__init__.py`. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/lintpref.yml>` +* :searchfox:`Source <tools/lint/libpref/__init__.py>` diff --git a/docs/code-quality/lint/linters/mingw-capitalization.rst b/docs/code-quality/lint/linters/mingw-capitalization.rst new file mode 100644 index 0000000000..e6c51a4d14 --- /dev/null +++ b/docs/code-quality/lint/linters/mingw-capitalization.rst @@ -0,0 +1,28 @@ +MinGW capitalization +==================== + +This linter verifies that Windows include file are lowercase. +It might break the mingw build otherwise. + + +Run Locally +----------- + +This mozlint linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter mingw-capitalization <file paths> + + +Configuration +------------- + +This linter is enabled on the whole code base except WebRTC + + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/mingw-capitalization.yml>` +* :searchfox:`Source <tools/lint/cpp/mingw-capitalization.py>` diff --git a/docs/code-quality/lint/linters/perfdocs.rst b/docs/code-quality/lint/linters/perfdocs.rst new file mode 100644 index 0000000000..3169ee553f --- /dev/null +++ b/docs/code-quality/lint/linters/perfdocs.rst @@ -0,0 +1,84 @@ +PerfDocs +======== + +`PerfDocs`_ is a tool that checks to make sure all performance tests are documented in tree. + +At the moment, it is only used for this documentation verification, but in the future it will also auto-generate documentation from these descriptions that will be displayed in the source-docs documentation page (rather than the wiki, which is where they currently reside). + +Run Locally +----------- + +The mozlint integration of PerfDocs can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter perfdocs . + + +Configuration +------------- + +There are no configuration options available for this linter. It scans the full source tree under ``testing``, looking for folders named ``perfdocs`` and then validates their content. This has only been implemented for Raptor so far, but Talos will be added in the future. We also hope to expand this to search outside the ``testing`` directory. + +The ``perfdocs`` folders, there needs to be an ``index.rst`` file and it needs to contain the string ``{documentation}`` in some location in the file which is where the test documentation will be placed. The folders must also have a ``config.yml`` file following this schema: + +.. code-block:: python + + CONFIG_SCHEMA = { + "type": "object", + "properties": { + "name": {"type": "string"}, + "manifest": {"type": "string"}, + "suites": { + "type": "object", + "properties": { + "suite_name": { + "type": "object", + "properties": { + "tests": { + "type": "object", + "properties": { + "test_name": {"type": "string"}, + } + }, + "description": {"type": "string"}, + }, + "required": [ + "description" + ] + } + } + } + }, + "required": [ + "name", + "manifest", + "suites" + ] + } + +Here is an example of a configuration file for the Raptor framework: + +.. parsed-literal:: + + name: raptor + manifest: testing/raptor/raptor/raptor.ini + suites: + desktop: + description: "Desktop tests." + tests: + raptor-tp6: "Raptor TP6 tests." + mobile: + description: "Mobile tests" + benchmarks: + description: "Benchmark tests." + tests: + wasm: "All wasm tests." + +Note that there needs to be a FrameworkGatherer implemented for the framework being documented since each of them may have different ways of parsing test manifests for the tests. See `RaptorGatherer <https://searchfox.org/mozilla-central/source/tools/lint/perfdocs/framework_gatherers.py>`_ for an example gatherer that was implemented for Raptor. + +Sources +------- + +* `Configuration <https://searchfox.org/mozilla-central/source/tools/lint/perfdocs.yml>`__ +* `Source <https://searchfox.org/mozilla-central/source/tools/lint/perfdocs>`__ diff --git a/docs/code-quality/lint/linters/rejected-words.rst b/docs/code-quality/lint/linters/rejected-words.rst new file mode 100644 index 0000000000..9afe7df27e --- /dev/null +++ b/docs/code-quality/lint/linters/rejected-words.rst @@ -0,0 +1,28 @@ +Rejected words +============== + +Reject some words we don't want to use in the code base for various reasons. + +Run Locally +----------- + +The mozlint integration of codespell can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter rejected-words <file paths> + + +Configuration +------------- + +This linter is enabled on the whole code base. Issues existing in the code base +are listed in the exclude list in the :searchfox:`rejected-words.yml +<tools/lint/rejected-words.yml>` file. + +New words can be added in the `payload` section. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/rejected-words.yml>` diff --git a/docs/code-quality/lint/linters/rstlinter.rst b/docs/code-quality/lint/linters/rstlinter.rst new file mode 100644 index 0000000000..46a68d5849 --- /dev/null +++ b/docs/code-quality/lint/linters/rstlinter.rst @@ -0,0 +1,32 @@ +RST Linter +========== + +`rstcheck`_ is a popular linter for restructuredtext. + + +Run Locally +----------- + +The mozlint integration of rst linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter rst <file paths> + + +Configuration +------------- + +All directories will have rst linter run against them. +If you wish to exclude a subdirectory of an included one, you can add it to the ``exclude`` +directive. + + +.. _rstcheck: https://github.com/myint/rstcheck + + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/rst.yml>` +* :searchfox:`Source <tools/lint/rst/__init__.py>` diff --git a/docs/code-quality/lint/linters/ruff.rst b/docs/code-quality/lint/linters/ruff.rst new file mode 100644 index 0000000000..359e8dcbf6 --- /dev/null +++ b/docs/code-quality/lint/linters/ruff.rst @@ -0,0 +1,44 @@ +Ruff +==== + +`Ruff <https://github.com/charliermarsh/ruff>`_ is an extremely fast Python +linter and formatter, written in Rust. It can process all of mozilla-central in +under a second, and implements rule sets from a large array of Python linters +and formatters, including: + +* flake8 (pycodestyle, pyflakes and mccabe) +* isort +* pylint +* pyupgrade +* and many many more! + +Run Locally +----------- + +The mozlint integration of ruff can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter ruff <file paths> + + +Configuration +------------- + +Ruff is configured in the root `pyproject.toml`_ file. Additionally, ruff will +pick up any ``pyproject.toml`` or ``ruff.toml`` files in subdirectories. The +settings in these files will only apply to files contained within these +subdirs. For more details on configuration discovery, see the `configuration +documentation`_. + +For a list of options, see the `settings documentation`_. + +Sources +------- + +* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/ruff.yml>`_ +* `Source <https://searchfox.org/mozilla-central/source/tools/lint/python/ruff.py>`_ + +.. _pyproject.toml: https://searchfox.org/mozilla-central/source/pyproject.toml +.. _configuration documentation: https://beta.ruff.rs/docs/configuration/ +.. _settings documentation: https://beta.ruff.rs/docs/settings/ diff --git a/docs/code-quality/lint/linters/rustfmt.rst b/docs/code-quality/lint/linters/rustfmt.rst new file mode 100644 index 0000000000..eb7e75fa6b --- /dev/null +++ b/docs/code-quality/lint/linters/rustfmt.rst @@ -0,0 +1,33 @@ +Rustfmt +======= + +`rustfmt <https://github.com/rust-lang/rustfmt>`__ is the tool for Rust coding style. + +Run Locally +----------- + +The mozlint integration of rustfmt can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter rustfmt <file paths> + + +Configuration +------------- + +To enable rustfmt on new directory, add the path to the include +section in the :searchfox:`rustfmt.yml <tools/lint/rustfmt.yml>` file. + + +Autofix +------- + +Rustfmt is reformatting the code by default. To highlight the results, we are using +the ``--check`` option. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/rustfmt.yml>` +* :searchfox:`Source <tools/lint/rust/__init__.py>` diff --git a/docs/code-quality/lint/linters/stylelint.rst b/docs/code-quality/lint/linters/stylelint.rst new file mode 100644 index 0000000000..1e8b6c7ff9 --- /dev/null +++ b/docs/code-quality/lint/linters/stylelint.rst @@ -0,0 +1,77 @@ +Stylelint +========= + +`Stylelint`__ is a popular linter for CSS. + +Run Locally +----------- + +The mozlint integration of Stylelint can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter stylelint <file paths> + +Alternatively, omit the ``--linter stylelint`` and run all configured linters, which will include +Stylelint. + +Stylelint also supports the ``--fix`` option to autofix most errors raised from most of the rules. + +See the `Usage guide`_ for more options. + +Understanding Rules and Errors +------------------------------ + +* Only some files are linted, see the :searchfox:`configuration <tools/lint/stylelint.yml>` for details. + + * By design we do not lint/format reftests not crashtests as these are specially crafted tests. + +* If you don't understand a rule, you can look it in `stylelint.io's rule list`_ for more + information about it. + +Common Issues and How To Solve Them +----------------------------------- + +This code should neither be linted nor formatted +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* If it is a third-party piece of code, please add it to :searchfox:`ThirdPartyPaths.txt <tools/rewriting/ThirdPartyPaths.txt>`. +* If it is a generated file, please add it to :searchfox:`Generated.txt <tools/rewriting/Generated.txt>`. +* If intentionally invalid, please add it to :searchfox:`.stylelintignore <.stylelintignore>`. + +Configuration +------------- + +The global configuration file lives in ``topsrcdir/.stylelintrc.js``. +For an overview of the supported configuration, see `Stylelint's documentation`_. + +Please keep differences in rules across the tree to a minimum. We want to be consistent to +make it easier for developers. + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/stylelint.yml>` +* :searchfox:`Source <tools/lint/stylelint/__init__.py>` + +Builders +-------- + +`Gijs Kruitbosch (gijs) <https://people.mozilla.org/s?query=gijs>`__ owns +the builders. Questions can also be asked on #lint:mozilla.org on Matrix. + +Stylelint task +^^^^^^^^^^^^^^ + +This is a tier-1 task. For test failures the patch causing the +issue should be backed out or the issue fixed. + +Some failures can be fixed with ``./mach lint -l stylelint --fix path/to/file``. + +For test harness issues, file bugs in Developer Infrastructure :: Lint and Formatting. + + +.. __: https://stylelint.io/ +.. _Usage guide: ../usage.html +.. _Stylelint's documentation: https://stylelint.io/user-guide/configure/ +.. _stylelint.io's rule list: https://stylelint.io/user-guide/rules/ diff --git a/docs/code-quality/lint/linters/trojan-source.rst b/docs/code-quality/lint/linters/trojan-source.rst new file mode 100644 index 0000000000..250bdd9afe --- /dev/null +++ b/docs/code-quality/lint/linters/trojan-source.rst @@ -0,0 +1,34 @@ +Trojan Source +============= + +This linter verifies if a change is using some invalid unicode. + +The goal of this linter is to identify some potential usage of this +technique: + +https://trojansource.codes/ + +The code is inspired by the Red Hat script published: + +https://access.redhat.com/security/vulnerabilities/RHSB-2021-007#diagnostic-tools + +Run Locally +----------- + +This mozlint linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter trojan-source <file paths> + + +Configuration +------------- + +This linter is enabled on most of the code base on C/C++, Python and Rust. + +Sources +------- + +* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/trojan-source.yml>`_ +* `Source <https://searchfox.org/mozilla-central/source/tools/lint/trojan-source/__init__.py>`_ diff --git a/docs/code-quality/lint/linters/yamllint.rst b/docs/code-quality/lint/linters/yamllint.rst new file mode 100644 index 0000000000..e148a6aace --- /dev/null +++ b/docs/code-quality/lint/linters/yamllint.rst @@ -0,0 +1,31 @@ +yamllint +======== + +`yamllint <https://github.com/adrienverge/yamllint>`__ is a linter for YAML files. + + +Run Locally +----------- + +The mozlint integration of yamllint can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter yaml <file paths> + +Alternatively, omit ``--linter yaml`` to run all configured linters, including +yamllint. + + +Configuration +------------- + +To enable yamllint on a new directory, add the path to the include section in +the :searchfox:`yaml.yml <tools/lint/yaml.yml>` file. + + +Sources +------- + +* :searchfox:`Configuration (YAML) <tools/lint/yaml.yml>` +* :searchfox:`Source <tools/lint/yamllint_/__init__.py>` diff --git a/docs/code-quality/lint/mozlint.rst b/docs/code-quality/lint/mozlint.rst new file mode 100644 index 0000000000..48a6a78a6f --- /dev/null +++ b/docs/code-quality/lint/mozlint.rst @@ -0,0 +1,23 @@ +MozLint +======= + +Linters are used in mozilla-central to help enforce coding style and avoid bad practices. +Due to the wide variety of languages in use, this is not always an easy task. +In addition, linters should be runnable from editors, from the command line, from review tools +and from continuous integration. It's easy to see how the complexity of running all of these +different kinds of linters in all of these different places could quickly balloon out of control. + +``Mozlint`` is a library that accomplishes several goals: + +1. It provides a standard method for adding new linters to the tree, which can be as easy as + defining a config object in a ``.yml`` file. This helps keep lint related code localized, and + prevents different teams from coming up with their own unique lint implementations. +2. It provides a streamlined interface for running all linters at once. Instead of running N + different lint commands to test your patch, a single ``mach lint`` command will automatically run + all applicable linters. This means there is a single API surface that other tools can use to + invoke linters. +3. With a simple taskcluster configuration, Mozlint provides an easy way to execute all these jobs + at review phase. + +``Mozlint`` isn't designed to be used directly by end users. Instead, it can be consumed by things +like mach, phabricator and taskcluster. diff --git a/docs/code-quality/lint/usage.rst b/docs/code-quality/lint/usage.rst new file mode 100644 index 0000000000..d0eb1d5b02 --- /dev/null +++ b/docs/code-quality/lint/usage.rst @@ -0,0 +1,133 @@ +Running Linters Locally +======================= + +Using the Command Line +---------------------- + +You can run all the various linters in the tree using the ``mach lint`` command. Simply pass in the +directory or file you wish to lint (defaults to current working directory): + +.. parsed-literal:: + + ./mach lint path/to/files + +Multiple paths are allowed: + +.. parsed-literal:: + + ./mach lint path/to/foo.js path/to/bar.py path/to/dir + +To force execution on a directory that would otherwise be excluded: + +.. parsed-literal:: + + ./mach lint -n path/in/the/exclude/list + +``Mozlint`` will automatically determine which types of files exist, and which linters need to be run +against them. For example, if the directory contains both JavaScript and Python files then mozlint +will automatically run both ESLint and Flake8 against those files respectively. + +To restrict which linters are invoked manually, pass in ``-l/--linter``: + +.. parsed-literal:: + + ./mach lint -l eslint path/to/files + +You can see a list of the available linters by running: + +.. parsed-literal:: + + ./mach lint --list + +Finally, ``mozlint`` can lint the files touched by outgoing revisions or the working directory using +the ``-o/--outgoing`` and ``-w/--workdir`` arguments respectively. These work both with mercurial and +git. In the case of ``--outgoing``, the default remote repository the changes would be pushed to is +used as the comparison. If desired, a remote can be specified manually. In git, you may only want to +lint staged commits from the working directory, this can be accomplished with ``--workdir=staged``. +Examples: + +.. parsed-literal:: + + ./mach lint --workdir + ./mach lint --workdir=staged + ./mach lint --outgoing + ./mach lint --outgoing origin/master + ./mach lint -wo + +.. _lint-vcs-hook: + +Using a VCS Hook +---------------- + +There are also both pre-commit and pre-push version control hooks that work in +either hg or git. To enable a pre-push hg hook, add the following to hgrc: + +.. parsed-literal:: + + [hooks] + pre-push.lint = python:./tools/lint/hooks.py:hg + + +To enable a pre-commit hg hook, add the following to hgrc: + +.. parsed-literal:: + + [hooks] + pretxncommit.lint = python:./tools/lint/hooks.py:hg + + +To enable a pre-push git hook, run the following command: + +.. parsed-literal:: + + $ ln -s /path/to/gecko/tools/lint/hooks.py .git/hooks/pre-push + + +To enable a pre-commit git hook, run the following command: + +.. parsed-literal:: + + $ ln -s /path/to/gecko/tools/lint/hooks.py .git/hooks/pre-commit + + +Fixing Lint Errors +================== + +``Mozlint`` has a best-effort ability to fix lint errors: + +.. parsed-literal:: + + $ ./mach lint --fix + +Not all linters support fixing, and even the ones that do can not usually fix +all types of errors. Any errors that cannot be automatically fixed, will be +printed to stdout like normal. In that case, you can also fix errors manually: + +.. parsed-literal:: + + $ ./mach lint --edit + +This requires the $EDITOR environment variable be defined. For most editors, +this will simply open each file containing errors one at a time. For vim (or +neovim), this will populate the `quickfix list`_ with the errors. + +The ``--fix`` and ``--edit`` arguments can be combined, in which case any +errors that can be fixed automatically will be, and the rest will be opened +with your $EDITOR. + +Editor Integration +================== + +Editor integrations are highly recommended for linters, as they let you see +errors in real time, and can help you fix issues before you compile or run tests. + +Although mozilla-central does not currently have an integration available for +`./mach lint`, there are various integrations available for some of the major +linting tools that we use: + +* `ESLint`_ +* `Black (Python)`_ + +.. _quickfix list: http://vimdoc.sourceforge.net/htmldoc/quickfix.html +.. _ESLint: https://eslint.org/docs/user-guide/integrations#editors +.. _Black (Python): https://black.readthedocs.io/en/stable/editor_integration.html diff --git a/docs/code-quality/static-analysis/existing.rst b/docs/code-quality/static-analysis/existing.rst new file mode 100644 index 0000000000..81ed79a54f --- /dev/null +++ b/docs/code-quality/static-analysis/existing.rst @@ -0,0 +1,245 @@ +Existing Infrastructure and Analysis +==================================== + +This document is about how Static Analysis occurs at Mozilla: the Firefox-specific and general llvm clang-tidy checks that are run on submissions in Phabricator and how to run them locally. For information about how to develop your own static analysis checks, please see `Writing New Firefox-Specific Checks </code-quality/static-analysis/writing-new/>`_. + +For linting, please see the `linting documentation </code-quality/lint/>`_. + +For reviews, use the `#static-analysis-reviewers review group <https://phabricator.services.mozilla.com/project/view/120/>`__. +Ask questions on `#static-analysis:mozilla.org <https://chat.mozilla.org/#/room/#static-analysis:mozilla.org>`__. + + +Clang-Tidy static analysis +-------------------------- + +As explained earlier, our current static-analysis infrastructure is based on +`clang-tidy <http://clang.llvm.org/extra/clang-tidy/>`__. The checkers that +we use are split into 3 categories: + +#. :searchfox:`Firefox specific checkers <build/clang-plugin>`. They detect incorrect Gecko programming + patterns which could lead to bugs or security issues. +#. `Clang-tidy checkers <https://clang.llvm.org/extra/clang-tidy/checks/list.html>`_. They aim to suggest better programming practices + and to improve memory efficiency and performance. +#. `Clang-analyzer checkers <https://clang-analyzer.llvm.org/>`_. These checks are more advanced, for example + some of them can detect dead code or memory leaks, but as a typical + side effect they have false positives. Because of that, we have + disabled them for now, but will enable some of them in the near + future. + +In order to simplify the process of static-analysis we have focused on +integrating this process with Phabricator and mach. A list of some +checkers that are used during automated scan can be found +:searchfox:`here <tools/clang-tidy/config.yaml>`. + +Static analysis at review phase +------------------------------- + +We created a TaskCluster bot that runs clang static analysis on every +patch submitted to Phabricator. It then quickly reports any code defects +directly on the review platform, thus preventing bad patches from +landing until all their defects are fixed. Currently, its feedback is +posted in about 10 minutes after a patch series is published on the +review platform. + +As part of the process, the various linting jobs are also executed +using try. This can be also used to add new jobs, see: :ref:`attach-job-review`. +An example of automated review can be found `on +phabricator <https://phabricator.services.mozilla.com/D2066>`__. + + +./mach static-analysis +---------------------- + +The ``./mach static-analysis`` command is supported on all Firefox built platforms. During the first run it +automatically installs all of its dependencies, such as the clang-tidy +executable, in the .mozbuild folder thus making it very easy to use. The +resources that are used are provided by toolchain artifacts clang-tidy +target. + +This is used through ``mach static-analysis`` command that has the +following parameters: + +- ``check`` - Runs the checks using the installed helper tool from + ~/.mozbuild. +- ``--checks, -c`` - Checks to enabled during the scan. The checks + enabled + :searchfox:`in the yaml file <tools/clang-tidy/config.yaml>` + are used by default. +- ``--fix, -f`` - Try to autofix errors detected by the checkers. + Depending on the checker, this option might not do anything. + The list of checkers with autofix can be found on the `clang-tidy website <https://clang.llvm.org/extra/clang-tidy/checks/list.html>`__. +- ``--header-filter, -h-f`` - Regular expression matching the names of + the headers to output diagnostic from.Diagnostic from the main file + of each translation unit are always displayed. + +As an example we run static-analysis through mach on +``dom/presentation/Presentation.cpp`` with +``google-readability-braces-around-statements`` check and autofix we +would have: + +.. code-block:: shell + + ./mach static-analysis check --checks="-*, google-readability-braces-around-statements" --fix dom/presentation/Presentation.cpp + +If you want to use a custom clang-tidy binary this can be done by using +the ``install`` subcommand of ``mach static-analysis``, but please note +that the archive that is going to be used must be compatible with the +directory structure clang-tidy from toolchain artifacts. + +.. code-block:: shell + + ./mach static-analysis install clang.tar.gz + + +Regression Testing +------------------ + +In order to prevent regressions in our clang-tidy based static analysis, +we have created a +:searchfox:`task <taskcluster/ci/static-analysis-autotest/kind.yml>` +on automation. This task runs on each commit and launches a test suite +that is integrated into mach. + +The test suite implements the following: + +- Downloads the necessary clang-tidy artifacts. +- Reads the + :searchfox:`configuration <tools/clang-tidy/config.yaml>` + file. +- For each checker reads the test file plus the expected result. A + sample of test and expected result can be found + :searchfox:`in the test file <tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.cpp>` + and + :searchfox:`the json file <tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.json>`. + +This testing suit can be run locally by doing the following: + +.. code-block:: shell + + ./mach static-analysis autotest + +If we want to test only a specific checker, let's say +modernize-raw-string-literal, we can run: + +.. code-block:: shell + + ./mach static-analysis autotest modernize-raw-string-literal + +If we want to add a new checker we need to generated the expected result +file, by doing: + +.. code-block:: shell + + ./mach static-analysis autotest modernize-raw-string-literal -d + + +Build-time static-analysis +-------------------------- + +If you want to build with the Firefox Clang plug-in +(located in ``/build/clang-plugin`` and associated with +``MOZ_CLANG_PLUGIN`` and the attributes in ``/mfbt/Attributes.h``) +just add ``--enable-clang-plugin`` to your mozconfig! +If you want to also have our experimental checkers that will produce ``warnings`` as +diagnostic messages also add ``--enable-clang-plugin-alpha``. +This requires to build Firefox using Clang. + +Configuring the build environment +--------------------------------- + +Once you have your Clang build in place, you will need to set up tools +to use it. +A full working .mozconfig for the desktop browser is: + +.. code-block:: shell + + . $topsrcdir/browser/config/mozconfig + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-dbg + + ac_add_options --enable-debug + +Attempts to use ``ccache`` will likely result in failure to compile. It +is also necessary to avoid optimized builds, as these will modify macros +which will result in many false positives. + +At this point, your Firefox build environment should be configured to +compile via the Clang static analyzer! + + +Performing scanning builds +-------------------------- + +It is not enough to simply start the build like normal. Instead, you +need to run the build through a Clang utility script which will keep +track of all produced analysis and consolidate it automatically. + +Reports are published daily on +`https://sylvestre.ledru.info/reports/fx-scan-build/ <http://sylvestre.ledru.info/reports/fx-scan-build/>`__ +Many of the defects reported as sources for Good First Bug. + +That script is scan-build. You can find it in +``$clang_source/tools/scan-build/scan-build``. + +Try running your build through ``scan-build``: + +.. code-block:: shell + + $ cd /path/to/mozilla/source + + # Blow away your object directory because incremental builds don't make sense + $ rm -rf obj-dir + + # To start the build: + scan-build --show-description ./mach build -v + + # The above should execute without any errors. However, it should take longer than + # normal because all compilation will be executing through Clang's static analyzer, + # which adds overhead. + +If things are working properly, you should see a bunch of console spew, +just like any build. + +The first time you run scan-build, CTRL+C after a few files are +compiled. You should see output like: + +.. code-block:: shell + + scan-build: 3 bugs found. + scan-build: Run 'scan-view /Users/gps/tmp/mcsb/2011-12-15-3' to examine bug reports. + +If you see a message like: + +.. code-block:: shell + + scan-build: Removing directory '/var/folders/s2/zc78dpsx2rz6cpc_21r9g5hr0000gn/T/scan-build-2011-12-15-1' because it contains no reports. + +either no static analysis results were available yet or your environment +is not configured properly. + +By default, ``scan-build`` writes results to a folder in a +pseudo-temporary location. You can control where results go by passing +the ``-o /path/to/output`` arguments to ``scan-build``. + +You may also want to run ``scan-build --help`` to see all the options +available. For example, it is possible to selectively enable and disable +individual analyzers. + + +Analyzing the output +-------------------- + +Once the build has completed, ``scan-build`` will produce a report +summarizing all the findings. This is called ``index.html`` in the +output directory. You can run ``scan-view`` (from +``$clang_source/tools/scan-view/scan-view``) as ``scan-build's`` output +suggests; this merely fires up a local HTTP server. Or you should be +able to open the ``index.html`` directly with your browser. + + +False positives +--------------- + +By definition, there are currently false positives in the static +analyzer. A lot of these are due to the analyzer having difficulties +following the relatively complicated error handling in various +preprocessor macros. diff --git a/docs/code-quality/static-analysis/index.rst b/docs/code-quality/static-analysis/index.rst new file mode 100644 index 0000000000..595eab363d --- /dev/null +++ b/docs/code-quality/static-analysis/index.rst @@ -0,0 +1,30 @@ +Static Analysis +=============== + +Static Analysis is running an analysis of the source code without actually executing the code. For the most part, at Mozilla static analysis refers to the stuff we do with `clang-tidy <http://clang.llvm.org/extra/clang-tidy/>`__. It uses +checkers in order to prevent different programming errors present in the +code. The checkers that we use are split into 3 categories: + +#. :searchfox:`Firefox specific checkers <build/clang-plugin>`. They detect incorrect Gecko programming + patterns which could lead to bugs or security issues. +#. `Clang-tidy checkers <https://clang.llvm.org/extra/clang-tidy/checks/list.html>`_. They aim to suggest better programming practices + and to improve memory efficiency and performance. +#. `Clang-analyzer checkers <https://clang-analyzer.llvm.org/>`_. These checks are more advanced, for example + some of them can detect dead code or memory leaks, but as a typical + side effect they have false positives. Because of that, we have + disabled them for now, but will enable some of them in the near + future. + +In order to simplify the process of static-analysis we have focused on +integrating this process with Phabricator and mach. A list of some +checkers that are used during automated scan can be found +:searchfox:`here <tools/clang-tidy/config.yaml>`. + +This documentation is split into two parts: + +.. toctree:: + :maxdepth: 1 + :glob: + + existing.rst + writing-new/index.rst diff --git a/docs/code-quality/static-analysis/writing-new/adding-a-check.rst b/docs/code-quality/static-analysis/writing-new/adding-a-check.rst new file mode 100644 index 0000000000..ec3bc030af --- /dev/null +++ b/docs/code-quality/static-analysis/writing-new/adding-a-check.rst @@ -0,0 +1,107 @@ +.. _add_a_check: + +Adding a check +============== + +After you've completed a matcher using clang-query, it's time to take it to the next step and turn it into C++ and run it on the whole m-c codebase and see what happens. + +Clang plugins live in `build/clang-plugin <https://searchfox.org/mozilla-central/source/build/clang-plugin>`_ and here we'll cover what is needed to add one. To see how the most recent check was added, you can look at the log for `Checks.inc <https://hg.mozilla.org/mozilla-central/log/tip/build/clang-plugin/Checks.inc>`_ which is one of the necessary files to edit. That's also what we'll be covering next. + +Boilerplate Steps to Add a New Check +------------------------------------ + +First pick a name. Pick something that makes sense without punctuation, in no more than 8 words or so. For this example we'll call it "Missing Else In Enum Comparisons". + +#. Add it alphabetically in build/clang-plugin/Checks.inc, ChecksIncludes.inc, and moz.build +#. ``cd build/clang-plugin && touch MissingElseInEnumComparisons.h MissingElseInEnumComparisons.cpp`` +#. Copy the contents of an existing, simple .h file (e.g. `build/clang-plugin/ScopeChecker.h <https://searchfox.org/mozilla-central/source/build/clang-plugin/ScopeChecker.h>`_) and edit the class name and header guards. +#. Create the following boilerplate for your implementation: + +:: + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "MissingElseInEnumComparisons.h" + #include "CustomMatchers.h" + + void MissingElseInEnumComparisons::registerMatchers(MatchFinder *AstMatcher) { + + } + + void MissingElseInEnumComparisons::check(const MatchFinder::MatchResult &Result) { + + } + + +Converting your matcher to C++ +------------------------------ +With the boilerplate out of the way, now we can focus on converting the matcher over to C++. Once it's in C++ you'll also be able to take advantage of techniques that will make your matcher easier to read and understand. + +The gist of converting your matcher is to take the following pseudo-code and paste your entire matcher in where 'foo' is; keeping the `.bind("node")` there: + +:: + + AstMatcher->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + foo + .bind("node")), + this); + + +It honest to god is usually that easy. Here's a working example where I pasted in straight from Compiler Explorer: + +:: + + AstMatcher->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + ifStmt(allOf( + has( + binaryOperator( + has( + declRefExpr(hasType(enumDecl().bind("enum"))) + ) + ) + ), + hasElse( + ifStmt(allOf( + unless(hasElse(anything())), + has( + binaryOperator( + has( + declRefExpr(hasType(enumDecl())) + ) + ) + ) + )) + ) + )) + .bind("node")), + this); + + + +If for some reason you're not using the ``IgnoreUnlessSpelledInSource`` Traversal Mode, remove the call to traverse and the corresponding closing paren. (Also, if you're comparing this code to existing source code, know that because this traversal mode is a new clang feature, most historical clang checks do not use it.) + +Wiring up Warnings and Errors +----------------------------- +To get started with a some simple output, just take the boilerplate warning here and stick it in: + +:: + + const auto *MatchedDecl = Result.Nodes.getNodeAs<IfStmt>("node"); + diag(MatchedDecl->getIfLoc(), + "Enum comparisons in an if/else if block without a trailing else.", + DiagnosticIDs::Warning); + + +You'll need to edit two things: + +#. Make sure "node" matches whatever you put in `.bind()` up above. +#. ``getNodeAs<IfStmt>`` needs to be changed to whatever type of element "node" is. Above, we bind "node" to an ifStmt so that's what we need to cast it to. Doing this step incorrectly will cause clang to crash during compilation as if there was some internal compiler error. + + +Running it on Central +---------------------- +After this, the next thing to do is to add ``ac_add_options --enable-clang-plugin`` to your .mozconfig and do a build. Your plugin will be automatically compiled and used across the entire codebase. I suggest using ``./mach build | tee output.txt`` and then ``grep "Enum comparisons" output.txt | cut -d " " -f 3- | sort | uniq``. (The ``cut`` is there to get rid of the timestamp in the line.) diff --git a/docs/code-quality/static-analysis/writing-new/advanced-check-features.rst b/docs/code-quality/static-analysis/writing-new/advanced-check-features.rst new file mode 100644 index 0000000000..e8adcf664f --- /dev/null +++ b/docs/code-quality/static-analysis/writing-new/advanced-check-features.rst @@ -0,0 +1,148 @@ +.. _advanced_check_features: + +Advanced Check Features +======================= + +This page covers additional ways to improve and extend the check you've added to build/clang-plugin. + +Adding Tests +------------ + +No doubt you've seen the tests for existing checks in `build/clang-plugin/tests <https://searchfox.org/mozilla-central/source/build/clang-plugin/tests>`_. Adding tests is straightforward; and your reviewer should insist you do so. Simply copying the existing format of any test and how diagnostics are marked as expected. + +One wrinkle - all clang plugin checks are applied to all tests. We try to write tests so that only one check applies to it. If you write a check that triggers on an existing test, try to fix the existing test slightly so the new check does not trigger on it. + +Using Bind To Output More Useful Information +-------------------------------------------- + +You've probably been wondering what the heck ``.bind()`` is for. You've been seeing it all over the place but never has it actually been explained what it's for and when to use it. + +``.bind()`` is used to give a name to part of the AST discovered through your matcher, so you can use it later. Let's go back to our sample matcher: + +:: + + AstMatcher->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + ifStmt(allOf( + has( + binaryOperator( + has( + declRefExpr(hasType(enumDecl())) + ) + ) + ), + hasElse( + ifStmt(allOf( + unless(hasElse(anything())), + has( + binaryOperator( + has( + declRefExpr(hasType(enumDecl())) + ) + ) + ) + )) + ) + )) + .bind("node")), + this); + +Now the ``.bind("node")`` makes more sense. We're naming the If statement we matched, so we can refer to it later when we call ``Result.Nodes.getNodeAs<IfStmt>("node")``. + +Let's say we want to provide the *type* of the enum in our warning message. There are two enums we end up seeing in our matcher - the enum in the first if statement, and the enum in the second. We're going to arbitrarily pick the first and give it the name ``enumType``: + +:: + + AstMatcher->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + ifStmt(allOf( + has( + binaryOperator( + has( + declRefExpr(hasType(enumDecl().bind("enumType"))) + ) + ) + ), + hasElse( + ifStmt(allOf( + unless(hasElse(anything())), + has( + binaryOperator( + has( + declRefExpr(hasType(enumDecl())) + ) + ) + ) + )) + ) + )) + .bind("node")), + this); + +And in our check() function, we can use it like so: + +:: + + void MissingElseInEnumComparisons::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs<IfStmt>("node"); + const auto *EnumType = Result.Nodes.getNodeAs<EnumDecl>("enumType"); + + diag(MatchedDecl->getIfLoc(), + "Enum comparisons to %0 in an if/else if block without a trailing else.", + DiagnosticIDs::Warning) << EnumType->getName(); + } + +Repeated matcher calls +-------------------------- + +If you find yourself repeating the same several matchers in several spots, you can turn it into a variable to use. + +:: + + auto isTemporaryLifetimeBoundCall = + cxxMemberCallExpr( + onImplicitObjectArgument(anyOf(has(cxxTemporaryObjectExpr()), + has(materializeTemporaryExpr()))), + callee(functionDecl(isMozTemporaryLifetimeBound()))); + + auto hasTemporaryLifetimeBoundCall = + anyOf(isTemporaryLifetimeBoundCall, + conditionalOperator( + anyOf(hasFalseExpression(isTemporaryLifetimeBoundCall), + hasTrueExpression(isTemporaryLifetimeBoundCall)))); + +The above example is parameter-less, but if you need to supply a parameter that changes, you can turn it into a lambda: + +:: + + auto hasConstCharPtrParam = [](const unsigned int Position) { + return hasParameter( + Position, hasType(hasCanonicalType(pointsTo(asString("const char"))))); + }; + + auto hasParamOfType = [](const unsigned int Position, const char *Name) { + return hasParameter(Position, hasType(asString(Name))); + }; + + auto hasIntegerParam = [](const unsigned int Position) { + return hasParameter(Position, hasType(isInteger())); + }; + + AstMatcher->addMatcher( + callExpr( + hasName("fopen"), + hasConstCharPtrParam(0)) + .bind("funcCall"), + this); + + +Allow-listing existing callsites +-------------------------------- + +While it's not a great situation, you can set up an allow-list of existing callsites if you need to. A simple allow-list is demonstrated in `NoGetPrincipalURI <https://hg.mozilla.org/mozilla-central/rev/fb60b22ee6616521b386d90aec07b03b77905f4e>`_. The `NoNewThreadsChecker <https://hg.mozilla.org/mozilla-central/rev/f400f164b3947b4dd54089a36ea31cca2d72805b>`_ is an example of a more sophisticated way of setting up a larger allow-list. + + +Custom Annotations +------------------ +It's possible to create custom annotations that will be a no-op when compiled, but can be used by a static analysis check. These can be used to annotate special types of sources and sinks (for example). We have some examples of this in-tree presently (such as ``MOZ_CAN_RUN_SCRIPT``) but currently don't have a detailed walkthrough in this documentation of how to set these up and use them. (Patches welcome.) diff --git a/docs/code-quality/static-analysis/writing-new/clang-query.rst b/docs/code-quality/static-analysis/writing-new/clang-query.rst new file mode 100644 index 0000000000..1308a32821 --- /dev/null +++ b/docs/code-quality/static-analysis/writing-new/clang-query.rst @@ -0,0 +1,167 @@ +.. _using_clang_query: + +Using clang-query +================= + +clang-query is a tool that allows you to quickly iterate and develop the difficult part of a matcher. +Once the design of the matcher is completed, it can be transferred to a C++ clang-tidy plugin, `similar +to the ones in mozilla-central <https://searchfox.org/mozilla-central/source/build/clang-plugin>`_. + +Recommended Boilerplate +----------------------- + +:: + + set traversal IgnoreUnlessSpelledInSource + set bind-root true + # ^ true unless you use any .bind("foo") commands + set print-matcher true + enable output dump + + +clang-query Options +------------------- + +set traversal +~~~~~~~~~~~~~ + +`Traversal mode <https://clang.llvm.org/docs/LibASTMatchersReference.html#traverse-mode>`_ specifies how the AST Matcher will traverse the nodes in the Abstract Syntax Tree. There are two values: + +AsIs + This mode notes all the nodes in the AST, even if they are not explicitly spelled out in the source. This will include nodes you have never seen and probably don't immediately understand, for example ``ExprWithCleanups`` and ``MaterializeTemporaryExpr``. In this mode, it is necessary to write matchers that expliticly match or otherwise traverse these potentially unexpected nodes. + +IgnoreUnlessSpelledInSource + This mode skips over 'implicit' nodes that are created as a result of implicit casts or other usually-low-level language details. This is typically much more user-friendly. **Typically you would want to use** ``set traversal IgnoreUnlessSpelledInSource``. + +More examples are available `in the documentation <https://clang.llvm.org/docs/LibASTMatchersReference.html#traverse-mode>`_, but here is a simple example: + +:: + + B func1() { + return 42; + } + + /* + AST Dump in 'Asis' mode for C++17/C++20 dialect: + + FunctionDecl + `-CompoundStmt + `-ReturnStmt + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 + + AST Dump in 'IgnoreUnlessSpelledInSource' mode for all dialects: + + FunctionDecl + `-CompoundStmt + `-ReturnStmt + `-IntegerLiteral 'int' 42 + */ + + +set bind-root +~~~~~~~~~~~~~ + +If you are matching objects and assigning them names for later use, this option may be relevant. If you are debugging a single matcher and not using any ``.bind()``, it is irrelevant. + +Consider the output of ``match functionDecl().bind("x")``: + +:: + + clang-query> match functionDecl().bind("x") + + Match #1: + + testfile.cpp:1:1: note: "root" binds here + int addTwo(int num) + ^~~~~~~~~~~~~~~~~~~ + testfile.cpp:1:1: note: "x" binds here + int addTwo(int num) + ^~~~~~~~~~~~~~~~~~~ + + Match #2: + + testfile.cpp:6:1: note: "root" binds here + int main(int, char**) + ^~~~~~~~~~~~~~~~~~~~~ + testfile.cpp:6:1: note: "x" binds here + int main(int, char**) + ^~~~~~~~~~~~~~~~~~~~~ + 2 matches. + + +clang-query automatically binds ``root`` to the match, but we also bound the name ``x`` to that match. The ``root`` is redundant. If you ``set bind-root false`` then the output is less noisy: + +:: + + clang-query> set bind-root false + clang-query> m functionDecl().bind("x") + + Match #1: + + testfile.cpp:1:1: note: "x" binds here + int addtwo(int num) + ^~~~~~~~~~~~~~~~~~~ + + Match #2: + + testfile.cpp:6:1: note: "x" binds here + int main(int, char**) + ^~~~~~~~~~~~~~~~~~~~~ + 2 matches. + + +set print-matcher +~~~~~~~~~~~~~~~~~ + +``set print-matcher true`` will print a header line of the form 'Matcher: <foo>' where foo is the matcher you have written. It is helpful when debugging multiple matchers at the same time, and no inconvience otherwise. + +enable/disable/set output <foo> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These commands will control the type of output you get from clang-query. The options are: + +``print`` + Shows you the C++ form of the node you are matching. This is typically not useful. + +``diag`` + Shows you the individual node you are matching. + +``dump`` (alias: ``detailed-ast``) + Shows you the node you are matching and the entire subtree for the node + +By default, you get ``diag`` output. You can change the output by choosing ``set output``. You can *add* output by using ``enable output``. You can *disable* output using ``disable output`` but this is typically not needed. + +So if you want to get all three output formats you can do: + +:: + + # diag output happens automatically because you did not override with 'set' + enable output print + enable output dump + + +Patches +------- + +This section tracks some patches; they are currently not used, but we may want them in the future. + +- Functionality: + + - `traverse() operator available to clang-query <https://reviews.llvm.org/D80654>`_ + - `srclog output <https://reviews.llvm.org/D93325>`_ + - `allow anyOf() to be empty <https://reviews.llvm.org/D94126>`_ + - breakpoints + - debug + - profile + +- Matcher Changes: + + - `binaryOperation() matcher <https://reviews.llvm.org/D94129>`_ + +- Plumbing: + + - `mapAnyOf() <https://reviews.llvm.org/D94127>`_ (`Example of usage <https://reviews.llvm.org/D94131>`_) + - `Make cxxOperatorCallExpr matchers API-compatible with n-ary operators <https://reviews.llvm.org/D94128>`_ + - `CXXRewrittenBinaryOperator <https://reviews.llvm.org/D94130>`_ diff --git a/docs/code-quality/static-analysis/writing-new/documentation-expanded.png b/docs/code-quality/static-analysis/writing-new/documentation-expanded.png new file mode 100644 index 0000000000..82f12a516d Binary files /dev/null and b/docs/code-quality/static-analysis/writing-new/documentation-expanded.png differ diff --git a/docs/code-quality/static-analysis/writing-new/index.rst b/docs/code-quality/static-analysis/writing-new/index.rst new file mode 100644 index 0000000000..9107fb1b59 --- /dev/null +++ b/docs/code-quality/static-analysis/writing-new/index.rst @@ -0,0 +1,14 @@ +Writing New Firefox-Specific Static Analysis Checks +=================================================== + +This section is intended to help Mozilla engineers either casually play with writing a static analysis check +or seriously develop one we can land and run internally. While being written for internal consumption, it's broadly applicable outside Mozilla. + +.. toctree:: + :maxdepth: 2 + + clang-query.rst + writing-matchers.rst + matcher-cookbook.rst + adding-a-check.rst + advanced-check-features.rst diff --git a/docs/code-quality/static-analysis/writing-new/matcher-cookbook.rst b/docs/code-quality/static-analysis/writing-new/matcher-cookbook.rst new file mode 100644 index 0000000000..9eb0d96c43 --- /dev/null +++ b/docs/code-quality/static-analysis/writing-new/matcher-cookbook.rst @@ -0,0 +1,23 @@ +.. _matcher_cookbook: + +Matcher Cookbook +================= + +This page is designed to be a selection of common ingredients to a more complicated matcher. + +.. list-table:: + :widths: 35 65 + :header-rows: 1 + :class: matcher-cookbook + + * - Desired Outcome + - Syntax + * - Ignore header files + + *If you have an #include in your example code, your matcher may match things in the header files.* + - Add **isExpansionInMainFile()** to the matcher. e.g. + + ``m functionDecl(isExpansionInMainFile())`` + + +*More coming* diff --git a/docs/code-quality/static-analysis/writing-new/narrowing-matcher.png b/docs/code-quality/static-analysis/writing-new/narrowing-matcher.png new file mode 100644 index 0000000000..52c82791d3 Binary files /dev/null and b/docs/code-quality/static-analysis/writing-new/narrowing-matcher.png differ diff --git a/docs/code-quality/static-analysis/writing-new/narrowing-matcher.xcf b/docs/code-quality/static-analysis/writing-new/narrowing-matcher.xcf new file mode 100644 index 0000000000..0102f79e76 Binary files /dev/null and b/docs/code-quality/static-analysis/writing-new/narrowing-matcher.xcf differ diff --git a/docs/code-quality/static-analysis/writing-new/writing-matchers.rst b/docs/code-quality/static-analysis/writing-new/writing-matchers.rst new file mode 100644 index 0000000000..5b693f5f27 --- /dev/null +++ b/docs/code-quality/static-analysis/writing-new/writing-matchers.rst @@ -0,0 +1,199 @@ +.. _writing_matchers: + +Writing Matchers +================ + +On this page we will give some information about what a matcher is, and then provide an example of developing a simple match iteratively. + +Types of Matchers +----------------- + +There are three types of matches: Node, Narrowing, and Traversal. There isn't always a clear separation or distinction between them, so treat this explanation as illustrative rather than definitive. Here is the documentation on matchers: `https://clang.llvm.org/docs/LibASTMatchersReference.html <https://clang.llvm.org/docs/LibASTMatchersReference.html>`_ + +On that page it is not obvious, so we want to note, **cicking on the name of a matcher expands help about that matcher.** Example: + +.. image:: documentation-expanded.png + +Node Matchers +~~~~~~~~~~~~~ + +Node matchers can be thought of as 'Nouns'. They specify a **type** of node you want to match, that is, a particular *thing*. A function, a binary operation, a variable, a type. + +A full list of `node matchers are listed in the documentation <https://clang.llvm.org/docs/LibASTMatchersReference.html#node-matchers>`_. Some common ones are ``functionDecl()``, ``binaryOperator()``, and ``stmt()``. + +Narrowing Matchers +~~~~~~~~~~~~~~~~~~ + +Narrowing matchers can be thought of as 'Adjectives'. They narrow, or describe, a node, and therefore must be applied to a Node Matcher. For instance a node matcher may be a ``functionDecl``, and the narrowing matcher applied to it may be ``parameterCountIs``. + +The `table in the documentation <https://clang.llvm.org/docs/LibASTMatchersReference.html#narrowing-matchers>`_ lists all the narrowing matchers, which they apply to and how to use them. Here is how to read the table: + +.. image:: narrowing-matcher.png + +And some examples: + +:: + + m functionDecl(parameterCountIs(1)) + m functionDecl(anyOf(isDefinition(), isVariadic())) + + +As you can see **only one Narrowing Matcher is allowed** and it goes inside the parens of the Node Matcher. In the first example, the matcher is ``parameterCountIs``, in the second it is ``anyOf``. + +In the second, we use the singular ``anyOf`` matcher to match any of multiple other Narrowing Matchers: ``isDefinition`` or ``isVariadic``. The other two common combining narrowing matchers are ``allOf()`` and ``unless()``. + +If you *need* to specify a narrowing matcher (because it's a required argument to some other matcher), you can use the ``anything()`` narrowing matcher to have a no-op narrowing matcher. + +Traversal Matchers +~~~~~~~~~~~~~~~~~~ + +Traversal Matchers *also* can be thought of as adjectives - at least most of them. They also describe a specific node, but the difference from a narrowing matcher is that the scope of the description is broader than the individual node. A narrowing matcher says something about the node in isolation (e.g. the number of arguments it has) while a traversal matcher says something about the node's contents or place in the program. + +Again, the `the documentation <https://clang.llvm.org/docs/LibASTMatchersReference.html#traversal-matchers>`_ is the best place to explore and understand these, but here is a simple example for the traversal matcher ``hasArraySize()``: + +:: + + Given: + class MyClass { }; + MyClass *p1 = new MyClass[10]; + + + cxxNewExpr() + matches the expression 'new MyClass[10]'. + + cxxNewExpr(hasArraySize(integerLiteral(equals(9)))) + does not match anything + + cxxNewExpr(hasArraySize(integerLiteral(equals(10)))) + matches the expression 'new MyClass[10]'. + + + +Example of Iterative Matcher Development +---------------------------------------- + +When developing matchers, it will be much easier if you do the following: + +1. Write out the code you want to match. Write it out in as many different ways as you can. Examples: For some value in the code use a variable, a constant and a function that returns a value. Put the code you want to match inside of a function, inside of a conditional, inside of a function call, and inside of an inline function definition. +2. Write out the code you *don't* want to match, but looks like code you do. Write out benign function calls, benign assignments, etc. +3. Iterate on your matcher and treat it as _code_ you're writing. Indent it, copy it somewhere in case your browser crashes, even stick it in a tiny temporary version-controlled file. + +As an example of the above, below is a sample iterative development process of a more complicated matcher. + + **Goal**: Match function calls where one of the parameters is an assignment expression with an integer literal, but the function parameter has a default value in the function definition. + +:: + + int add1(int a, int b) { return a + b; } + int add2(int c, int d = 8) { return c + d; } + + int main() { + int x, y, z; + + add1(x, y); // <- No match, no assignment + add1(3 + 4, y); // <- No match, no assignment + add1(z = x, y); // <- No match, assignment, but not an integer literal + add1(z = 2, y); // <- No match, assignment, integer literal, but function parameter lacks default value + add2(3, z = 2); // <- Match + } + + +Here is the iterative development process: + +:: + + //------------------------------------- + // Step 1: Find all the function calls + m callExpr() + // Matches all calls, as expected. + + //------------------------------------- + // Step 2: Start refining based on the arguments to the call + m callExpr(forEachArgumentWithParam())) + // Error: forEachArgumentWithParam expects two parameters + + //------------------------------------- + // Step 3: Figure out the syntax to matching all the calls with this new operator + m callExpr( + forEachArgumentWithParam( + anything(), + anything() + ) + ) + // Matches all calls, as expected + + //------------------------------------- + // Step 4: Find the calls with a binary operator of any kind + m callExpr( + forEachArgumentWithParam( + binaryOperator(), + anything() + ) + ) + // Does not match the first call, but matches the others + + //------------------------------------- + // Step 5: Limit the binary operator to assignments + m callExpr( + forEachArgumentWithParam( + binaryOperator(isAssignmentOperator()), + anything() + ) + ) + // Now matches the final three calls + + //------------------------------------- + // Step 6: Starting to refine matching the right-hand of the assignment + m callExpr( + forEachArgumentWithParam( + binaryOperator( + allOf( + isAssignmentOperator(), + hasRHS() + )), + anything() + ) + ) + // Error, hasRHS expects a parameter + + //------------------------------------- + // Step 7: + m callExpr( + forEachArgumentWithParam( + binaryOperator( + allOf( + isAssignmentOperator(), + hasRHS(anything()) + )), + anything() + ) + ) + // Okay, back to matching the final three calls + + //------------------------------------- + // Step 8: Refine to just integer literals + m callExpr( + forEachArgumentWithParam( + binaryOperator( + allOf( + isAssignmentOperator(), + hasRHS(integerLiteral()) + )), + anything() + ) + ) + // Now we match the final two calls + + //------------------------------------- + // Step 9: Apply a restriction to the parameter definition + m callExpr( + forEachArgumentWithParam( + binaryOperator( + allOf( + isAssignmentOperator(), + hasRHS(integerLiteral()) + )), + hasDefaultArgument() + ) + ) + // Now we match the final call diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000000..cf2205a7a6 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,152 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import sys + +# Set up Python environment to load build system packages. +OUR_DIR = os.path.dirname(__file__) +topsrcdir = os.path.normpath(os.path.join(OUR_DIR, "..")) + +# Escapes $, [, ] and 3 dots in copy button +copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " +copybutton_prompt_is_regexp = True + +EXTRA_PATHS = ( + "layout/tools/reftest", + "python/mach", + "python/mozbuild", + "python/mozversioncontrol", + "testing/mozbase/manifestparser", + "testing/mozbase/mozfile", + "testing/mozbase/mozprocess", + "testing/mozbase/moznetwork/moznetwork", + "third_party/python/jsmin", + "third_party/python/which", + "docs/_addons", + "taskcluster/gecko_taskgraph/test", +) + +sys.path[:0] = [os.path.join(topsrcdir, p) for p in EXTRA_PATHS] + +sys.path.insert(0, OUR_DIR) + +extensions = [ + "myst_parser", + "sphinx.ext.autodoc", + "sphinx.ext.autosectionlabel", + "sphinx.ext.doctest", + "sphinx.ext.graphviz", + "sphinx.ext.napoleon", + "sphinx.ext.todo", + "mozbuild.sphinx", + "sphinx_js", + "sphinxcontrib.mermaid", + "sphinx_copybutton", + "sphinx_markdown_tables", + "sphinx_design", + "bzlink", +] + +# JSDoc must run successfully for dirs specified, so running +# tree-wide (the default) will not work currently. +# When adding more paths to this list, please ensure that they are not +# excluded from valid-jsdoc in the top-level .eslintrc.js. +js_source_path = [ + "../browser/components/extensions", + "../browser/components/migration", + "../browser/components/migration/content", + "../browser/components/uitour", + "../browser/components/urlbar", + "../remote/marionette", + "../testing/mochitest/BrowserTestUtils", + "../testing/mochitest/tests/SimpleTest/SimpleTest.js", + "../testing/mochitest/tests/SimpleTest/EventUtils.js", + "../testing/modules/Assert.sys.mjs", + "../testing/modules/TestUtils.sys.mjs", + "../toolkit/actors", + "../toolkit/components/extensions", + "../toolkit/components/extensions/parent", + "../toolkit/components/featuregates", + "../toolkit/mozapps/extensions", + "../toolkit/components/prompts/src", + "../toolkit/components/pictureinpicture", + "../toolkit/components/pictureinpicture/content", + "../toolkit/components/search", +] +root_for_relative_js_paths = ".." +jsdoc_config_path = "jsdoc.json" + +templates_path = ["_templates"] +source_suffix = [".rst", ".md"] +master_doc = "index" +project = "Firefox Source Docs" + +# Override the search box to use Google instead of +# sphinx search on firefox-source-docs.mozilla.org +if ( + os.environ.get("MOZ_SOURCE_DOCS_USE_GOOGLE") == "1" + and os.environ.get("MOZ_SCM_LEVEL") == "3" +): + templates_path.append("_search_template") + +html_sidebars = { + "**": [ + "searchbox.html", + ] +} +html_logo = os.path.join( + topsrcdir, "browser/branding/nightly/content/firefox-wordmark.svg" +) +html_favicon = os.path.join(topsrcdir, "browser/branding/nightly/firefox.ico") + +exclude_patterns = ["_build", "_staging", "_venv", "**security/nss/legacy/**"] +pygments_style = "sphinx" +# generate label “slugs” for header anchors so that +# we can reference them from markdown links. +myst_heading_anchors = 5 + +# We need to perform some adjustment of the settings and environment +# when running on Read The Docs. +on_rtd = os.environ.get("READTHEDOCS", None) == "True" + +if on_rtd: + # SHELL isn't set on RTD and mach.mixin.process's import raises if a + # shell-related environment variable can't be found. Set the variable here + # to hack us into working on RTD. + assert "SHELL" not in os.environ + os.environ["SHELL"] = "/bin/bash" +else: + # We only need to set the RTD theme when not on RTD because the RTD + # environment handles this otherwise. + import sphinx_rtd_theme + + html_theme = "sphinx_rtd_theme" + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + + +html_static_path = ["_static"] +htmlhelp_basename = "FirefoxTreeDocs" + +moz_project_name = "main" + +html_show_copyright = False + +# Only run autosection for the page title. +# Otherwise, we have a huge number of duplicate links. +# For example, the page https://firefox-source-docs.mozilla.org/code-quality/lint/ +# is called "Linting" +# just like https://firefox-source-docs.mozilla.org/remote/CodeStyle.html +autosectionlabel_maxdepth = 1 + + +def install_sphinx_design(app, pagename, templatename, context, doctree): + if "perfdocs" in pagename: + app.add_js_file("sphinx_design.js") + app.add_css_file("sphinx_design.css") + + +def setup(app): + app.add_css_file("custom_theme.css") + app.connect("html-page-context", install_sphinx_design) diff --git a/docs/config.yml b/docs/config.yml new file mode 100644 index 0000000000..f2589fdc2e --- /dev/null +++ b/docs/config.yml @@ -0,0 +1,115 @@ +--- + +# The order of the main categories are defined in index.rst +# Sub categories orders are preserved +categories: + setup_doc: + - setup + contributing_doc: + - contributing + - bug-mgmt + user_guide: + - devtools-user + source_doc: + - mots + - browser + - dom + - editor + - layout + - gfx + - ipc + - devtools + - toolkit + - js + - mobile/android/geckoview + - dom/bindings/webidl + - modules/libpref + - networking + - remote + - services + - uriloader + - widget/cocoa + - widget/windows + - accessible + - code-quality + - writing-rust-code + - tools/profiler + - performance + - xpcom + - nspr + - security/nss + build_doc: + - mach + - tools/try + - build/buildsystem + - taskcluster + - tools/moztreedocs + testing_doc: + - testing/automated-testing + - testing/tests-for-new-config + - testing/intermittent + - testing/testing-policy + - testing/ci-configs + - testing/browser-chrome + - testing/chrome-tests + - testing/marionette + - testing/geckodriver + - testing/test-verification + - testing/webrender + - testing/mochitest-plain + - testing/xpcshell + - web-platform + - gtest + - tools/fuzzing + - tools/sanitizer + - testing/perfdocs + - tools/code-coverage + - testing-rust-code + release_doc: + - update-infrastructure + l10n_doc: + - intl + - l10n + python_doc: + - mozbase + - python + fennec_doc: + - mobile/android + metrics_doc: + - metrics + +redirects: + browser/browser: browser + contributing/how_to_contribute_firefox.html: contributing/contribution_quickref.html + contributing/artifact_builds.html: contributing/build/artifact_builds.html + contributing/linux_build.html: setup/linux_build.html + contributing/build/linux_build.html: setup/linux_build.html + contributing/mercurial.html: contributing/vcs/mercurial.html + contributing/mercurial_bundles.html: contributing/vcs/mercurial_bundles.html + contributing/vscode.html: contributing/editors/vscode.html + dom/dom: dom + layout/layout: layout + gfx/gfx: gfx + intl/l10n/l10n: l10n + ipc/ipc: ipc + modules/libpref/libpref: modules/libpref + python/mach: mach + python/python: python + setup/getting_set_up.html: contributing/contributing_to_mozilla.html + taskcluster/taskcluster: taskcluster + testing/geckodriver/geckodriver: testing/geckodriver + testing/marionette/marionette: testing/marionette + toolkit/components/telemetry/telemetry: toolkit/components/telemetry + tools/compare-locales/index.html: build/buildsystem/locales.html + tools/docs/index.html: tools/moztreedocs/index.html + tools/docs/contribute/how_to_contribute_firefox.html: contributing/how_to_contribute_firefox.html + tools/docs/contribute/directory_structure.html: contributing/directory_structure.html + tools/lint: code-quality/lint + tools/lint/coding-style: code-quality/coding-style + tools/static-analysis/index.html: code-quality/static-analysis.html + xpcom/xpcom: xpcom + +fatal warnings: + - "WARNING: '([^']*)' reference target not found:((?!.rst).)*$" + +max_num_warnings: 861 diff --git a/docs/contributing/Code_Review_FAQ.rst b/docs/contributing/Code_Review_FAQ.rst new file mode 100644 index 0000000000..18fe85a6e2 --- /dev/null +++ b/docs/contributing/Code_Review_FAQ.rst @@ -0,0 +1,93 @@ +Code Review FAQ +=============== + +What is the purpose of code review? +----------------------------------- + +Code review is our basic mechanism for validating the design and +implementation of patches. It also helps us maintain a level of +consistency in design and implementation practices across the many +hackers and among the various modules of Mozilla. + +Of course, code review doesn't happen instantaneously, and so there is +some latency built into the system. We're always looking for ways to +reduce the wait, while simultaneously allowing reviewers to do a good +chunk of hacking themselves. We don't have a perfect system, and we +never will. It's still evolving, so let us know if you have suggestions. + +Mozilla used to have the concept of "super-review", but `a consensus was +reached in +2018 <https://groups.google.com/forum/#!topic/mozilla.governance/HHU0h-44NDo>`__ +to retire this process. + +Who must review my code? +------------------------ + +You must have an approval ("r={{ mediawiki.external('name') }}") from +the module owner or designated "peer" of the module where the code will +be checked in. If your code affects several modules, then generally you +should have an "r={{ mediawiki.external('name') }}" from the owner or +designated peer of each affected module. We try to be reasonable here, +so we don't have an absolute rule on when every module owner must +approve. For example, tree-wide changes such as a change to a string +class or a change to text that is displayed in many modules generally +doesn't get reviewed by every module owner. + +You may wish to ask others as well. + + +What do reviewers look for? +--------------------------- + +A review is focused on a patch's design, implementation, usefulness in +fixing a stated problem, and fit within its module. A reviewer should be +someone with domain expertise in the problem area. A reviewer may also +utilize other areas of his or her expertise and comment on other +possible improvements. There are no inherent limitations on what +comments a reviewer might make about improving the code. + +Reviewers will probably look at the following areas of the code: + +- “goal” review: is the issue being fixed actually a bug? Does the + patch fix the fundamental problem? +- API/design review. Because APIs define the interactions between + modules, they need special care. Review is especially important to + keep APIs balanced and targeted, and not too specific or + overdesigned. There are a `WebIDL review + checklist <https://wiki.mozilla.org/WebAPI/WebIDL_Review_Checklist>`__. + There are also templates for emails that should be sent when APIs are + going to be exposed to the Web and general guidance around naming on + `this wiki + page <https://wiki.mozilla.org/WebAPI/ExposureGuidelines>`__. +- Maintainability review. Code which is unreadable is impossible to + maintain. If the reviewer has to ask questions about the purpose of a + piece of code, then it is probably not documented well enough. Does + the code follow the :ref:`Coding style` ? Be careful when + reviewing code using modern C++ features like auto. +- Security review. Does the design use security concepts such as input + sanitizers, wrappers, and other techniques? Does this code need + additional security testing such as fuzz-testing or static analysis? +- Integration review. Does this code work properly with other modules? + Is it localized properly? Does it have server dependencies? Does it + have user documentation? +- Testing review. Are there tests for correct function? Are there tests + for error conditions and incorrect inputs which could happen during + operation? +- Performance review. Has this code been profiled? Are you sure it's + not negatively affecting performance of other code? +- License review. Does the code follow the `code licensing + rules <http://www.mozilla.org/hacking/committer/committers-agreement.pdf>`__? + + +How can I tell the status of reviews? +------------------------------------- + +When a patch has passed review you'll see "Accepted" in green at the top +of a Phabricator revision, under the title. In Bugzilla (which is +deprecated in favour of Phabricator), this is indicated by "{{ +mediawiki.external('name') }}:review+" in the attachment table in the +bug report. If it has failed review then you'll see "Needs Revision" in +red at the top of the revision, or, in Bugzilla, "{{ +mediawiki.external('name') }}:review-". Most of the time that a reviewer +sets a review flag, they will also add a comment to the bug explaining +the review. diff --git a/docs/contributing/build/artifact_builds.rst b/docs/contributing/build/artifact_builds.rst new file mode 100644 index 0000000000..7a92a559f6 --- /dev/null +++ b/docs/contributing/build/artifact_builds.rst @@ -0,0 +1,173 @@ +Understanding Artifact Builds +============================= + +Firefox for Desktop and Android supports a **fast build mode** called +*artifact mode*. The resulting builds are called *artifact builds*. +Artifact mode downloads pre-built C++ components rather than building them +locally, trading bandwidth for time. + +Artifact builds will be useful to many developers who are not working +with compiled code (see "Restrictions" below). Artifacts are typically +fetched from `mozilla-central <https://hg.mozilla.org/mozilla-central/>`__. + +To automatically download and use pre-built binary artifacts, add the +following lines into your :ref:`mozconfig <Configuring Build Options>` +file: + +.. code-block:: shell + + # Automatically download and use compiled C++ components: + ac_add_options --enable-artifact-builds + + # Write build artifacts to: + mk_add_options MOZ_OBJDIR=./objdir-frontend + +To automatically download and use the debug version of the pre-built +binary artifact (currently supported for Linux, OSX and Windows +artifacts), add ``ac_add_options --enable-debug`` to your mozconfig file +(with artifact builds option already enabled): + +.. code-block:: shell + + # Enable debug versions of the pre-built binary artifacts: + ac_add_options --enable-debug + + # Automatically download and use compiled C++ components: + ac_add_options --enable-artifact-builds + + # Download debug info so that stack traces refers to file and columns rather than library and Hex address + ac_add_options --enable-artifact-build-symbols + + # Write build artifacts to: + mk_add_options MOZ_OBJDIR=./objdir-frontend-debug-artifact + + +Prerequisites +------------- + +Artifact builds are supported for users of Mercurial and Git. Git +artifact builds require a mozilla-central clone made with the help of +`git-cinnabar <https://github.com/glandium/git-cinnabar>`__. Please +follow the instructions on the git-cinnabar project page to install +git-cinnabar. Further information about using git-cinnabar to interact +with Mozilla repositories can be found on `the project +wiki <https://github.com/glandium/git-cinnabar/wiki/Mozilla:-A-git-workflow-for-Gecko-development>`__. + +Building +-------- + +If you've added ``--enable-artifact-builds`` to your ``mozconfig``, each +time you run ``mach build`` and ``mach build path/to/subdirectory`` the +build system will determine what the best pre-built binary artifacts +available are, download them, and put them in place for you. The +computations are cached, so the additional calculations should be very +fast after the up-to-date artifacts are downloaded -- just a second or +two on modern hardware. Most Desktop developers should find that + +.. code-block:: shell + + ./mach build + ./mach run + +just works. + +To only rebuild local changes (to avoid re-checking for pushes and/or +unzipping the downloaded cached artifacts after local commits), you can +use: + +.. code-block:: shell + + ./mach build faster + +which only "builds" local JS, CSS and packaged (e.g. images and other +asset) files. + +Most Firefox for Android developers should find that + +.. code-block:: shell + + ./mach build + ./mach package + ./mach install + +just works. + +Pulling artifacts from a try build +---------------------------------- + +To only accept artifacts from a specific revision (such as a try build), +set ``MOZ_ARTIFACT_REVISION`` in your environment to the value of the +revision that is at the head of the desired push. Note that this will +override the default behavior of finding a recent candidate build with +the required artifacts, and will cause builds to fail if the specified +revision does not contain the required artifacts. + +Restrictions +------------ + +Oh, so many. Artifact builds are rather delicate: any mismatch between +your local source directory and the downloaded binary artifacts can +result in difficult to diagnose incompatibilities, including unexplained +crashes and catastrophic XPCOM initialization and registration +failures. These are rare, but do happen. + +Things that are supported +------------------------- + +- Modifying JavaScript, (X)HTML, and CSS resources; and string + properties and FTL files. +- Modifying Android Java code, resources, and strings. +- Running mochitests and xpcshell tests. +- Modifying ``Scalars.yaml`` to add Scalar Telemetry (since {{ + Bug("1425909") }}, except artifact builds on try). +- Modifying ``Events.yaml`` to add Event Telemetry (since {{ + Bug("1448945") }}, except artifact builds on try). + +Essentially everything updated by ``mach build faster`` should work with +artifact builds. + +Things that are not supported +----------------------------- + +- Support for products other than Firefox for Desktop and + Android are not supported and are unlikely to ever be supported. + Other projects like Thunderbird may provide + `their own support <https://developer.thunderbird.net/thunderbird-development/building-thunderbird/artifact-builds>`__ + for artifact builds. +- You cannot modify C, C++, or Rust source code anywhere in the tree. + If it’s compiled to machine code, it can't be changed. +- You cannot modify ``histograms.json`` to add Telemetry histogram + definitions.(But see `Bug 1206117 <https://bugzilla.mozilla.org/show_bug.cgi?id=1206117>`__). +- Modifying build system configuration and definitions does not work in + all situations. + +Things that are not **yet** supported +------------------------------------- + +- Tests other than mochitests, xpcshell, and Marionette-based tests. + There aren’t inherent barriers here, but these are not known to work. +- Modifying WebIDL definitions, even ones implemented in JavaScript. + +Troubleshooting +--------------- + +There are two parts to artifact mode: +the ``--disable-compile-environment`` option, and the ``mach artifact`` +command that implements the downloading and caching. Start by running + +.. code-block:: shell + + ./mach artifact install --verbose + +to see what the build system is trying to do. There is some support for +querying and printing the cache; run ``mach artifact`` to see +information about those commands. + +Downloaded artifacts are stored in +``$MOZBUILD_STATE_PATH/package-frontend``, which is almost always +``~/.mozbuild/package-frontend``. + +Discussion is best started on the `dev-builds mailing +list <https://lists.mozilla.org/listinfo/dev-builds>`__. Questions are +best raised in `#build <https://chat.mozilla.org/#/room/#build:mozilla.org>`__ on `Matrix <https://chat.mozilla.org/>`__. Please +file bugs in *Firefox Build System :: General*, blocking `Bug 901840 <https://bugzilla.mozilla.org/show_bug.cgi?id=901840>`__ diff --git a/docs/contributing/build/building_mobile_firefox.rst b/docs/contributing/build/building_mobile_firefox.rst new file mode 100644 index 0000000000..90e922af8a --- /dev/null +++ b/docs/contributing/build/building_mobile_firefox.rst @@ -0,0 +1,34 @@ +Firefox for Mobile Devices +-------------------------- + +We have several different mobile products aimed at different tasks, +devices, and audiences: + +- Building **Firefox for Android** (codename: fenix). Our general-purpose + mobile browser is split into several different artifact layers: + + - `The fenix Android application </mobile/android/fenix.html>`_ + - `The android-components Android library <https://github.com/mozilla-mobile/firefox-android/tree/main/android-components>`_ + - `The GeckoView platform </mobile/android/geckoview>`_ + +- `Firefox for iOS <https://github.com/mozilla-mobile/firefox-ios>`_, + our general-purpose browser for iOS with desktop sync built-in. +- Building **Firefox Focus**, our privacy-focused browser for + + - `iOS <https://github.com/mozilla-mobile/focus-ios>`_ + - `Android <https://github.com/mozilla-mobile/firefox-android/tree/main/focus-android>`_. This browser + also uses the android-components library and GeckoView platform, like Firefox for Android + +For both Desktop and Mobile development, please bear the following in +mind: + +- While you can build Firefox on older hardware it can take quite a bit + of time to compile on slower machines. Having at least 8GB of RAM is + recommended, and more is always better. The build process is both CPU + and I/O intensive, so building on a machine with an SSD is also + strongly preferred. +- Fast broadband internet is strongly recommended as well. Both the + development environment and the source code repository are quite + large. +- Though you can build Firefox to run on 32-bit machines, the build + process for almost all of our products requires a 64-bit OS. diff --git a/docs/contributing/build/supported.rst b/docs/contributing/build/supported.rst new file mode 100644 index 0000000000..4223f812ff --- /dev/null +++ b/docs/contributing/build/supported.rst @@ -0,0 +1 @@ +.. include:: ../../build/buildsystem/supported-configurations.rst diff --git a/docs/contributing/committing_rules_and_responsibilities.rst b/docs/contributing/committing_rules_and_responsibilities.rst new file mode 100644 index 0000000000..c3edcba79f --- /dev/null +++ b/docs/contributing/committing_rules_and_responsibilities.rst @@ -0,0 +1,198 @@ +Committing rules and responsibilities +===================================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +Preparation +----------- + +There are things you need to be sure of before you even attempt to check +in: + +- Your code must + :ref:`compile <Building Firefox On Linux>` and `pass all the automated tests <https://developer.mozilla.org/docs/Mozilla/QA/Automated_testing>`__ + before you consider pushing changes. If you are at all unsure, verify + your changes with the + `mozilla-central <https://wiki.mozilla.org/Build:TryServer>`__. + try server, as appropriate. +- You need :ref:`code review <Code Review FAQ>`. +- Depending on the stage of the development process, you may need + `approval <https://wiki.mozilla.org/Tree_Rules>`__. Commits to trees + where approval is required must have "a=" in the commit message + followed by the name of the approver. +- Code should be factored in such a way such that we can disable + features which cause regressions, either by backout or via a kill + switch/preference. Be especially careful when landing features which + depend on other new features which may be disabled. Ask + mozilla.dev.planning for assistance if there are any questions. + +Checkin comment +--------------- + +The checkin comment for the change you push should include the bug +number, the names of the reviewers, and a clear explanation of the fix. +Please say what changes are made, not what problem was fixed, e.g.: + +Good: "Bug 123456 - Null-check presentation shell so we don't crash when a +button removes itself during its own onclick handler. r=paul, a=ringo." + +Bad: "Bug 123456 - crash clicking button on www.example.com" + +If you are not the author of the code, use ``hg commit -u`` to specify +the actual author in the Mercurial changeset: + +:: + + hg commit -u "Pat Chauthor <pat@chauthor.com>" + +Commit message restrictions +--------------------------- + +The purpose of these new restrictions, implemented via a mercurial hook, +is to prevent commit messages that do not have a bug number. We will +still allow a small set of special commits lacking bugs numbers, like +merges and backouts. + +This hook will be enabled on mozilla-central and every major branch that +directly merges into it, such as autoland or integration +branches, team branches, or established project branches. + +An example for a passing commit message would be, + +:: + + Bug 577872 - Create WebM versions of Ogg reftests. r=kinetik + +Note the *Bug ####*, you at least need that. You also can't commit +bustage-fixes without a bug number anymore. This is intentional to keep +track of the bug which caused it. + +Allowed are: + +- Commit messages containing "bug" or "b=" followed by a bug number +- Commit messages containing "no bug" (please use this sparingly) +- Commit message indicating backout of a given 12+ digit changeset ID, + starting with (back out|backing out|backed out|backout)( of)? + (rev|changeset|cset)s? [0-9a-f]{12} +- Commit messages that start with "merge" or "merging" and are actually + for a merge changeset. + +Special exceptions: + +- Commits by the special users "ffxbld", "seabld", "tbirdbld", or + "cltbld". +- When the commit is older then some date shortly after the hook has + been enabled, to allow merges from other branches. This exception + will be lifted after a short period of time (probably a few months) + after the hooks is enabled. +- You can also specify "IGNORE BAD COMMIT MESSAGES" in the tip (latest) + commit message to override all the restrictions. This is an extreme + measure, so you should only do this if you have a very good reason. + +Explicitly disallowed: + +- Commit messages containing "try: " to avoid unintentional commits + that were meant for the try server. + +All tests for allowed or excluded messages are case-insensitive. The +hook, +`commit-message.py <https://hg.mozilla.org/hgcustom/version-control-tools/file/tip/hghooks/mozhghooks/commit-message.py>`__, +was added in `bug 506949 <https://bugzilla.mozilla.org/show_bug.cgi?id=506949>`__. + + +Check the tree +-------------- + +TaskCluster is a continuous build system that builds and tests every change +checked into autoland/mozilla-central and related source trees. +`Treeherder <https://treeherder.mozilla.org/>`__ displays the progress +and results of all the build and test jobs for a given tree. For a +particular job, green means all is well, orange means tests have failed, +and red means the build itself broke. Purple means that a test was +interrupted, possibly by a problem with the build system or the +network. Blue means that a test was interrupted in a known way and will +be automatically restarted. You can click on the "Help" link in the top +right corner of Treeherder for a legend to help you decode all the other +colors and letters. + +If the tree is green, it is okay to check in. If some builds are orange +or red, you can either wait, or make sure all the failures are +classified with annotations/comments that reference bug numbers or +fixes. + +If the tree is marked as "closed", or if you have questions about any +oranges or reds, you should contact the sheriff before checking in. + + +Failures and backouts +--------------------- + +Patches which cause unit test failures (on :ref:`tier 1 +platforms <Supported Build Hosts and Targets>`) will be backed out. +Regressions on tier-2 platforms and in performance are not cause for a +direct backout, but you will be expected to help fix them if quickly. + +*Note: Performance regressions require future data points to ensure a +sustained regression and can take anywhere from 3 hours to 30 hours +depending on the volume of the tree and build frequency. All regression +alerts do get briefly investigated and bugs are filed if necessary.* + + +Dealing with test failures +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a build or a test job fails, you can click on the red or orange or +purple symbol for the job on Treeherder to display more information. +The information will appear in the footer, including a summary of any +error messages, a "+" icon to re-trigger the job (schedule it to run +again), and links to the log files and to possibly-related bugs. + +Here are some steps you can follow to figure out what is causing most +failures, `and "star" them +appropriately <http://ehsanakhgari.org/blog/2010-04-09/assisted-starring-oranges>`__: + +#. Click on the failing job to see a list of suggested bugs. If the + failure clearly matches a known bug, **click on the star** next to + that bug and then click "Add a comment" and then submit the comment. + This is referred to as "starring the build;" you'll see this phrase + or ones like it in IRC a lot. +#. If the failure might match a known bug but you are not sure, click + the bug number to open the Bugzilla report, and click the failing job + to open its log. If the log and the bug do match, add a comment as + in step 1 (above). +#. If the summary does not seem to match any suggested bugs, search + Bugzilla for the name of the failing test or the error message. If + you find a matching bug, add a comment in the bug in Bugzilla, and + another to the job in Treeherder. +#. If you can't figure out whether a known bug exists (for example, + because you can't figure out what part of the log you should search + for), look on Treeherder to see if there are other similar failures + nearby, or ask on #developers to see if anyone recognizes it as a + known failure. For example, many Android tests fail frequently in + ways that do not produce useful log messages. You can often find the + appropriate bug just by looking at other Android failures that are + already starred. +#. If there is no matching bug, you can back out the change (if you + suspect the failure was caused by your changeset) or re-trigger the + job (if you suspect it's an unrelated intermittent failure). After + more test runs it should become clear whether it is a new regression + or just an unknown intermittent failure. +#. If it turns out to be an unknown intermittent failure, file a new bug + with "intermittent-failure" in the keywords. Include the name of the + test file and an one-line summary of the log messages in the Summary + field. In the description, include an excerpt of the error messages + from the log, and a link to the log file itself. + +At any point if you are not sure or can't figure out what to do, ask for +advice or help in `#developers <https://chat.mozilla.org>`__. +If a large number of jobs are failing and you suspect an infrastructure problem, you can also ask +about it in `#releng <https://chat.mozilla.org>`__. + + +Dealing with performance regressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Under some circumstances, if your patch causes a performance regression +that is not acceptable, it will get backed out. diff --git a/docs/contributing/contributing_to_mozilla.rst b/docs/contributing/contributing_to_mozilla.rst new file mode 100644 index 0000000000..0e12922ece --- /dev/null +++ b/docs/contributing/contributing_to_mozilla.rst @@ -0,0 +1,63 @@ +Contributing to Mozilla projects +================================ + +This page is here to help you get from "I want to build Firefox" +to "I'm building my own Firefox" to "I can contribute to Firefox". +So if you'd like to help Mozilla build the best web browsers in the +world, you're in the right place. + +.. rubric:: Need help? + :name: Need_help + +The Mozilla community prides itself on being an open, accessible, and +friendly community for new participants. If you have any difficulties +getting involved or finding answers to your questions, please `come and +ask your questions in our +chatroom <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_, +where we can help you get started. + +We know even before you start contributing that getting set up to work +on Firefox and finding a bug that's a good fit for your skills can be a +challenge, and we're always looking for ways to improve this process: making +Mozilla more open, accessible, and easier to participate with. If you're +having any trouble following this documentation, or hit a barrier you +can't get around, please join us in the the Introduction room on Matrix. + +What skills do I need? +---------------------- + +Mozilla maintains small and large projects and we are thrilled to have contributors with +very diverse skills: + +- If you know **C++,** **Rust,** **JavaScript,** **HTML** or **CSS**, + you can :ref:`contribute to the core layers <Firefox Contributors' Quick Reference>` of + Firefox and many other Mozilla projects. +- If you know **Rust**, you can also contribute to the `Rust programming + language <https://github.com/rust-lang/rust>`_ itself, numerous crates like `grcov <https://github.com/mozilla/grcov/>`_ + or `Servo <https://servo.org/>`_, the web browser engine designed for parallelism and safety. +- If you know **Kotlin**, you can contribute to `Firefox + for Android <https://github.com/mozilla-mobile/fenix>`_ (code name: + "Fenix"). +- If you know **Swift**, you can contribute to `Firefox for + iOS <https://github.com/mozilla-mobile/firefox-ios>`_ and `Firefox + Focus for iOS <https://github.com/mozilla-mobile/focus-ios>`_. +- If you know **C++**, you can contribute to our `VPN client <https://github.com/mozilla-mobile/mozilla-vpn-client>`_. +- If you know **Python**, you can contribute to our web services, + including Firefox Sync and Firefox Accounts. +- If you know **Make**, **shell**, **Perl**, or **Python**, you can + contribute to our build systems, release engineering, and automation. +- If you know **Go** or **JavaScript**, you can contribute to `TaskCluster + <https://github.com/taskcluster/taskcluster>`_ our CI infrastructure. +- If you know **C**, you can contribute to `NSS <https://developer.mozilla.org/docs/Mozilla/Projects/NSS>`_, + `Opus <https://opus-codec.org/>`_, and `Daala <https://wiki.xiph.org/Daala>`_. +- There are even many ways to contribute to the Mozilla mission without + programming. If getting involved in design, support, translation, + testing, or other types of contributions sparks your interest please + see the `Volunteer Opportunities + wiki <https://contribute.mozilla.org>`_ or the `Mozilla + community <https://mozilla.community/>`_ site. + +Perhaps you do not know programming yet, but you want to start learning? +There are `plenty of +resources <https://developer.mozilla.org/learn>`_ available on +the MDN Web Docs! diff --git a/docs/contributing/contribution_quickref.rst b/docs/contributing/contribution_quickref.rst new file mode 100644 index 0000000000..dcaa969c97 --- /dev/null +++ b/docs/contributing/contribution_quickref.rst @@ -0,0 +1,369 @@ +Firefox Contributors' Quick Reference +===================================== + +Some parts of this process, including cloning and compiling, can take a long time even on modern hardware. +If at any point you get stuck, please don't hesitate to ask at `https://chat.mozilla.org <https://chat.mozilla.org>`__ +in the `#introduction <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`__ channel. + +Don’t hesitate to look at the :ref:`Getting Set Up To Work On The Firefox Codebase<Getting Set Up To Work On The Firefox Codebase>` for a more detailed tutorial. + +Before you start +---------------- +Please register and create your account for + +`Bugzilla <https://bugzilla.mozilla.org/>`__ : web-based general-purpose bug tracking system. +To register with Phabricator, make sure you enable Two-Factor Authentication (My Profile >> Edit Profile & Preferences >> Two-Factor Authentication) in Bugzilla. + +`Phabricator <https://phabricator.services.mozilla.com/>`__: web-based software development collaboration tools, mainly for code review. +Please obtain an API Token (Settings >> Conduit API Tokens) + +Windows dependencies +-------------------- + +#. You need a :ref:`supported version of Windows<tier_1_hosts>`. +#. Download and install `Visual Studio Community Edition. <https://visualstudio.microsoft.com/downloads/>`__ +#. Finally download the `MozillaBuild Package. <https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe>`__ Installation directory should be: + + .. code-block:: shell + + $ c:\mozilla-build\ + +#. Before moving on to the next steps, make sure to fulfill the :ref:`Windows prerequisites <Building Firefox On Windows>` + +.. note:: + + All the commands of this tutorial must be run in the shell provided with the MozillaBuild Package (start-shell.bat) + +:ref:`More information <Building Firefox On Windows>` + +Bootstrap a copy of the Firefox source code +------------------------------------------- + +You can download the source code and have Firefox automatically download and install the other dependencies it needs. The below command as per your Operating System, will download a lot of data (years of Firefox history!) then guide you through the interactive setup process. + +Downloading can take from 40 minutes to two hours (depending on your connection) and the repository should be less than 5GB (~ 20GB after the build). + +The default options are recommended. +If you're not planning to write C++ or Rust code, select :ref:`Artifact Mode <Understanding Artifact Builds>` +and follow the instructions at the end of the bootstrap for creating a mozconfig file. + +To Setup Firefox On Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: shell + + $ cd c:/ + $ mkdir mozilla-source + $ cd mozilla-source + $ wget https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py + $ python3 bootstrap.py + +More information :ref:`for Windows <Building Firefox On Windows>` + +To Setup Firefox On macOS and Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: shell + + $ curl https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py -O + $ python3 bootstrap.py + +More information :ref:`for Linux <Building Firefox On Linux>` and :ref:`for MacOS <Building Firefox On MacOS>` + +To set up your editor +--------------------- + +.. note:: + + Visual Studio Code is the recommended editor for Firefox development. + Not because it is better than the other editors but because we decided to + focus our energy on a single editor. + +Setting up your editor is an important part of the contributing process. Having +linting and other features integrated, saves you time and will help with reducing +build and reviews cycles. + +See our :ref:`editor page for more information about how to set up your favorite editor <Editor / IDE integration>`. + +To build & run +-------------- + +Once the System is bootstrapped, run: + +.. code-block:: shell + + $ cd mozilla-unified + $ ./mach build + +which will check for dependencies and start the build. +This will take a while; a few minutes to a few hours depending on your hardware. + +.. note:: + + The default build is a compiled build with optimizations. Check out the + :ref:`mozconfig file documentation <Configuring Build Options>` + to see other build options. If you don't plan to change C++ or Rust code, + an :ref:`artifact build <Understanding Artifact Builds>` will be faster. + +To run it: + +.. code-block:: shell + + $ ./mach run + +:ref:`More information about Linux <Building Firefox On Linux>` / :ref:`More information about MacOS <Building Firefox On MacOS>` + +.. _write_a_patch: + +To write a patch +---------------- + +Make the changes you need in the codebase. You can look up UI text in `Searchfox <https://searchfox.org>`__ to find the right file. + +Then: + +.. code-block:: shell + + # Mercurial + $ hg commit + + # Git + $ git commit + +.. _Commit message: + +The commit message should look like: + +.. code-block:: text + + Bug xxxx - Short description of your change. r?reviewer + + Optionally, a longer description of the change. + +**Make sure you include the bug number and at least one reviewer (or reviewer group) in this format.** + +To :ref:`find a reviewer or a review group <Getting reviews>`, the easiest way is to run +``hg log <modified-file>`` (or ``git log <modified-file>``, if +you're using git) on the relevant files, and look who usually is +reviewing the actual changes (ie not reformat, renaming of variables, etc). + + +To visualize your patch in the repository, run: + +.. code-block:: shell + + # Mercurial + $ hg wip + + # Git + $ git show + +:ref:`More information on how to work with stack of patches <Working with stack of patches Quick Reference>` + +:ref:`More information <Mercurial Overview>` + +To make sure the change follows the coding style +------------------------------------------------ + +To detect coding style violations, use mach lint: + +.. code-block:: shell + + $ ./mach lint path/to/the/file/or/directory/you/changed + + # To get the autofix, add --fix: + $ ./mach lint path/to/the/file/or/directory/you/changed --fix + +:ref:`More information <Code quality>` + +To test a change locally +------------------------ + +To run the tests, use mach test with the path. However, it isn’t +always easy to parse the results. + +.. code-block:: shell + + $ ./mach test dom/serviceworkers + +To run tests based on :ref:`GTest` (C/C++ based unit tests), run: + +.. code-block:: shell + + $ ./mach gtest 'QuotaManager.*' + +To test a change remotely +------------------------- + +Running all the tests for Firefox takes a very long time and requires multiple +operating systems with various configurations. To build Firefox and run its +tests on continuous integration servers (CI), multiple :ref:`options to select tasks <Selectors>` +are available. + +To automatically select the tasks that are most likely to be affected by your changes, run: + +.. code-block:: shell + + $ ./mach try auto + +To select tasks manually using a fuzzy search interface, run: + +.. code-block:: shell + + $ ./mach try fuzzy + +To rerun the same tasks: + +.. code-block:: shell + + $ ./mach try again + +From `Treeherder <https://treeherder.mozilla.org/>`__ (our continuous integration system), it is also possible to attach new jobs. As every review has +a try CI run associated, it makes this work easier. See :ref:`attach-job-review` for +more information. + +.. note:: + + This requires `level 1 commit access <https://www.mozilla.org/about/governance/policies/commit/access-policy/>`__. + + You can ask your reviewer to submit the patch for you if you don't have that + level of access. + +:ref:`More information <Pushing to Try>` + + +To submit a patch +----------------- + +To submit a patch for review, we use a tool called `moz-phab <https://pypi.org/project/MozPhab/>`__. +To install it, run: + +.. code-block:: shell + + $ ./mach install-moz-phab + +Once you want to submit your patches (make sure you :ref:`use the right commit message <Commit message>`), run: + +.. code-block:: shell + + $ moz-phab + +It will publish all the currently applied patches to Phabricator and inform the reviewer. + +If you wrote several patches on top of each other: + +.. code-block:: shell + + $ moz-phab submit <first_revision>::<last_revision> + +`More +information <https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html>`__ + +To update the working directory +------------------------------- + +If you're finished with a patch and would like to return to the tip to make a new patch: + +.. code-block:: shell + + $ hg pull central + $ hg up central + +To update a submitted patch +--------------------------- + +It is rare that a reviewer will accept the first version of patch. Moreover, +as the code review bot might suggest some improvements, changes to your patch +may be required. + +If your patch is not loaded in your working directory, you first need to re-apply it: + +.. code-block:: shell + + $ moz-phab patch D<revision_id> + +Make your changes in the working folder and run: + +.. code-block:: shell + + # Or, if you need to pass arguments, e.g., changing the commit message: + $ hg commit --amend + + # Git + $ git commit --amend + +After amending the patch, you will need to submit it using moz-phab again. + +.. warning:: + + Don't use ``hg commit --amend -m`` or ``git commit --amend -m``. + + Phabricator tracks revision by editing the commit message when a + revision is created to add a special ``Differential Revision: + <url>`` line. + + When ``--amend -m`` is used, that line will be lost, leading to + the creation of a new revision when re-submitted, which isn't + the desired outcome. + +If you wrote many changes, you can squash or edit commits with the +command: + +.. code-block:: shell + + # Mercurial + $ hg histedit + + # Git + $ git rebase -i + +The submission step is the same as for the initial patch. + +:ref:`More information on how to work with stack of patches <Working with stack of patches Quick Reference>` + +Retrieve new changes from the repository +---------------------------------------- + +To pull changes from the repository, run: + +.. code-block:: shell + + # Mercurial + $ hg pull --rebase + + # Git + $ git pull --rebase + +.. _push_a_change: + +To push a change in the code base +--------------------------------- + +Once the change has been accepted and you've fixed any remaining issues +the reviewer identified, the reviewer should land the patch. + +If the patch has not landed on "autoland" (the integration branch) after a few days, +feel free to contact the reviewer and/or +@Aryx or @Sylvestre on the `#introduction <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`__ +channel. + +The landing procedure will automatically close the review and the bug. + +:ref:`More information <How to submit a patch>` + +Contributing to GeckoView +------------------------- + +Note that the GeckoView setup and contribution processes are different from those of Firefox; +GeckoView setup and contribution docs live in `geckoview.dev <https://geckoview.dev>`__. + +More documentation about contribution +------------------------------------- + +:ref:`Contributing to Mozilla projects` + +https://mozilla-version-control-tools.readthedocs.io/en/latest/devguide/contributing.html + +https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html + +https://mikeconley.github.io/documents/How_mconley_uses_Mercurial_for_Mozilla_code diff --git a/docs/contributing/debugging/capturing_minidump.rst b/docs/contributing/debugging/capturing_minidump.rst new file mode 100644 index 0000000000..4c8f7591f5 --- /dev/null +++ b/docs/contributing/debugging/capturing_minidump.rst @@ -0,0 +1,259 @@ +Capturing a minidump +==================== + +*Minidumps* are files created by various Windows tools which record the +complete state of a program as it's running, or as it was at the moment +of a crash. Small minidumps are created by the Breakpad :ref:`crash +reporting <Crash Reporter>` tool, but sometimes that's not +sufficient to diagnose a problem. For example, if the application is +hanging (not responding to input, but hasn't crashed) then Breakpad is +not triggered, and it can be difficult to determine where the problem +lies. Sometimes a more complete form of minidump is needed to see +additional details about a crash, in which case manual capture of a +minidump is desired. + +This page describes how to capture these minidumps on Windows, to permit +better debugging. + + +Privacy and minidumps +--------------------- + +.. warning:: + + **Warning!** Unlike the minidumps submitted by Breakpad, these + minidumps contain the **complete** contents of program memory. They + are therefore much more likely to contain private information, if + there is any in the browser. For this reason, you may prefer to + generate minidumps against a `clean + profile <http://support.mozilla.com/en-US/kb/Managing%20profiles>`__ + where possible. + + +Capturing a minidump: application crash +--------------------------------------- + +To capture a full minidump for an application crash, you can use a tool called +**Debugging Tools for Windows**, which is provided by Microsoft for free. + + +Install Debugging Tools for Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Please follow `these instructions +<https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/>`__. +You can install the Debugging Tools for Windows alone, but you cannot +download it alone. To install it, download Windows Software Development Kit +(SDK) first, start the installer, and then select only **Debugging Tools for +Windows** in the list of features to install. + +.. image:: img/sdk-installer.png + +The latest installer installs the tools for all CPU architectures (X86, +X64, ARM, and ARM64). You need to choose a tool of the architecture +matching Firefox you want to capture a minidump from. For example, if +you want to capture a minidump from 32-bit Firefox on 64-bit Windows, +use the X86 version of tools, not X64 tools. + +The default install path of SDK for 64-bit Windows is +``%ProgramFiles(x86)%\Windows Kits\10``. The debugging tools can be found in +the folder named **Debuggers** under your install path of SDK. + +The Debugging Tools for Windows contains both graphical and command line +debugging tools that can be used to capture a minidump. If you prefer +a graphical tool, please follow `Capture a minidump in a graphical way +<#capture-a-minidump-in-a-graphical-way>`__. If you prefer a command +line tool, please follow `Capture a minidump from the command line +<#capture-a-minidump-from-the-command-line>`__. + + +Capture a minidump in a graphical way +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#. Launch the graphical debugger named WinDbg from the Start Menu. WinDbg + icons are registered under "Windows Kits" as below. + + |WinDbg in Start Menu| + +#. Connect Firefox to the debugger. + + a. If Firefox is not already running, open the **"File"** menu on WinDbg + and choose **"Open Executable..."**. In the file chooser window that + appears, open the firefox.exe executable. If you're not sure about where + it is, please see `How to find the location of firefox.exe + <#how-to-find-the-location-of-firefox-exe>`__. + + b. If Firefox is already running and you know which process you want to + capture a minidump from, open the **"File"** menu on WinDbg and choose + **"Attach to a Process..."**. In the "Attach to Process" dialog that + appears, select the process. To identify a process, please see + `Identify a process to attach a debugger to + <#identify-a-process-to-attach-a-debugger-to>`__. + +#. You should now see a "Command" text window with debug output at the + top and an input box at the bottom. From the menu, select + ``Debug → Go``, and Firefox should start. If the debugger spits out + some text right away and Firefox doesn't come up, select + ``Debug → Go`` again. + +#. When the program is about to crash, WinDbg will spit out more data, + and the prompt at the bottom will change from saying "``*BUSY*``" to + having a number in it. At this point, you should type + "``.dump /ma c:\temp\firefoxcrash.dmp``" -- without the quotes, but + don't forget the dot at the beginning. Once it completes, which can + take a fair while, you will have a very large file at + ``c:\temp\firefoxcrash.dmp`` that can be used to help debug your + problem. File size will depend on this size of Firefox running in + your environment, which could several GB. + +#. Ask in the relevant bug or thread how best to share this very large + file! + + +Capture a minidump from the command line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If Firefox is not already running, open the Command Prompt and run the following +command. This command launches all Firefox processes under a debugger. This +technique is useful when you have a startup crash or when you're not sure about +which process will crash. + +To find out where firefox.exe is, please see `How to find the location +of firefox.exe <#how-to-find-the-location-of-firefox-exe>`__. + +.. code:: + + <path to debugger>\cdb.exe -g -G -o <path to firefox>\firefox.exe + + +For example, if both the debugging tools and Firefox are installed in the +default folder and you want to capture a minidump of 64-bit Firefox, +the command will be like this. Please note that you need to add double +quotes when a path contains one or more whitespaces. + +.. code:: + + "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe" -g -G -o "C:\Program Files\Mozilla Firefox\firefox.exe" + + +If a Firefox process you want to capture a minidump from is already running, +attach the debugger to it with the following command. To identify a process, +please see `Identify a process to attach a debugger to +<#identify-a-process-to-attach-a-debugger-to>`__. + +.. code:: + + <path to debugger>\cdb.exe -g -G -p <PID> + +When the process crashes, the debugger tool captures it and waits for your +command. At this point, you should type ``.dump /ma c:\temp\firefoxcrash.dmp`` +-- don't forget the dot at the beginning. Once it completes, which can take +a fair while, you will have a very large file at ``c:\temp\firefoxcrash.dmp`` +that can be used to help debug your problem. File size will depend on this +size of Firefox running in your environment, which could several GB. + +After a minidump is generated, type ``q`` and press Enter to quit the debugger. + + +Capturing a minidump: application hang +-------------------------------------- + +On Windows Vista and Windows 7, you can follow `these +instructions <http://support.microsoft.com/kb/931673>`__ to capture a +dump file and locate it after it's been saved. + + +Identify a process to attach a debugger to +------------------------------------------ + +When you're running Firefox, even if you have only a single tab, you may have +noticed a bunch of firefox.exe instances in Task Manager. This means Firefox +consists of multiple processes. Since an application crash happens per process +and a minidump is generated per process, you need to identify which process will +crash before starting a debugger. + +Identify a process type +~~~~~~~~~~~~~~~~~~~~~~~ + +Each instance of firefox.exe has a type. To identify a process to attach +a debugger to, you need to know its process type first. + +When a crash happens, if all Firefox windows are suddenly gone and Mozilla +Crash Reporter window is opend, a process that crashed is the main process. + +.. image:: img/crashreporter.png + +When a crash happens, if you see the following page, a process that crashed +is a tab (content) process. + +.. image:: img/tabcrashed.png + +There are more process types, but there isn't an easy way to detect a crash in +a process of those types because the symptom varies. If you cannot be sure +about the type of a crashing process, terminate Firefox and launch a new +instance of Firefox under a debugger in the way described above. + +If a GPU process crashes, you may see a window is not rendered correctly as +below. Since the main process relaunches a GPU process, this symptom will be +transient and the window will be rendered correctly again. + +.. image:: img/crash-gpu.png + +If a GMP (= Gecko Media Plugin) process crashes, you will see an information +bar will be displayed below the address bar. + +.. image:: img/crash-gmp.png + +If an RDD (= Remote Data Decoder) process crashes, Firefox may stop playing +a video as below, but not limited to this symptom. + +.. image:: img/crash-rdd.png + + +Identify a process ID (PID) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you understand what type of process crashes, the next step is to get a +process ID (PID), which is a value to specify in the debugger command we +discussed above. We present two ways to get a PID here. + +The first way is to use Firefox itself. Open a new tab and go to the +**about:processes** page. This page shows the list of all processes and their +PIDs. In the example below, the PID of the main process is **6308** and the +PID of the tab process hosting a page of mozilla.org is **6748**. + +.. image:: img/about-processes.png + +The second way is to use `Process Explorer +<https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer>`__, +which is provided by Microsoft for free. You may need this technique to attach +a debugger to a hung process or when you cannot open a new tab in the existing +Firefox for some reason. + +Process Explorer is basically an advanced version of Task Manager. Since it +displays processes in a hierarchical tree view, you can easily locate the main +process, which is the parent of all child processes. In the example below, the +PID of the main process is **6308** and all processes, including +plugin-container.exe, under the main process is child processes. + +Another helpful feature of Process Explorer is that when you hover the mouse +cursor on a process, it displays a tooltip window showing the process's command +line string. For a child process of firefox.exe, the command line's last +keyword shows the process type, so you can tell which process is which process +type. In the example below, the tooltip window displays a command line string +of a GPU process. + +.. image:: img/process-explorer.png + + +How to find the location of firefox.exe +--------------------------------------- + +If you're not sure about the location of the executable file (firefox.exe) of +Firefox you run, you can find it in the **about:support** page. In the +"Application Basics" section, the path to firefox.exe is displayed in the row +of "Application Binary". + +.. image:: img/about-support.png + +.. |WinDbg in Start Menu| image:: img/windbg-in-startmenu.png + :width: 50% diff --git a/docs/contributing/debugging/debugging_a_hang_on_macos.rst b/docs/contributing/debugging/debugging_a_hang_on_macos.rst new file mode 100644 index 0000000000..ee2bed16b2 --- /dev/null +++ b/docs/contributing/debugging/debugging_a_hang_on_macos.rst @@ -0,0 +1,10 @@ +Debugging A Hang On macOS +========================= + +See `How to Report a Hung +Firefox <https://developer.mozilla.org/en-US/docs/Mozilla/How_to_report_a_hung_Firefox>`_. + +See also +~~~~~~~~ + +`Debugging on macOS <https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_on_macOS>`__ diff --git a/docs/contributing/debugging/debugging_a_minidump.rst b/docs/contributing/debugging/debugging_a_minidump.rst new file mode 100644 index 0000000000..5638c29d85 --- /dev/null +++ b/docs/contributing/debugging/debugging_a_minidump.rst @@ -0,0 +1,202 @@ +Debugging A Minidump +==================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +The +`minidump <http://msdn.microsoft.com/en-us/library/windows/desktop/ms680369%28v=vs.85%29.aspx>`__ +file format contains data about a crash on Windows. It is used by +`rust-minidump <https://github.com/luser/rust-minidump>`__, +`Breakpad <https://wiki.mozilla.org/Breakpad>`__, and also by various +Windows debugging tools. Each minidump includes the following data. + +- Details about the exception which led to the crash. +- Information about each thread in the process: the address which was + executing and the register state at the time the process stopped. +- A list of shared libraries loaded into the process at the time of the + crash. +- The stack memory of each thread. +- The memory right around the crashing address. +- (Optional) Other memory regions, if requested by the application. +- (Optional) Other platform-specific data. + +Accessing minidumps from crash reports +-------------------------------------- + +Minidumps are not available to everyone. For details on how to gain +access and where to find minidump files for crash reports, consult the +:ref:`crash report documentation <Understanding Crash Reports>` + +Using rust-minidump's tooling +----------------------------------- + +Most of our crash-reporting infrastructure is based on rust-minidump. +The primary tool for this is the +`minidump-stackwalk <https://github.com/luser/rust-minidump/tree/master/minidump-stackwalk>`__ +CLI application, which includes extensive user documentation. + +That documentation includes a +`dedicated section <https://github.com/luser/rust-minidump/tree/master/minidump-stackwalk#analyzing-firefox-minidumps>`__ +on locally analyzing Firefox crashreports and minidumps. + +If you're looking for minidump_dump, it's included as part of +minidump-stackwalk. + +Using the MS Visual Studio debugger +----------------------------------- + +#. Set up the debugger to :ref:`use the Mozilla symbol + server <Using The Mozilla Symbol Server>` and + :ref:`source server <Using The Mozilla Source Server>`. +#. Double-click on the minidump file to open it in the debugger. +#. When it loads, click the green icon in the visual studio debugger + toolbar that looks like a play button. + +For Firefox releases older than Firefox 41, you will also need to +install the relevant release of Firefox (for example from +`here <https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/>`__), +and add the directory it is in (e.g., "C:\Program Files\Mozilla +Firefox 3.6 Beta 1\") to the same dialog in which you set up the +symbol server (in case the binary location in the minidump is not the +same as the one on your machine). Note that you can install the +relevant release anywhere. Just make sure to configure the symbol +server to the directory where you installed it. For releases from 41 +onward, the binaries are available on the symbol server. + +If this doesn't work, downloading the exact build and crashreporter +symbols full files. These can be found in treeherder / build folder. +Load Visual Studio, and go to file -> open -> minidump location. Click +on "Run Native", and Visual Studio will ask for the corresponding symbol +files. For each .dll you wish to have symbols for, you must go to a +console and go to the corresponding directory. E.g. (xul.dll should go +to xul.pdf in the crashreporter symbols directory). Each directory will +have a .pd\_ file. In a command shell run: "expand /r foo.pd\_". Then +point Visual Studio to this directory. + +Then you'll be able to examine: + ++------------------+-------------------------------------------------------------------------+ +| stack trace | The debugger shows the stack trace. You can right-click on any frame | +| | in the stack, and then choose "go to disassembly" or "go to source". | +| | (Choosing "go to disassembly" from the source view might not get you | +| | to the right place due to optimizations.) When looking at the | +| | source, beware that the debugging information will associate all | +| | inlined functions as part of the line into which they were inlined, | +| | and compiler (with PGO) inlines *very* aggressively (including | +| | inlining virtual functions). You can often figure out where you | +| | *really* are by reading the disassembly. | ++------------------+-------------------------------------------------------------------------+ +| registers | In the Registers tab (Debug->Windows->Registers if you don't have | +| | it open), you can look at the registers associated with each stack | +| | frame, but only at the current state (i.e., the time of the crash). | +| | Registers that Visual Studio can't figure out will be grayed-out and | +| | have the value 00000000. | ++------------------+-------------------------------------------------------------------------+ +| stack memory | You open a window (Memory 1, etc.) that shows contiguous segments of | +| | memory using the Debug->Windows->Memory menu item. You can then | +| | enter the address of the stack pointer (ESP register) in this window | +| | and look at the memory on the stack. (The minidump doesn't have the | +| | memory on the heap.) It's a good idea to change the "width" dropdown | +| | in the top right corner of the window from its default "Auto" to | +| | either "8" or "16" so that the memory display is word-aligned. If | +| | you're interested in pointers, which is usually the case, you can | +| | right click in this window and change the display to show 4-byte | +| | words (so that you don't have to reverse the order due to | +| | little-endianness). This view, combined with the disassembly, can | +| | often be used to reconstruct information beyond what in shown the | +| | function parameters. | ++------------------+-------------------------------------------------------------------------+ +| local variables | In the Watch 1 (etc.) window (which, if you don't have open, you can | +| | iget from Debug->Windows->Watch), you can type an expression | +| | (e.g., the name of a local variable) and the debugger will show you | +| | its value (although it sometimes gets confused). If you're looking | +| | at a pointer to a variable that happens to be on the stack, you can | +| | even examine member variables by just typing expressions. If Visual | +| | Studio can't figure something out from the minidump, it might show | +| | you 00000000 (is this true?). | ++------------------+-------------------------------------------------------------------------+ + +Using minidump-2-core on Linux +------------------------------ + +The `Breakpad +source <https://chromium.googlesource.com/breakpad/breakpad/+/master/>`__ +contains a tool called +`minidump-2-core <https://chromium.googlesource.com/breakpad/breakpad/+/master/src/tools/linux/md2core/>`__, +which converts Linux minidumps into core files. If you checkout and +build Breakpad, the binary will be at +``src/tools/linux/md2core/minidump-2-core``. Running the binary with the +path to a Linux minidump will generate a core file on stdout which can +then be loaded in gdb as usual. You will need to manually download the +matching Firefox binaries, but then you can use the :ref:`GDB Python +script <Downloading symbols on Linux / Mac OS X>` to download symbols. + +The ``minidump-2-core`` source does not currently handle processing +minidumps from a different CPU architecture than the system it was +built for. If you want to use it on an ARM dump, for example, you may +need to build the tool for ARM and run it under QEMU. + +Using other tools to inspect minidump data +------------------------------------------ + +Ted has a few tools that can be built against an already-built copy of +Breakpad to do more targeted inspection. All of these tools assume you +have checked out their source in a directory next to the breakpad +checkout, and that you have built Breakpad in an objdir named +``obj-breakpad`` at the same level. + +- `stackwalk-http <https://hg.mozilla.org/users/tmielczarek_mozilla.com/stackwalk-http/>`__ + is a version of the breakpad's minidump_stackwalk that can fetch symbols + over HTTP, and also has the Mozilla symbol server URL baked in. If you + run it like ``stackwalk /path/to/dmp /tmp/syms`` it will print the stack + trace and save the symbols it downloaded in ``/tmp/syms``. Note that + symbols are only uploaded to the symbol server for nightly and + release builds, not per-change builds. +- `dump-lookup <https://hg.mozilla.org/users/tmielczarek_mozilla.com/dump-lookup/>`__ + takes a minidump and prints values on the stack that are potential + return addresses. This is useful when a stack trace looks truncated + or otherwise wrong. It needs symbol files to produce useful output, + so you will generally want to have run ``stackwalk-http`` to download + them first. +- `get-minidump-instructions <https://hg.mozilla.org/users/tmielczarek_mozilla.com/get-minidump-instructions/>`__ + retrieves and displays the memory range surrounding the faulting + instruction pointer from a minidump. You will almost always want to + run it with the ``--disassemble`` option, which will make it send the + bytes through ``objdump`` to display the disassembled instructions. + If you also give it a path to symbols (see ``stackwalk-http`` above) + it can download the matching source files from hg.mozilla.org and + display source interleaved with the disassembly. +- `minidump-modules <http://hg.mozilla.org/users/tmielczarek_mozilla.com/minidump-modules>`__ + takes a minidump and prints the list of modules from the crashed + process. It will print the full path to each module, whereas the + Socorro UI only prints the filename for each module for privacy + reasons. It also accepts a -v option to print the debug ID for each + module, and a -d option to print relative paths to the symbol files + that would be used instead of the module filenames. + +Getting a stack trace from a crashed B2G process +------------------------------------------------ + +#. Get the minidump file in the phone at + /data/b2g/mozilla/\*.default/minidump/. You can use `adb + pull <http://developer.android.com/tools/help/adb.html>`__ for that. +#. Build the debug symbols using the command ./build.sh buildsymbols + inside the B2G tree. The symbol files will be generated in + $OBJDIR/dist/crashreporter-symbols. +#. Build and install + `google-breakpad <https://code.google.com/p/google-breakpad/>`__. +#. Use the + `minidump-stackwalk <https://github.com/luser/rust-minidump/tree/master/minidump-stackwalk>`__ + tool to get the stack trace. + +.. code:: bash + + Example: + + $ cd B2G + $ adb pull /data/b2g/mozilla/*.default/minidump/*.dmp . + $ls *.dmp + 71788789-197e-d769-67167423-4e7aef32.dmp + $ minidump-stackwalk 71788789-197e-d769-67167423-4e7aef32.dmp objdir-debug/dist/crashreporter-symbols/ diff --git a/docs/contributing/debugging/debugging_firefox_with_gdb.rst b/docs/contributing/debugging/debugging_firefox_with_gdb.rst new file mode 100644 index 0000000000..8b188edc85 --- /dev/null +++ b/docs/contributing/debugging/debugging_firefox_with_gdb.rst @@ -0,0 +1,501 @@ +Debugging Firefox with GDB +========================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +This page details how you can more easily debug Firefox and work around +some GDB problems. + +Use GDB 5, or higher. A more recent version of GDB can be obtained from +`sourceware <https://sourceware.org/gdb/>`__ or your Linux distro repo. +If you are running less than 256 MB of RAM, be sure to see `Using gdb on +wimpy computers <https://developer.mozilla.org/en/Using_gdb_on_wimpy_computers>`__. + +Where can I find general gdb documentation? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Using GDB is beyond the scope of this document. Documentation is likely +available on your system if you have GDB installed, in the form of +**info,** **man** pages, or the gnome help browser. Additionally, you +can use a graphical front-end to GDB like +`ddd <https://www.gnu.org/software/ddd/>`__ or +`insight <https://sourceware.org/insight/>`__. For more information see +https://sourceware.org/gdb/current/onlinedocs/gdb/ + +How do I run Firefox under gdb? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The preferred method, is using the +:ref:`mach` command-line tool to run the +debugger, which can bypass several optional defaults. Use "mach help +run" to get more details. If inside the source directory, you would use +"./mach". Please note that :ref:`mach is aware of mozconfigs <mach_and_mozconfigs>`. + +.. code:: bash + + $ ./mach run --debug [arguments to pass to firefox] + +If you need to direct arguments to gdb, you can use '--debugger-args' +options via the command line parser, taking care to adhere to shell +splitting rules. For example, if you wanted to run the command 'show +args' when gdb starts, you would use: + +.. code:: bash + + $ ./mach run --debug --debugger-args "-ex 'show args'" + +Alternatively, you can run gdb directly against Firefox. However, you +won't get some of the more useful capabilities this way. For example, +mach sets an environment variable (see below) to stop the JS engine from +generating synthetic segfaults to support the slower script dialoging +mechanism. + +.. code:: + + (gdb) OBJDIR/dist/bin/firefox + +How do I pass arguments in prun? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Set the arguments in GDB before calling prun. Here's an example on how +to do that: + +.. code:: + + (gdb) set args https://www.mozilla.org + (gdb) prun + +How do I set a breakpoint in a library that hasn't been loaded? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +GDB 6.1 and above has support for "pending breakpoints". This is +controlled by the "``set breakpoint pending``" setting, and is enabled +by default. If a breakpoint cannot be immediately resolved, it will be +re-checked each time a shared library is loaded, by the process being +debugged. If your GDB is older than this, you should upgrade. + +In older versions, there isn't a way to set breakpoints in a library +that has not yet been loaded. See more on `setting a breakpoint when a +component is +loaded <#How_do_I_set_a_breakpoint_when_a_component_is_loaded.3F>`__. If +you have to set a breakpoint you can set a breakpoint in ``_dl_open``. +This function is called when a new library is loaded, when you can +finally set your breakpoint. + +How do I set a breakpoint when a component is loaded? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In Firefox Version 57 (and possibly earlier) XPCOM_BREAK_ON_LOAD does +not seem to exist. + +There's a facility in XPCOM which allows you to set an environment +variable to drop into the debugger when loading a certain component. You +have to set ``XPCOM_BREAK_ON_LOAD`` variable before you run Firefox, +setting it to a string containing the names of libraries you want to +load. For example, if you wish to stop when a library named ``raptor`` +or ``necko`` is loaded, you set the variable to ``raptor:necko``. Here's +an example: + +.. code:: + + (gdb) set env XPCOM_BREAK_ON_LOAD raptor:necko + (gdb) prun + +Why can't I set a breakpoint? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You probably can't set a breakpoint because its library hasn't been +loaded. Most Firefox functionality is in libraries loaded mid-way +through the ``main()``\ function. If you break on ``main(),``\ and step +through until the libraries are loaded, with a call to +``InitCOMGlue()``, you should be able to set breakpoints on many more +symbols, source files, and continue running. + +.. code:: + + (gdb) break main + (gdb) run + Breakpoint 1, main(argc=4, argv=0x7fffffffde98, envp=0x7ffffffffdec0) ..... + 256 { + (gdb) next + ... + 293 nsresult rv = InitXPCOMGlue() + (gdb) next + +If you still can't set the breakpoints, you need to confirm the library +has loaded. You can't proceed until the library loads. See more on +`loading shared libraries <#How_do_I_load_shared_libraries.3F>`__. If +you wish to break as soon as the library is loaded, see the section on +`breaking when a component is +loaded <#How_do_I_set_a_breakpoint_when_a_component_is_loaded.3F>`__ and +`breaking on a library +load <#How_do_I_set_a_breakpoint_when_a_component_is_loaded.3F>`__. + +How do I display PRUnichar's? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One suggestion is this: + +.. code:: + + (gdb) print ((PRUnichar*)uri.mBuffer)[0]@16 + $47 = {114, 100, 102, 58, 110, 117, 108, 108, 0, 0, 8, 0, 0, 0, 37432, + 16514} + + + +.. code:: + + (gdb) print aURI + $1 = (const PRUnichar *) 0x855e6e0 + (gdb) x/32ch aURI + 0x855e6e0: 104 'h' 116 't' 116 't' 112 'p' 58 ':' 47 '/' 47 '/' 119 'w' + 0x855e6f0: 119 'w' 119 'w' 46 '.' 109 'm' 111 'o' 122 'z' 105 'i' 108 'l' + 0x855e700: 108 'l' 97 'a' 46 '.' 111 'o' 114 'r' 103 'g' 47 '/' 115 's' + 0x855e710: 116 't' 97 'a' 114 'r' 116 't' 47 '/' 0 '\0' 25 '\031' 0 '\0' + (gdb) + +- Define helper functions in your .gdbinit + +.. code:: + + # Define a "pu" command to display PRUnichar * strings (100 chars max) + # Also allows an optional argument for how many chars to print as long as + # it's less than 100. + def pu + set $uni = $arg0 + if $argc == 2 + set $limit = $arg1 + if $limit > 100 + set $limit = 100 + end + else + set $limit = 100 + end + # scratch array with space for 100 chars plus null terminator. Make + # sure to not use ' ' as the char so this copy/pastes well. + set $scratch = "____________________________________________________________________________________________________" + set $i = 0 + set $scratch_idx = 0 + while (*$uni && $i++ < $limit) + if (*$uni < 0x80) + set $scratch[$scratch_idx++] = *(char*)$uni++ + else + if ($scratch_idx > 0) + set $scratch[$scratch_idx] = '\0' + print $scratch + set $scratch_idx = 0 + end + print /x *(short*)$uni++ + end + end + if ($scratch_idx > 0) + set $scratch[$scratch_idx] = '\0' + print $scratch + end + end + + # Define a "ps" command to display subclasses of nsAC?String. Note that + # this assumes strings as of Gecko 1.9 (well, and probably a few + # releases before that as well); going back far enough will get you + # to string classes that this function doesn't work for. + def ps + set $str = $arg0 + if (sizeof(*$str.mData) == 1 && ($str.mFlags & 1) != 0) + print $str.mData + else + pu $str.mData $str.mLength + end + end + +`This is hard. Give me a .gdbinit that already has the +functions. <#This_is_hard._Give_me_a_.gdbinit_that_works.>`__ + +- Define a small helper function "punichar" in #ifdef NS_DEBUG code + somewhere. + +How do I display an nsString? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can call the ToNewCString() method on the nsString. It leaks a +little memory but it shouldn't hurt anything if you only do it a few +times in one gdb session. (via akkana@netscape.com) + +.. code:: + + (gdb) p string.ToNewCString() + +Another method (via bent) is the following (replace ``n`` with: the +returned length of your string): + +.. code:: + + (gdb) p string.Length() + $1 = n + (gdb) x/ns string.BeginReading() + +You can of course use any of the above unichar-printing routines instead +of x/s. + +This is hard. Give me a .gdbinit that works. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See `Boris Zbarsky's +.gdbinit <http://web.mit.edu/bzbarsky/www/gdbinit>`__. It contained +several function definitions including: + +- "prun" to start the browser and disable library loading. +- "pu" which will display a (PRUnichar \*) string. +- "ps" which will display a nsString. + +How do I determine the concrete type of an object pointed to by an interface pointer? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can determine the concrete type of any object pointed to, by an +XPCOM interface pointer, by looking at the mangled name of the symbol +for the object's vtable: + +.. code:: + + (gdb) p aKidFrame + $1 = (nsIFrame *) 0x85058d4 + (gdb) x/wa *(void**)aKidFrame + 0x4210d380 <__vt_14nsRootBoxFrame>: 0x0 + (gdb) p *(nsRootBoxFrame*)aKidFrame + [ all the member variables of aKidFrame ] + +If you're using gcc 3.x, the output is slightly different from the gcc +2.9x output above. Pay particular attention to the vtable symbol, in +this case ``__vt_14nsRootBoxFrame``. You won't get anything useful if +the shared library containing the object is not loaded. See `How do I +load shared libraries? <#How_do_I_load_shared_libraries.3F>`__ and `How +do I see what libraries I already have +loaded? <#How_do_I_see_what_libraries_I_already_have_loaded.3F>`__ + +Or use the gdb command ``set print object on``. + +How can I debug JavaScript from gdb? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have JavaScript Engine code on the stack, you'll probably want a +JS stack in addition to the C++ stack. + +.. code:: + + (gdb) call DumpJSStack() + +See `https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript <https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript>`__ +for more JS debugging tricks. + +How can I debug race conditions and/or how can I make something different happen at NS_ASSERTION time? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +| [submitted by Dan Mosedale] +| As Linux is unable to generate useful core files for multi-threaded + applications, tracking down race-conditions which don't show up under + the debugger can be a bit tricky. Unless you've given the + ``--enable-crash-on-assert`` switch to ``configure``, you can now + change the behavior of ``NS_ASSERTION`` (nsDebug::Break) using the + ``XPCOM_DEBUG_BREAK`` environment variable. + +How do I run the debugger in emacs/xemacs? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Emacs and XEmacs contain modes for doing visual debugging. However, you +might want to set up environment variables, specifying the loading of +symbols and components. The easiest way to set up these is to use the +``run-mozilla.sh`` script, located in the dist/bin directory of your +build. This script sets up the environment to run the editor, shell, +debugger, or defining a preferred setup and running any commands you +wish. For example: + +.. code:: bash + + $ ./run-mozilla.sh /bin/bash + MOZILLA_FIVE_HOME=/home/USER/src/mozilla/build/dist/bin + LD_LIBRARY_PATH=/home/USER/src/mozilla/build/dist/bin + LIBRARY_PATH=/home/USER/src/mozilla/build/dist/bin + SHLIB_PATH=/home/USER/src/mozilla/build/dist/bin + LIBPATH=/home/USER/src/mozilla/build/dist/bin + ADDON_PATH=/home/USER/src/mozilla/build/dist/bin + MOZ_PROGRAM=/bin/bash + MOZ_TOOLKIT= + moz_debug=0 + moz_debugger= + +GDB 5 used to work for me, but now Firefox won't start. What can I do? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A recent threading change (see `bug +57051 <https://bugzilla.mozilla.org/show_bug.cgi?id=57051>`__ for +details) caused a problem on some systems. Firefox would get part-way +through its initialization, then stop before showing a window. A recent +change to gdb has fixed this. Download and build `the latest version of +Insight <https://sources.redhat.com/insight/>`__, or if you don't want a +GUI, `the latest version of gdb <https://sources.redhat.com/gdb/>`__. + +"run" or "prun" in GDB fails with "error in loading shared libraries." +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Running mozilla-bin inside GDB fails with an error message like: + +.. code:: + + Starting program: + /u/dmose/s/mozilla/mozilla-all/mozilla/dist/bin/./mozilla-bin + /u/dmose/s/mozilla/mozilla-all/mozilla/dist/bin/./mozilla-bin: error + in loading shared libraries: libraptorgfx.so: cannot open shared + object file: No such file or directory + +Your LD_LIBRARY_PATH is probably being reset by your .cshrc or .profile. +From the GDB manual: + +*\*Warning:\* GDB runs your program using the shell indicated by your +'SHELL' environment variable if it exists (or '/bin/sh' if not). If your +'SHELL' variable names a shell that runs an initialization file -- such +as '.cshrc' for C-shell, or '.bashrc' for BASH--any variables you set in +that file affect your program. You may wish to move the setting of +environment variables to files that are only run when you sign on, such +as '.login' or '.profile'.* + +Debian's GDB doesn't work. What do I do? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Debian's unstable distribution currently uses glibc 2.1 and GDB 4.18. +However, there is no package of GDB for Debian with the appropriate +threads patches that will work with glibc 2.1. I was able to get this to +work by getting the GDB 4.18 RPM from Red Hat's rawhide server and +installing that. It has all of the patches necessary for debugging +threaded software. These fixes are expected to be merged into GDB, which +will fix the problem for Debian Linux. (via `Bruce +Mitchener <mailto:bruce@cybersight.com>`__) + +Firefox is aborting. Where do I set a breakpoint to find out where it is exiting? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On Linux there are two possible symbols that are causing this: +``PR_ASSERT()`` and ``NS_ASSERTION()``. To see where it's asserting you +can stop at two places: + +.. code:: + + (gdb) b abort + (gdb) b exit + +I keep getting a SIGSEGV in JS/JIT code under gdb even though there is no crash when gdb is not attached. How do I fix it? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Set the JS_DISABLE_SLOW_SCRIPT_SIGNALS environment variable (in FF33, +the shorter and easier-to-remember JS_NO_SIGNALS). For an explanation, +read `Jan's blog +post <https://www.jandemooij.nl/blog/2014/02/18/using-segfaults-to-interrupt-jit-code/>`__. + +I keep getting a SIG32 in the debugger. How do I fix it? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are getting a SIG32 while trying to debug Firefox you might have +turned off shared library loading before the pthreads library was +loaded. For example, ``set auto-solib-add 0`` in your ``.gdbinit`` file. +In this case, you can either: + +- Remove it and use the method explained in the section about `GDB's + memory + usage <#The_debugger_uses_a_lot_of_memory._How_do_I_fix_it.3F>`__ +- Use ``handle SIG32 noprint`` either in gdb or in your ``.gdbinit`` + file + +Alternatively, the problem might lie in your pthread library. If this +library has its symbols stripped, then GDB can't hook into thread +events, and you end up with SIG32 signals. You can check if your +libpthread is stripped in ``file /lib/libpthread*`` and looking for +``'stripped'.``\ To fix this problem on Gentoo Linux, you can re-emerge +glibc after adding ``"nostrip"`` to your ``FEATURES`` in +``/etc/make.conf``. + +How do I get useful stack traces inside system libraries? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many Linux distributions provide separate packages with debugging +information for system libraries, such as gdb, Valgrind, profiling +tools, etc., to give useful stack traces via system libraries. + +Fedora +^^^^^^ + +On Fedora, you need to enable the debuginfo repositories, as the +packages are in separate repositories. Enable them permanently, so when +you get updates you also get security updates for these packages. A way +to do this is edit ``/etc/yum.repos.d/fedora.repo`` and +``fedora-updates.repo`` to change the ``enabled=0`` line in the +debuginfo section to ``enabled=1``. This may then flag a conflict when +upgrading to a new distribution version. You would the need to perform +this edit again. + +You can finally install debuginfo packages with yum or other package +management tools. The best way is install the ``yum-utils`` package, and +then use the ``debuginfo-install`` command to install all the debuginfo: + +.. code:: bash + + $ yum install yum-utils + $ debuginfo-install firefox + +This can be done manually using: + +.. code:: bash + + $ yum install GConf2-debuginfo ORBit2-debuginfo atk-debuginfo \ + cairo-debuginfo dbus-debuginfo dbus-glib-debuginfo expat-debuginfo \ + fontconfig-debuginfo freetype-debuginfo gcc-debuginfo glib2-debuginfo \ + glibc-debuginfo gnome-vfs2-debuginfo gtk2-debuginfo gtk2-engines-debuginfo \ + hal-debuginfo libX11-debuginfo libXcursor-debuginfo libXext-debuginfo \ + libXfixes-debuginfo libXft-debuginfo libXi-debuginfo libXinerama-debuginfo \ + libXrender-debuginfo libbonobo-debuginfo libgnome-debuginfo \ + libselinux-debuginfo pango-debuginfo popt-debuginfo scim-bridge-debuginfo + +Debugging electrolysis (e10s) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``mach run`` and ``mach test`` both accept a ``--disable-e10s`` +argument. Some debuggers can't catch child-process crashes without it. + +You can find some (outdated) information on +https://wiki.mozilla.org/Electrolysis/Debugging. You may also like to +read +https://mikeconley.ca/blog/2014/04/25/electrolysis-debugging-child-processes-of-content-for-make-benefit-glorious-browser-of-firefox +for a more up-to-date blog post. + +To get the child process id use: + +.. code:: + + MOZ_DEBUG_CHILD_PROCESS=1 mach run + +See also +~~~~~~~~~ + +- `Debugging <https://developer.mozilla.org/En/Debugging>`__ +- `Performance tools <https://wiki.mozilla.org/Performance:Tools>`__ +- `Fun with + gdb <https://blog.mozilla.com/sfink/2011/02/22/fun-with-gdb/>`__ by + Steve Fink +- `Archer pretty printers for + SpiderMonkey <https://hg.mozilla.org/users/jblandy_mozilla.com/archer-mozilla>`__ + (`blog + post <https://itcouldbesomuchbetter.wordpress.com/2010/12/20/debugging-spidermonkey-with-archer-2/>`__) +- `More pretty + printers <https://hg.mozilla.org/users/josh_joshmatthews.net/archer-mozilla/>`__ + for Gecko internals (`blog + post <https://www.joshmatthews.net/blog/2011/06/nscomptr-has-never-been-so-pretty/>`__) + +.. container:: originaldocinfo + + .. rubric:: Original Document Information + :name: Original_Document_Information + + - `History <http://bonsai-www.mozilla.org/cvslog.cgi?file=mozilla-org/html/unix/debugging-faq.html&rev=&root=/www/>`__ + - Copyright Information: © 1998-2008 by individual mozilla.org + contributors; content available under a `Creative Commons + license <https://www.mozilla.org/foundation/licensing/website-content.html>`__ diff --git a/docs/contributing/debugging/debugging_firefox_with_lldb.rst b/docs/contributing/debugging/debugging_firefox_with_lldb.rst new file mode 100644 index 0000000000..99ae5a60c0 --- /dev/null +++ b/docs/contributing/debugging/debugging_firefox_with_lldb.rst @@ -0,0 +1,80 @@ +Debugging Firefox with LLDB +=========================== + +See http://lldb.llvm.org/index.html. + +Mozilla-specific lldb settings +------------------------------ + +There's an +``.lldbinit`` `file <https://searchfox.org/mozilla-central/source/.lldbinit>`_ +in the Mozilla source tree, which applies recommended settings and +includes a few type summaries and Mozilla-specific debugging commands +via the lldbutils module (see +`python/lldbutils/README.txt <https://searchfox.org/mozilla-central/source/python/lldbutils/README.txt>`__). +For information about available features see the links above and the `Using +LLDB to debug Gecko <http://mcc.id.au/blog/2014/01/lldb-gecko>`__ blog +post. + +The in-tree ``.lldbinit`` should be loaded automatically in most cases +when running lldb from the command line (e.g. using +:ref:`mach`), but **not** +when using Xcode. See :ref:`Debugging on macOS` for information on setting up +Xcode. + +.. warning:: + + LLDB warning: Xcode 5 only comes with lldb (gdb is gone). The + introduction and use of UNIFIED_SOURCES in the source starting around + November 2013 has broken the default LLDB configuration so that it + will not manage to resolve breakpoints in files that are build using + UNIFIED_SOURCES (the breakpoints will be listed as "pending", and + lldb will not stop at them). To fix this add the following to your + $HOME/.lldbinit file: + + .. code:: + + # Mozilla's use of UNIFIED_SOURCES to include multiple source files into a + # single compiled file breaks lldb breakpoint setting. This works around that. + # See http://lldb.llvm.org/troubleshooting.html for more. + settings set target.inline-breakpoint-strategy always + + Restart Xcode/lldb and restart your debugging session. If that still + doesn't fix things then try closing Xcode/lldb, doing a clobber + build, reopening Xcode/lldb, and restarting your debugging session. + +Starting a debugging session +---------------------------- + +Attaching to an existing process +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can attach to Firefox with following command: + +.. code:: + + (lldb) process attach --name firefox + +Some versions of lldb causes crashes after attaching to Firefox. + +Running a new process +~~~~~~~~~~~~~~~~~~~~~ + +To start Firefox under the debugger, run ``lldb`` followed by "--", +followed by the command line you'd like to run, like this: + +.. code:: bash + + $ lldb -- obj-ff-dbg/dist/Nightly.app/Contents/MacOS/firefox-bin -no-remote -profile /path/to/profile + +Then set breakpoints you need and start the process: + +.. code:: + + (lldb) breakpoint set --name nsInProcessTabChildGlobal::InitTabChildGlobal + Breakpoint created: 1: name = 'nsInProcessTabChildGlobal::InitTabChildGlobal', locations = 0 (pending) + WARNING: Unable to resolve breakpoint to any actual locations. + + (lldb) r + Process 7602 launched: '/.../obj-ff-opt/dist/Nightly.app/Contents/MacOS/firefox-bin' (x86_64) + 1 location added to breakpoint 1 diff --git a/docs/contributing/debugging/debugging_firefox_with_rr.rst b/docs/contributing/debugging/debugging_firefox_with_rr.rst new file mode 100644 index 0000000000..ef68d9c6ea --- /dev/null +++ b/docs/contributing/debugging/debugging_firefox_with_rr.rst @@ -0,0 +1,98 @@ +Debugging Firefox with rr +========================= + +This page is intended to help Firefox/Gecko developers get started using rr to debug Firefox. + +Prerequisites +------------- + +You must have Linux installed with a recent kernel. If you're not running Linux already, an option is set up a virtual machine in which to record Firefox. Be forewarned though that + + * rr requires a VM hypervisor that virtualizes CPU performance counters. VMWare Workstation supports that. + * there's a 20% or so performance hit from running in a VM; generally speaking recorder overhead increases from ~1.2x to ~1.4x. (It's a feather in the cap of the hypervisor authors that the hit is that small, though!) + * Some features (reverse execution) `may not work well in VMWare <https://robert.ocallahan.org/2014/09/vmware-cpuid-conditional-branch.html>`__ due to a VMWare optimization that can be disabled `this way <http://robert.ocallahan.org/2015/11/rr-in-vmware-solved.html>`__. + +When using VSCode, consider adding the `Midas <https://github.com/farre/midas>`__ addon to debug rr traces from the editor. You can use Midas to install / build rr and to configure the :code:`auto-load safe path` via the setup commands. + +Ensure that you've `installed <http://rr-project.org/>`__ or `built <https://github.com/mozilla/rr/wiki/Building-And-Installing>`__ rr and have `used it successfully <https://github.com/mozilla/rr/wiki/Usage>`__. Check that you have the latest version. + +You likely need to configure your :code:`auto-load safe path` for rr / gdb to work correctly. If you are on Linux and your builds are in ~/moz, then add the following to ~/.gdbinit + +.. code:: + + add-auto-load-safe-path ~/moz + +Firefox developers are strongly encouraged to build rr from source. If your Firefox patch triggers a bug in rr, rr developers will fix that bug with high priority. You might be able to pull a fix within a few hours or days instead of waiting for the next release. + +Recording Firefox +----------------- + + +To record Firefox running normally, simply launch it under rr as you would if running it under valgrind or gdb + +.. code:: bash + + $ rr $ff-objdir/dist/bin/firefox ... + +or use mach + +.. code:: bash + + $ ./mach run --debugger=rr + +This will save a trace to your working directory as described in the `usage instructions <https://github.com/mozilla/rr/wiki/Usage>`__. Please refer to `those instructions <https://github.com/mozilla/rr/wiki/Usage>`__ for details on how to debug the recording, which isn't covered in this document. + +Sandboxing reduces recording performance because of the SIGSYS signals and extra syscall. Disabling it can help. + +The background hang monitor might also be making things worse by causing a lot of extra syscalls. It can be disabled by setting +toolkit.content-background-hang-monitor.disabled=true. + +SIGSYS +------ + +When recording and replaying Firefox running with the Linux sandbox, you will get SIGSYS signals frequently. This is expected behavior caused by the sandbox. In gdb, use handle SIGSYS noprint nostop to suppress the signals. + +Recording test suites +--------------------- + +You can use the test runners' --debugger feature to punch rr down through the layers of python script to where Firefox is launched. This is used in the same way you would use --debugger to run valgrind or gdb, for example: + +.. code:: bash + + $ ./mach mochitest --debugger=rr ... + +The test harnesses disable the slow-script timeout when the --debugger argument is passed. That's usually sensible, because you don't want those warnings being generated while Firefox is stopped in gdb. However, this has been `observed to change Gecko behavior <https://bugzilla.mozilla.org/show_bug.cgi?id=986673>`__. rr doesn't need to have the slow-script timeout disabled, so to avoid those kinds of pitfalls, pass the --slowscript argument to the test harness. + +To run rr in chaos mode: + +.. code:: bash + + $ ./mach mochitest --debugger=rr --debugger-args="record --chaos" + +You can also run the entire test harness in rr: + +.. code:: bash + + $ rr ./mach mochitest ... + +The trace will contain many processes, so to debug the correct one, you'll want to use rr ps or rr replay -p firefox etc. + +Working with multiple processes +------------------------------ + +rr should work out of the box with multi-process Firefox. Once you have a recording you can use rr ps to show all the process that were recorded and rr replay -p <pid> to attach to a particular process. + +If you want to debug a particular part of code, you can use the :code:`MOZ_DBG` macro and :code:`getpid()` function to write the process id to stderr. `MOZ_LOG <https://firefox-source-docs.mozilla.org/xpcom/logging.html>`__ will include the pid in log messages by default. + +You can combine that with the -M and -g flags to jump to a particular point in a particular process's lifetime. + +Get help! +--------- + +If you encounter a problem with rr, please `file an issue <https://github.com/mozilla/rr/issues>`__. Firefox bugs are high priority, so usually your issue can be fixed very quickly. + +If you want to chat with rr developers, because you need more help or want to contribute or want to complain, we hang out in the `#rr channel <https://chat.mozilla.org/#/room/#rr:mozilla.org>`__. There is also a channel for `#midas <https://chat.mozilla.org/#/room/#midas:mozilla.org>`__. + +You also may find `these debugging protips <https://github.com/mozilla/rr/wiki/Debugging-protips>`__ helpful, though many are for rr developers, not users. + +Happy debugging! diff --git a/docs/contributing/debugging/debugging_firefox_with_valgrind.rst b/docs/contributing/debugging/debugging_firefox_with_valgrind.rst new file mode 100644 index 0000000000..33aab3638a --- /dev/null +++ b/docs/contributing/debugging/debugging_firefox_with_valgrind.rst @@ -0,0 +1,177 @@ +Debugging Firefox with Valgrind +=============================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +This page describes how to use Valgrind (specifically, its Memcheck +tool) to find memory errors. + +Supported platforms +------------------- + +Valgrind runs desktop Firefox fine on Linux, especially on x86 and +x86-64. Firefox for Android and Firefox OS on ARMv7 should also run, +though perhaps not as smoothly. The other architectures supported by +Valgrind on Linux (AARCH64, PPC{32,64}, MIPS{32,64}, S390X) should also +work, in theory. + +MacOS X 10.10 (Yosemite), 64-bit only, works, although it can be a bit +of a rough ride. + +- Expect lower performance and a somewhat higher false positive error + rate than on Linux. +- Valgrind's handling of malloc zones on Yosemite is imperfect. Regard + leak reports with caution. +- Valgrind has been known to cause kernel panics, for unknown reasons. + +Where to get Valgrind +--------------------- + +Linux: Download `Valgrind <https://valgrind.org/>`__ directly, or use +your distribution's package manager (if it has a recent enough version). + +MacOSX: `Get Valgrind trunk from +SVN <https://valgrind.org/downloads/repository.html>`__ and build it. +Don't use 3.10.x or any other tarball. + +Make sure you have Valgrind 3.14 or later, version 3.16.1 is known to work, +3.13.0 did not. Newer versions tend to have better compatibility with both +Firefox's JITs and newer toolchain components (compiler, libc and linker +versions). + +Basics +------ + +Build +~~~~~ + +Build Firefox with the following options, which maximize speed and +accuracy. + +.. code:: + + ac_add_options --disable-jemalloc + ac_add_options --disable-strip + ac_add_options --enable-valgrind + ac_add_options --enable-optimize="-g -O2" + ac_add_options --disable-sandbox + +Run +~~~ + +Note that programs run *much* more slowly under Valgrind than they do +natively. Slow-downs of 20x or 30x aren't unexpected, and it's slower on +Mac than on Linux. Don't try this on an underpowered machine. + +Linux +^^^^^ + +On Linux, run Valgrind with the following options. + +.. code:: + + --smc-check=all-non-file --vex-iropt-register-updates=allregs-at-mem-access --show-mismatched-frees=no --read-inline-info=yes + +The ``--smc-check`` and ``--vex-iropt-register-updates`` options are +necessary to avoid crashes in JIT-generated code. + +The ``--show-mismatched-frees`` option is necessary due to inconsistent +inlining of ``new`` and ``delete`` -- i.e. one gets inlined but the +other doesn't -- which lead to false-positive mismatched-free errors. + +The ``--read-inline-info`` option improves stack trace readability in +the presence of inlining. + +Also, run with the following environment variable set. + +.. code:: + + G_SLICE=always-malloc + +This is necessary to get the Gnome system libraries to use plain +``malloc`` instead of pool allocators. + +Mac +^^^ + +On Mac, run Valgrind with the following options. + +.. code:: + + --smc-check=all-non-file --vex-iropt-register-updates=allregs-at-mem-access --show-mismatched-frees=no --dsymutil=yes + +The ``--dsymutil`` option ensures line number information is present in +stack traces. + +Advanced usage +-------------- + +Shared suppression files +~~~~~~~~~~~~~~~~~~~~~~~~ + +`/build/valgrind/ <https://searchfox.org/mozilla-central/source/build/valgrind/>`__ +contains the suppression files used by the periodic Valgrind jobs on +Treeherder. Some of these files are platform-specific. + +Running mochitests under Valgrind? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To run a mochitest under Valgrind, use the following command. + +.. code:: bash + + $ ./mach mochitest-plain --debugger="valgrind" --debugger-args="$VALGRIND_OPTIONS" relative/path/to/tests + +Where ``$VALGRIND_OPTIONS`` are the options described +:ref:`above <Debugging Firefox With Valgrind>`. You might also +need ``--trace-children=yes`` to trace into child processes. + +As of December 2014 it is possible to do a complete run of +mochitests-plain on Valgrind in about 8 CPU hours on a Core i4910 +(Haswell) machine. Maximum process size is 5.4G, of which about 80% is +in memory. Runs of small subsets of mochitests take far less memory. + +Bits and pieces +~~~~~~~~~~~~~~~ + +For un-released Linux distros (Fedora Rawhide, etc.) you'll need to use +a version of Valgrind trunk build, because fixes for the latest gcc and +glibc versions appear there first. Without them you'll be flooded with +false errors from Memcheck, and have debuginfo reading problems. + +On Linux, code compiled by LLVM at high optimisation levels can cause +Memcheck to report false uninitialised value errors. See +`here <https://bugs.kde.org/show_bug.cgi?id=242137#c3>`__ for an easy +workaround. On Mac, Valgrind has this workaround built in. + +You can make stack traces easier to read by asking for source file names +to be given relative to the root of your source tree. Do this by using +``--fullpath-after=`` to specify the rightmost part of the absolute path +that you don't want to see. For example, if your source tree is rooted +at ``/home/sewardj/MC-20-12-2014``, use ``--fullpath-after=2014/`` to +get path names relative to the source directory. + +The ``--track-origins=yes`` slows down Valgrind greatly, so don't use it +unless you are hunting down a specific uninitialised value error. But if +you are hunting down such an error, it's extremely helpful and worth +waiting for. + +Additional help +--------------- + +The `Valgrind Quick Start +Guide <http://www.valgrind.org/docs/manual/quick-start.html>`__ is short +and worth reading. The `User +Manual <https://valgrind.org/docs/manual/manual.html>`__ is also useful. + +If Valgrind asserts, crashes, doesn't do what you expect, or otherwise +acts up, first of all read this page and make sure you have both Firefox +and Valgrind correctly configured. If that's all OK, try using the +`Valgrind trunk from +SVN <http://www.valgrind.org/downloads/repository.html>`__. Oftentimes +bugs are fixed in the trunk before most users fall across them. If that +doesn't help, consider `filing a bug +report <http://www.valgrind.org/support/bug_reports.html>`__, and/or +mailing Julian Seward or Nick Nethercote. diff --git a/docs/contributing/debugging/debugging_on_macos.rst b/docs/contributing/debugging/debugging_on_macos.rst new file mode 100644 index 0000000000..ef42c162f9 --- /dev/null +++ b/docs/contributing/debugging/debugging_on_macos.rst @@ -0,0 +1,359 @@ +Debugging On macOS +================== + +This document explains how to debug Gecko-based applications such as +Firefox, Thunderbird, and SeaMonkey on macOS using Xcode. If you want to +debug from the terminal see :ref:`Debugging Mozilla with +lldb <Debugging Firefox with LLDB>`. For specific +information on a way to debug hangs, see :ref:`Debugging a hang on macOS <Debugging A Hang On macOS>`. + +Creating a debuggable build +--------------------------- + +First, you need to build the application you're going to debug using +this in your .mozconfig + +.. code:: + + ac_add_options --disable-optimize + ac_add_options --enable-debug-symbols + +you can also add this flag if you want assertions etc. compiled in + +.. code:: + + ac_add_options --enable-debug + +See :ref:`Building Firefox for macOS <Building Firefox On MacOS>` +if you need help creating your own build. + +Debugging Firefox on macOS 10.14+ +--------------------------------- + +macOS 10.14 introduced Notarization and Hardened Runtime features for +improved application security. macOS 10.15 went further, requiring +applications to be Notarized with Hardened Runtime enabled in order to +launch (ignoring workarounds). When run on earlier macOS versions, +Notarization and Hardened Runtime settings have no effect. + +Official Builds +~~~~~~~~~~~~~~~ + +At this time, official builds of Firefox 69 and later are Notarized. +**As a result, it is not possible to attach a debugger to these official +Firefox releases on macOS 10.14+ without disabling System Integrity +Protection (SIP).** This is due to Notarization requiring Hardened +Runtime to be enabled with the ``com.apple.security.get-task-allow`` +entitlement disallowed. **Rather than disabling SIP (which has security +implications), it is recommended to debug with try builds or local +builds. The differences are explained below.** + +try Server Builds +~~~~~~~~~~~~~~~~~ + +In most cases, developers needing to debug a build as close as possible +to the production environment should use a :ref:`try +build <Pushing to Try>`. These +builds enable Hardened Runtime and only differ from production builds in +that they are not Notarized which should not otherwise affect +functionality, (other than the ability to easily launch the browser on +macOS 10.15+ -- see quarantine note below). At this time, developers can +obtain a Hardened Runtime build with the +``com.apple.security.get-task-allow`` entitlement allowed by submitting +a try build and downloading the dmg generated by the "Rpk" shippable +build job. A debugger can be attached to Firefox processes of these +builds. try builds use the ``developer.entitlements.xml`` file from the +source tree while production builds use ``production.entitlements.xml``. +**On macOS 10.15+, downloaded try builds will not launch by default +because Notarization is required. To workaround this problem, remove the +quarantine extended attribute from the downloaded Nightly:** + + ``$ xattr -r -d com.apple.quarantine /Path/to/Nightly.app`` + +Local Builds +~~~~~~~~~~~~ + +Local builds of mozilla-central do not enable Hardened Runtime and hence +do not have debugging restrictions. As a result, some functionality will +be permitted on local builds, but blocked on production builds which +have Hardened Runtime enabled. `Bug +1522409 <https://bugzilla.mozilla.org/show_bug.cgi?id=1522409>`__ was +filed to automate codesigning local builds to enable Hardened Runtime by +default and eliminate this discrepancy. + +To obtain a Hardened Runtime build without using try infrastructure, a +developer can manually codesign builds using the macOS ``codesign(1)`` +command with the ``developer.entitlements.xml`` file from the tree. This +requires creating a codesigning identity. + +Disabling System Integrity Protection (SIP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If debugging a production build is required, follow Apple's documented +steps for disabling System Integrity Protection (SIP). Note that +disabling SIP bypasses Hardened Runtime restrictions which can mask some +bugs that only occur with Hardened Runtime so it is recommended to test +fixes with SIP enabled. **Disabling SIP has system security implications +that should be understood before taking this step.** + +Creating an Xcode project +------------------------- + +If you try to create a new Xcode project in an existing directory +then Xcode will delete its existing contents (Xcode will warn you +beforehand). To work around that, the steps below have you initialize +the project outside the Mozilla source tree, close the project, copy +the .xcodeproj project "file" into the source tree, and then reopen +the project to finish setting it up. + +Note also that since Xcode 7.3.1 it doesn't seem to be possible to +have the Xcode project live outside the source tree. If you try to do +that then Xcode will simply **copy** the source files under the +project directory rather than link to them which breaks debugging and the +possibility to modify-rebuild-relaunch from inside Xcode. + +These steps were last updated for Xcode 10.3: + +#. Open Xcode, and create a new Project with File > New Project. Select + the "Cross-platform" tab then under the "Other" template group select + the "Empty" project type. the click Next. Name the project and click + Next. Create/select a temporary directory to contain the project and + then click Create. +#. Before going any further, close the project (File > Close Project) + and open Finder. Find the \*.xcodejproj directory in the temporary + directory, move it into your Mozilla source tree, and then + double-click on it to reopen it. +#. In the left-hand pane in Xcode you should see a tree item where the + root item has the project name. If the temporary directory that you + originally created the Xcode project in is under that, right click it + and delete it. Now, right click on the root item, select 'Add files + to "<project-name>"', select all the files and directories in your + source directory, untick "Copy items if needed", then click Add. + (These will then be progressively added under the root item + <project-name> in the left-hand pane. Note that subdirectories may + initially appear to be empty, but they too will progressively be + populated as Xcode processes the sourse files. Once done, you should + be able to open any file quickly by hitting Cmd-Shift-O and typing in + the name of a file.) +#. In the Product menu, select Scheme > New Scheme and name your scheme + (for example, "Debug"). After you click OK, Xcode should open the + settings window for the new scheme. (If not, then open its settings + from the Product > Edit Scheme menu.) +#. Select "Run" on the left-hand side of the settings window, then + select the "Info" tab. Set the Executable by clicking on "None" and + selecting "Other...". A new dialog titled "Choose an executable to + launch" will pop up. Browse to the ``.app`` file that you want to + debug (``Firefox.app``, ``Nightly``\ ``Debug.app`` etc). The ``.app`` + file is typically found inside the ``dist`` folder in your build + directory. +#. If you are debugging Firefox, Thunderbird, or some other application + that supports multiple profiles, using a separate profile for + debugging purposes is recommended. See "Having a profile for + debugging purposes" below. Select the "Arguments" tab in the scheme + editor, and click the '+' below the "Arguments passed on launch" + field. Add "-P *profilename*", where *profilename* is the name of a + profile you created previously. Repeat that to also add the argument + "-no-remote". +#. Also in the "Arguments" panel, you may want to add an environment + variable MOZ_DEBUG_CHILD_PROCESS set to the value 1 to help with + debugging e10s. +#. Select "Build" from the left of the scheme editor window, and check + that there is nothing listed under Targets (otherwise it may cause + problems when you try to run the executable for debugging since you + will get build errors). +#. Click "Close" to close the scheme editor. + +At this point you can run the application from Xcode, and when you pause +or hit breakpoints it should show open the correct source file at the +correct line. + +Setting up lldb +--------------- + +``lldb`` is the debugger Xcode provides/uses. + +.. warning:: + + One important issue that the Mozilla .lldbinit file fixes is that by + default some breakpoints will be listed as "pending", and Xcode will + not stop at them. If you don't include the Mozilla's .lldbinit, you + must at least put + ``settings set target.inline-breakpoint-strategy always`` in your + ``$HOME/.lldbinit`` as recommended on :ref:`Debugging Firefox with + lldb <Debugging Firefox with LLDB>`. + +The +`.lldbinit <http://searchfox.org/mozilla-central/source/.lldbinit>`__ +file in the source tree imports many useful `Mozilla specific lldb +settings, commands and +formatters <https://searchfox.org/mozilla-central/source/python/lldbutils/README.txt>`__ +into ``lldb``, but you may need to take one of the following steps to +make sure this file is used. + +If you are using ``lldb`` on the command line (independently of Xcode) +and you will always run it from either the top source directory, the +object directory or else the dist/bin subdirectory of the object +directory, then adding the following setting to your ``$HOME/.lldbinit`` +is sufficient: + +:: + + settings set target.load-cwd-lldbinit true + +*However*, if you will run lldb from a different directory, or if you +will be running it indirectly by debugging in Xcode (Xcode always runs +lldb from "/"), then this setting will not help you. Instead, add the +following to your ``$HOME/.lldbinit``: + +:: + + # This automatically sources the Mozilla project's .lldbinit as soon as lldb + # starts or attaches to a Mozilla app (that's in an object directory). + # + # This is mainly a workaround for Xcode not providing a way to specify that + # lldb should be run from a given directory. (Xcode always runs lldb from "/", + # regardless of what directory Xcode was started from, and regardless of the + # value of the "Custom working directory" field in the Scheme's Run options. + # Therefore setting `settings set target.load-cwd-lldbinit true` can't help us + # without Xcode providing that functionality.) + # + # The following works by setting a one-shot breakpoint to break on a function + # that we know will both run early (which we want when we start first start the + # app) and run frequently (which we want so that it will trigger ASAP if we + # attach to an already running app). The breakpoint runs some commands to + # figure out the object directory path from the attached target and then + # sources the .lldbinit from there. + # + # NOTE: This scripts actions take a few seconds to complete, so the custom + # formatters, commands etc. that are added may not be immediately available. + # + breakpoint set --name nsThread::ProcessNextEvent --thread-index 1 --auto-continue true --one-shot true + breakpoint command add -s python + # This script that we run does not work if we try to use the global 'lldb' + # object, since it is out of date at the time that the script runs (for + # example, `lldb.target.executable.fullpath` is empty). Therefore we must + # get the following objects from the 'frame' object. + target = frame.GetThread().GetProcess().GetTarget() + debugger = target.GetDebugger() + + # Delete our breakpoint (not actually necessary with `--one-shot true`): + target.BreakpointDelete(bp_loc.GetBreakpoint().GetID()) + + # For completeness, find and delete the dummy breakpoint (the breakpoint + # lldb creates when it can't initially find the method to set the + # breakpoint on): + # BUG WORKAROUND! GetID() on the *dummy* breakpoint appears to be returning + # the breakpoint index instead of its ID. We have to add 1 to correct for + # that! :-( + dummy_bp_list = lldb.SBBreakpointList(target) + debugger.GetDummyTarget().FindBreakpointsByName("nsThread::ProcessNextEvent", dummy_bp_list) + dummy_bp_id = dummy_bp_list.GetBreakpointAtIndex(0).GetID() + 1 + debugger.GetDummyTarget().BreakpointDelete(dummy_bp_id) + + # "source" the Mozilla project .lldbinit: + os.chdir(target.executable.fullpath.split("/dist/")[0]) + debugger.HandleCommand("command source -s true " + os.path.join(os.getcwd(), ".lldbinit")) + DONE + +see :ref:`Debugging Mozilla with +lldb <Debugging Firefox with LLDB>`. for more information. + +Having a profile for debugging purposes +--------------------------------------- + +It is recommended to create a separate profile to debug with, whatever +your task, so that you don't lose precious data like Bookmarks, saved +passwords, etc. So that you're not bothered with the profile manager +every time you start to debug, expand the "Executables" branch of the +"Groups & Files" list and double click on the Executable you added for +Mozilla. Click the plus icon under the "Arguments" list and type "-P +<profile name>" (e.g. "-P MozillaDebug"). Close the window when you're +done. + +Running a debug session +----------------------- + +Make sure breakpoints are active (which implies running under the +debugger) by opening the Product menu and selecting "Debug / Activate +Breakpoints" (also shown by the "Breakpoints" button in the top right +section of the main window). Then click the "Run" button or select "Run" +from the Product menu. + +Setting breakpoints +~~~~~~~~~~~~~~~~~~~ + +Setting a breakpoint is easy. Just open the source file you want to +debug in Xcode, and click in the margin to the left of the line of code +where you want to break. + +During the debugging session, each time that line is executed, the +debugger will break there, and you will be able to debug it. + +.. warning:: + + Note that with the default configuration, some breakpoints will be + listed as "pending", and Xcode will not stop at them. If you don't + include the Mozilla's .lldbinit, you must at least put + ``settings set target.inline-breakpoint-strategy always`` in your + ``$HOME/.lldbinit`` as recommended on :ref:`Debugging Mozilla with + lldb <Debugging Firefox with LLDB>`. + +Using Firefox-specific lldb commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you included the .lldbinit when `Setting up +lldb <#setting-up-lldb>`__, you can use Mozilla-specific lldb commands +in the console, located in the Debug area of Xcode. For example, type +``js`` to see the JavaScript stack. For more information, see :ref:`Debugging +Mozilla with lldb <Debugging Firefox with LLDB>`. + +Debugging e10s child processes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Using Xcode to debug child processes created by an e10s-enabled browser +is a little trickier than debugging a single-process browser, but it can +be done. These directions were written using Xcode 6.3.1 + +#. Complete all the steps above under "Creating the Project" +#. From the "Product" menu, ensure the scheme you created is selected + under "Scheme", then choose "Scheme > Edit Scheme" +#. In the resulting popup, click "Duplicate Scheme" +#. Give the resulting scheme a more descriptive name than "Copy of + Scheme" +#. Select "Run" on the left-hand side of the settings window, then + select the "Info" tab. Set the Executable by clicking on the + "Executable" drop-down, and selecting the ``plugin-container.app`` + that is inside the app bundle of the copy of Firefox you want to + debug. +#. On the same tab, under "Launch" select "Wait for executable to be + launched" +#. On the "Arguments" tab, remove all arguments passed on launch. + +Now you're ready to start debugging: + +#. From the "Product" menu, ensure the scheme you created above is + selected under "Scheme" +#. Click the "Run" button. The information area at the top of the window + will show "Waiting for plugin-container to launch" +#. From a command line, run your build of Firefox. When that launches a + child process (for example, when you start to load a webpage), Xcode + will notice and attach to that child process. You can then debug the + child process like you would any other process. +#. When you are done debugging, click the "Stop" button and quit the + instance of Firefox that you were debugging in the normal way. + +For some help on using lldb see :ref:`Debugging Mozilla with +lldb <Debugging Firefox with LLDB>`. + +Other resources +--------------- + +Apple has an extensive list of `debugging tips and +techniques <https://developer.apple.com/library/mac/#technotes/tn2124/_index.html>`__. + +Questions? Problems? +~~~~~~~~~~~~~~~~~~~~ + +Try asking in our Element channels +`#developers <https://chat.mozilla.org/#/room/#developers:mozilla.org>`__ or +`#macdev <https://chat.mozilla.org/#/room/#macdev:mozilla.org>`__. diff --git a/docs/contributing/debugging/debugging_on_windows.rst b/docs/contributing/debugging/debugging_on_windows.rst new file mode 100644 index 0000000000..3213299199 --- /dev/null +++ b/docs/contributing/debugging/debugging_on_windows.rst @@ -0,0 +1,330 @@ +Debugging On Windows +==================== + +This document explains how to debug Gecko based applications such as +Firefox, Thunderbird, and SeaMonkey on Windows using the Visual Studio IDE. + +If VS and your Gecko application hang shortly after you launch the +application under the debugger, see `Problems Loading Debug +Symbols <#problems-loading-debug-symbols>`__. + +Ways to start the debugger +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First of all, it's necessary to install a Visual Studio extension to be +able to follow child processes as they are created. Firefox, in general, +and even in non-e10s mode, does not start the main process directly, it +starts it via a Launcher Process. This means that Visual Studio will +only attach to the first process it finds, and will not hit any +break-point (and even notifies you that it cannot find their location). +`Microsoft Child Process Debugging Power +Tool <https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool>`__ +allows automatically attaching to child processes, such as Web Content +process, GPU process, etc. Enable it by going its configuration menu in +"Debug > Other debugging targets > Child process debugging settings", +and ticking the box. + +If you have followed the steps in :ref:`Building Firefox for +Windows <Building Firefox On Windows>` +and have a local debug build, you can **execute this command from same command line.** + +.. code:: + + ./mach run --debug + +It would open Visual Studio with Firefox's +run options configured. You can **click "Start" button** to run Firefox +then, already attached in the debugger. + +Alternatively, if you have generated the Visual Studio solution, via +``./mach build-backend -b VisualStudio``, opening this solution allows +you to run ``firefox.exe`` directly in the debugger. To make it the +startup project, right click on the project and select ``Set As Startup +Project``. It appears bold when it's the case. Breakpoints are kept +across runs, this can be a good way to debug startup issues. + +**Run the program until you hit an assertion.** You will get a dialog +box asking if you would like to debug. Hit "Cancel". The MSDEV IDE will +launch and load the file where the assertion happened. This will also +create a Visual Studio Mozilla project in the directory of the executable +by default. + +**Attach the debugger to an existing Mozilla process**. In the Visual +Studio, select Debug > Attach to Process. If you want to debug a content +process, you can **hover on the tab** of page you want to debug, which +would show the pid. You can then select the process from dialog opened +from "Attach to Process". You can open ``about:processes`` to see the pid +for all subprocesses, including tabs but also GPU, networking etc. +For more information, see `Attach to Running Processes with the Visual Studio +Debugger <http://msdn.microsoft.com/en-us/library/vstudio/3s68z0b3.aspx>`__. + +**Starting an MSIX installed Firefox with the debugger**. In Visual +Studio, select Debug -> Other Debug Targets -> Debug Installed App Package. +In the dialog, select the installed Firefox package you wish to debug +and click "Start". + +Debugging Release and Nightly Builds +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Refer to the steps to :ref:`use the Mozilla symbol +server <Using The Mozilla Symbol Server>` and :ref:`source +server <Using The Mozilla Source Server>` + +Creating a Visual Studio project for Firefox +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Please refer to :ref:`this <Visual Studio Projects>`. + +Changing/setting the executable to debug +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To change or set the executable to debug, go to Project > Properties > +Debugging > Command. (As of Visual Studio 2022.) + +It should show the executable you are debugging. If it is empty or +incorrect, manually add the correct path to the executable. + +Command line parameters and environment variables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To change or set the command line options, go to Project > Properties > +Debugging > Command Arguments. + +Some common options would be the URL of the file you want the browser to +open as soon as it starts, starting the Profile Manager, or selecting a +profile. You can also redirect the console output to a file (by adding +"``> filename.txt``" for example, without the quotes). + +Customizing the debugger's variable value view +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can customize how Visual Studio displays classes in the variable view. +By default VS displays "{...}" and you need to click the small + icon +to expand the members. You can change this behaviour, and make Visual +Studio display whatever data member you want in whatever order, formatted +however you like instead of just "{...}". + +You need to locate a file called "gecko.natvis" under toolkit/library. +The file contains a list of types and how they should be displayed in +the debugger. It is XML and after a little practice you should be well +on your way. + +To understand the file in detail refer to `Create custom views of C++ +objects in the debugger using the Natvis framework +<https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects>`__ + +The file already comes with a number of entries that will make your life +easier, like support for several string types. If you need to add a custom +type, or want to change an existing entry for debugging purposes, you can +easily edit the file. For your convenience it is included in all generated +Visual Studio projects, and if you edit and save it within Visual Studio, it +will pick up the changes immediately. + +Handling multiple processes in Visual Studio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Turn off "Break all processes when one process breaks" to single step a single +process. + +Turning off "Break all processes when one process breaks" adds "Step Into +Current Process", "Step Over Current Process" and "Step Out Current Process" to +the "Debug" menu. + +To single step a single process with the other processes paused: + +- Turn on "Break all processes when one process breaks" +- Hit a breakpoint which stops all processes +- Turn off "Break all processes when one process breaks" +- Now using "Step Into Current Process" will leave the other processes stopped + and just advance the current one. + +Obtaining ``stdout`` and other ``FILE`` handles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Running the following command in the Command Window in Visual Studio +returns the value of ``stdout``, which can be used with various +debugging methods (such as ``nsGenericElement::List``) that take a +``FILE*`` param: + +.. code:: + + Debug.EvaluateStatement {,,msvcr80d}(&__iob_func()[1]) + +(Alternatively you can evaluate ``{,,msvcr80d}(&__iob_func()[1])`` in +the Immediate window) + +Similarly, you can open a file on the disk using ``fopen``: + +.. code:: + + >Debug.EvaluateStatement {,,msvcr80d}fopen("c:\\123", "w") + 0x10311dc0 { ..snip.. } + >Debug.EvaluateStatement ((nsGenericElement*)0x03f0e710)->List((FILE*)0x10311dc0, 1) + <void> + >Debug.EvaluateStatement {,,msvcr80d}fclose((FILE*)0x10311dc0) + 0x00000000 + +Note that you may not see the debugging output until you flush or close +the file handle. + +Disabling ASSERTIONS +~~~~~~~~~~~~~~~~~~~~ + +There are basically two ways to disable assertions. One requires setting +an environment variable, while the other affects only the currently +running program instance in memory. + +Environment variable +^^^^^^^^^^^^^^^^^^^^ + +There is an environment variable that can disable breaking for +assertions. This is how you would normally set it: + +.. code:: + + set XPCOM_DEBUG_BREAK=warn + +The environment variable takes also other values besides ``warn``, see +``XPCOM_DEBUG_BREAK`` for more details. + +Note that unlike Unix, the default for Windows is not warn, it's to pop +up a dialog. To set the environment variable for Visual Studio, use +Project > Properties > Debugging > Environment and click the little box. +Then use + +.. code:: + + XPCOM_DEBUG_BREAK=warn + +Changing running code +^^^^^^^^^^^^^^^^^^^^^ + +You normally shouldn't need to do this (just quit the application, set +the environment variable described above, and run it again). And this +can be **dangerous** (like **trashing your hard disc and corrupting your +system**). So unless you feel comfortable with this, don't do it. **You +have been warned!** + +It is possible to change the interrupt code in memory (which causes you +to break into debugger) to be a NOP (no operation). + +You do this by running the program in the debugger until you hit an +assertion. You should see some assembly code. One assembly code +instruction reads "int 3". Check the memory address for that line. Now +open memory view. Type/copy/drag the memory address of "int 3" into the +memory view to get it to update on that part of the memory. Change the +value of the memory to "90", close the memory view and hit "F5" to +continue. + +Automatically handling ASSERTIONS without a debugger attached +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When an assertion happens and there is not a debugger attached, a small +helper application +(```windbgdlg.exe`` </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__) +is run. That application can automatically select a response to the "Do +you want to debug" dialog instead of prompting if you configure it, for +more info, see +```windbgdlg.exe`` </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__. + +Debugging optimized builds +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To effectively debug optimized builds, you should enable debugging +information which effectively leaves the debug symbols in optimized code +so you can still set breakpoints etc. Because the code is optimized, +stepping through the code may occasionally provide small surprises when +the debugger jumps over something. + +You need to make sure this configure parameter is set: + +.. code:: + + ac_add_options --enable-debug + +You can also choose to include or exclude specific modules. + +Console debugging +~~~~~~~~~~~~~~~~~ + +When printing to STDOUT from a content process, the console message will +not appear on Windows. One way to view it is simply to disable e10s +(``./mach run --disable-e10s``) but in order to debug with e10s enabled +one can run + +:: + + ./mach run ... 2>&1 | tee + +It may also be necessary to disable the content sandbox +(``MOZ_DISABLE_CONTENT_SANDBOX=1 ./mach run ...``). + +Running two instances of Mozilla simultaneously +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can run two instances of Mozilla (e.g. debug and optimized) +simultaneously by setting the environment variable ``MOZ_NO_REMOTE``: + +.. code:: + + set MOZ_NO_REMOTE=1 + +Or, starting with Firefox 2 and other Gecko 1.8.1-based applications, +you can use the ``-no-remote`` command-line switch instead (implemented +in +`bug 325509 <https://bugzilla.mozilla.org/show_bug.cgi?id=325509>`__). + +You can also specify the profile to use with the ``-P profile_name`` +command-line argument. + +Debugging JavaScript +~~~~~~~~~~~~~~~~~~~~ + +You can use helper functions from +`nsXPConnect.cpp <https://searchfox.org/mozilla-central/source/js/xpconnect/src/nsXPConnect.cpp>`__ +to inspect and modify the state of JavaScript code from the MSVS +debugger. + +For example, to print current JavaScript stack to stdout, evaluate this +in Immediate window: + +.. code:: + + {,,xul}DumpJSStack() + +Visual Studio will show you something in the quick watch window, but +not the stack, you have to look in the OS console for the output. + +Also this magical command only works when you have JS on the VS stack. + +Debugging minidumps +~~~~~~~~~~~~~~~~~~~ + +See :ref:`debugging a minidump <Debugging A Minidump>`. + +Problems post-mortem debugging on Windows 7 SP1 x64? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you attempt to use ``NS_DebugBreak`` etc to perform post-mortem +debugging on a 64bit Windows 7, but as soon as you try and continue +debugging the program crashes with an Access Violation, you may be +hitting a Windows bug relating to AVX support. For more details, +including a work-around see `this blog +post <http://www.os2museum.com/wp/?p=960>`__ or `this social.msdn +thread <http://social.msdn.microsoft.com/Forums/vstudio/en-US/392ca62c-e502-42d9-adbc-b4e22d5da0c3/jit-debugging-32bit-app-crashing-with-access-violation>`__. +(And just in-case those links die, the work-around is to execute + +:: + + bcdedit /set xsavedisable 1 + +from an elevated command-prompt to disable AVX support.) + +Got a tip? +~~~~~~~~~~ + +If you think you know a cool Mozilla debugging trick, feel free to +discuss it with `#developers <https://chat.mozilla.org/#/room/#developers:mozilla.org>`__ and +then post it here. + +.. |Screenshot of disabling assertions| image:: https://developer.mozilla.org/@api/deki/files/420/=Win32-debug-nop.png + :class: internal diff --git a/docs/contributing/debugging/img/about-processes.png b/docs/contributing/debugging/img/about-processes.png new file mode 100644 index 0000000000..6f1563bcd1 Binary files /dev/null and b/docs/contributing/debugging/img/about-processes.png differ diff --git a/docs/contributing/debugging/img/about-support.png b/docs/contributing/debugging/img/about-support.png new file mode 100644 index 0000000000..2b12d1027d Binary files /dev/null and b/docs/contributing/debugging/img/about-support.png differ diff --git a/docs/contributing/debugging/img/crash-gmp.png b/docs/contributing/debugging/img/crash-gmp.png new file mode 100644 index 0000000000..595e439307 Binary files /dev/null and b/docs/contributing/debugging/img/crash-gmp.png differ diff --git a/docs/contributing/debugging/img/crash-gpu.png b/docs/contributing/debugging/img/crash-gpu.png new file mode 100644 index 0000000000..9e40b63917 Binary files /dev/null and b/docs/contributing/debugging/img/crash-gpu.png differ diff --git a/docs/contributing/debugging/img/crash-rdd.png b/docs/contributing/debugging/img/crash-rdd.png new file mode 100644 index 0000000000..5548672d27 Binary files /dev/null and b/docs/contributing/debugging/img/crash-rdd.png differ diff --git a/docs/contributing/debugging/img/crashlist.jpg b/docs/contributing/debugging/img/crashlist.jpg new file mode 100644 index 0000000000..4cb376d0f2 Binary files /dev/null and b/docs/contributing/debugging/img/crashlist.jpg differ diff --git a/docs/contributing/debugging/img/crashreporter.png b/docs/contributing/debugging/img/crashreporter.png new file mode 100644 index 0000000000..3137c71c78 Binary files /dev/null and b/docs/contributing/debugging/img/crashreporter.png differ diff --git a/docs/contributing/debugging/img/process-explorer.png b/docs/contributing/debugging/img/process-explorer.png new file mode 100644 index 0000000000..26e7837a8d Binary files /dev/null and b/docs/contributing/debugging/img/process-explorer.png differ diff --git a/docs/contributing/debugging/img/sdk-installer.png b/docs/contributing/debugging/img/sdk-installer.png new file mode 100644 index 0000000000..c7dcc1f1a4 Binary files /dev/null and b/docs/contributing/debugging/img/sdk-installer.png differ diff --git a/docs/contributing/debugging/img/tabcrashed.png b/docs/contributing/debugging/img/tabcrashed.png new file mode 100644 index 0000000000..9982e527ed Binary files /dev/null and b/docs/contributing/debugging/img/tabcrashed.png differ diff --git a/docs/contributing/debugging/img/windbg-in-startmenu.png b/docs/contributing/debugging/img/windbg-in-startmenu.png new file mode 100644 index 0000000000..0819d4b424 Binary files /dev/null and b/docs/contributing/debugging/img/windbg-in-startmenu.png differ diff --git a/docs/contributing/debugging/local_symbols.rst b/docs/contributing/debugging/local_symbols.rst new file mode 100644 index 0000000000..875717e1a1 --- /dev/null +++ b/docs/contributing/debugging/local_symbols.rst @@ -0,0 +1,64 @@ +Symbolicating TreeHerder stacks locally +======================================= + +When using tools like the :ref:`Dark Matter Detector (DMD)` or +:ref:`refcount logging<Refcount Tracing and Balancing>` to +investigate issues occurring on TreeHerder that you can't reproduce locally, you +can often end up with unsymbolicated stacks. Fortunately, there is a way to +symbolicate these stacks on your own machine. + +These instructions are for a Linux TreeHerder build for MacOS, so they might +require some modifications for other combinations of platforms. + +Download ``target.tar.bz2`` and ``target.crashreporter-symbols.zip`` from the +Build job. **Note that these files are very large so you'll want to delete +them and the extracted files when you are done.** + +These files each contain a large number of files, so I'd recommend creating +a directory for each of them. Call these ``<TARGET_DIR>`` and ``<SYMB_DIR>``, +and move the prior two files into these two directories, respectively. + +Go to ``<TARGET_DIR>`` and run something like + +.. code-block:: shell + + tar xf target.tar.bz2 + +then go to ``<SYMB_DIR>`` and run something like + +.. code-block:: shell + + unzip target.crashreporter-symbols.zip + +You should be able to delete the two original files now. + +Next we need to ensure that the locations of binaries are rewritten from +where they are on TreeHerder to where we have them locally. We'll do this by +editing ``fix_stacks.py``. This file is located in the ``tools/rb/`` directory of +the Firefox source directory. You need to add these two lines to the function +``fixSymbols``, after ``line_str`` is defined and before it is written to +``fix_stacks.stdin``. I've done this right before the definition of +``is_missing_newline``. + +.. code-block:: python + + line_str = line_str.replace("/builds/worker/workspace/build/application/firefox/firefox", + "<TARGET_DIR>/firefox/firefox-bin") + line_str = line_str.replace("/builds/worker/workspace/build/application/firefox/libxul.so", + "<TARGET_DIR>/firefox/libxul.so") + +The initial locations should appear verbatim in the stack you are trying to +symbolicate, so double check that they match. Also, ``<TARGET_DIR>`` of course +needs to be replaced with the actual local directories where those files are +located. Note that the ``firefox`` executable is changed to ``firefox-bin``. +I don't know why that is necessary, but only the latter existed for me. + +Finally, we need to make it so that the stack fixer can find the location of +the breakpad symbols we downloaded. If you are running ``fix_stacks.py`` via +``dmd.py`` or directly (in a recent version), you can do this by running with the +environment variable ``BREAKPAD_SYMBOLS_PATH`` set to the ``<SYMB_DIR>`` from above. +If that doesn't work, you'll have to edit ``initFixStacks`` in ``fix_stacks.py`` to +set ``breakpadSymsDir`` to ``<SYMB_DIR>``. + +With all of that done, you should now be able to run ``dmd.py`` or ``fix_stacks.py`` +to fix the stacks. Note that the stack fixing process can take a minute or two. diff --git a/docs/contributing/debugging/process_dump_task_manager.rst b/docs/contributing/debugging/process_dump_task_manager.rst new file mode 100644 index 0000000000..d345171856 --- /dev/null +++ b/docs/contributing/debugging/process_dump_task_manager.rst @@ -0,0 +1,69 @@ +How to get a process dump with Windows Task Manager +=================================================== + +Introduction +------------ + +When tracking down the causes of process hangs, it is often helpful to +obtain a process dump while the process is experiencing a hang. This +article describes how to get a process dump with Task Manager on +Windows. (To get a process dump for Thunderbird or some other product, +substitute the product name where ever you see Firefox in these +instructions.) + + +Caution +------- + +The memory dump that will be created through this process is a complete +snapshot of the state of Firefox when you create the file, so it +contains URLs of active tabs, history information, and possibly even +passwords depending on what you are doing when the snapshot is taken. It +is advisable to create a new, blank profile to use when reproducing the +hang and capturing the memory dump. Please ask for help doing this! + + +Requirements +------------ + +Windows + To get a process dump, you need to be using Windows Vista or above. +A Firefox nightly or release + You need a Firefox version for which symbols are available from the + :ref:`symbol server <Using The Mozilla Symbol Server>`. You + can use any `official nightly + build <https://ftp.mozilla.org/pub/firefox/nightly/>`__ or released + version of Firefox from Mozilla. You can find the latest trunk + nightly builds under + `http://ftp.mozilla.org/pub/mozilla.o.../latest-trunk/ <http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/>`__. + + +Creating the Dump File +---------------------- + +Ensure that Firefox is not already running. + + +Run Firefox, reproduce the hang +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Start Firefox and perform whatever steps are necessary to cause Firefox +to hang. Once the browser hangs, continue with the steps below. + + +After the hang +~~~~~~~~~~~~~~ + +#. Open Windows Task Manager (CTRL+SHIFT+ESC). +#. Find Firefox.exe among the list of processes. +#. Right-click Firefox.exe and select "Create dump file". Task manager + should indicate where the dump file was written to. + + +See also +-------- + +- :ref:`How to get a stacktrace for a bug report <How to get a stacktrace for a bug report>` +- `How to create a user-mode process dump file in Windows Vista and in + Windows 7 + (MSDN) <https://docs.microsoft.com/en-us/windows/client-management/generate-kernel-or-complete-crash-dump#manually-generate-a-memory-dump-file>`__ diff --git a/docs/contributing/debugging/stacktrace_report.rst b/docs/contributing/debugging/stacktrace_report.rst new file mode 100644 index 0000000000..2cae230745 --- /dev/null +++ b/docs/contributing/debugging/stacktrace_report.rst @@ -0,0 +1,153 @@ +How to get a stacktrace for a bug report +======================================== + +If you file a bug report in Bugzilla about a crash you should include a +stacktrace (call stack) in your report. A stacktrace will tell Mozilla +developers what crashed and provide a starting point for investigating +its cause. This article describes how to use the Mozilla Crash Reporter +(Breakpad) to get a crash ID, which our engineers can use to get a +stacktrace, and alternative ways to get a stacktrace if you can't get a +crash ID. + +Requirements +------------ + +You need a binary build of Firefox from +`Mozilla.org <https://www.mozilla.org/firefox/>`__. SeaMonkey and +Thunderbird also support crash reporting. + +Mozilla's crash report server currently only has debug information for +Mozilla builds and thus the crash reporter cannot work if you use a +build from a Linux distribution or if you compile from source code. In +these cases you will need to use one of the :ref:`alternative +methods <Alternative ways to get a stacktrace>` listed below. + +.. note:: + + **Note:** When filing a crash report, it is important to know whether + the crash occurs with `Firefox safe + mode <http://support.mozilla.com/kb/Safe+Mode>`__. This helps + engineers determine whether a particular + `extension <http://support.mozilla.com/kb/Troubleshooting+extensions+and+themes>`__ + or + `plugin <http://support.mozilla.com/kb/Troubleshooting+plugins>`__ + is the cause of the crash. + + +How to get a crash ID with the Mozilla Crash Reporter +----------------------------------------------------- + +1 - Crash and submit a report to the system. + +.. image:: img/crashreporter.png + +The Mozilla Crash Reporter window should automatically come up after Firefox crashes. +If you have any additional information about the crash, such as additional detail on +what you were doing at the time that may have triggered the crash, please enter it +into the comments box. Be sure that you **check the "Tell Mozilla about this crash"** +checkbox and click the restart button. The crash reporter should now submit the +crash report and Firefox should open again. + +.. note:: + + The "Details" button gives additional data about the incident, + however this is not useful in a bug report. + + +2 - Tell us the ID of the report you submitted. + +.. image:: img/crashlist.jpg + +To access all of your submitted reports type "about:crashes" into the Firefox address bar +and press enter. Firefox should open a list of IDs for your submitted crash reports. +Copy two or three of the IDs for the appropriate crashes and paste them into your +Bugzilla report. Please check the listed times to avoid copying the ID of an unrelated +crash report. + +.. note:: + + You can prefix a "bp-" to the beginning of an ID to make Bugzilla turn it + into a link: bp-a70759c6-1295-4160-aa30-bc4772090918 + + +How to get the crash ID if Firefox crashes on startup +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If Firefox crashes on startup you can still access your submitted crash +reports. Crash reports are accessible from all Firefox profiles, so if a +`new +profile <https://support.mozilla.org/kb/profile-manager-create-remove-switch-firefox-profiles>`__ +does not crash you can use it to access them through "about:crashes" as above. + + +Accessing crash report IDs outside of Firefox +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you cannot load Firefox at all you can find the crash report files at +this location depending on your operating system: + +* Windows : ``%APPDATA%\Mozilla\Firefox\Crash Reports\submitted\`` +* macOS : ``~/Library/Application Support/Firefox/Crash Reports/submitted/`` +* Linux : ``~/.mozilla/firefox/Crash Reports/submitted/`` + +Each file in this folder contains one submitted crash report ID. You can +check the modified or creation time for each file to discern which crash +reports are relevant to your bug report. + +.. _Alternative ways to get a stacktrace: + +Alternative ways to get a stacktrace +------------------------------------ + +If the Mozilla crash reporter doesn't come up or isn't available you +will need to obtain a stacktrace manually: + + +Windows +~~~~~~~ + +See the article :ref:`Create a stacktrace with Windbg <How to get a stacktrace with WinDbg>` for information +on how to do this. + +For a full process dump, see :ref:`How to get a process dump with Windows +Task Manager`. + + +macOS +~~~~~ + +Run /Applications/Utilities/Console.app. Expand "~/Library/Logs" and +"CrashReporter", then look for logs for "firefox-bin". + + +Linux +~~~~~ + +Note that for most distros, the package you need to get symbols for will +be something like "xulrunner", not "firefox". + + +Crash reports files on your computer +------------------------------------ + +When Breakpad initially catches a crash it first writes crash report +files (e.g. .dump and .extra files) into the 'pending' subdirectory of +its 'Crash Reports' directory. + +If Breakpad successfully sends the crash report to the reporting server +then, by default, the files added to the 'pending' subdirectory for the +crash are removed, and a .txt file is placed in the 'submitted' +directory containing the crash ID created by the reporting server. + +If you want Breakpad to leave the .dump and .extra files on your +computer so that you can examine them locally, then set the +MOZ_CRASHREPORTER_NO_DELETE_DUMP environment variable to 1. + +- Ubuntu: `Instructions from the Ubuntu + Team <https://wiki.ubuntu.com/MozillaTeam/Bugs#Obtain%20a%20backtrace%20from%20an%20apport%20crash%20report%20(using%20gdb)>`__ +- openSUSE: `General instructions from + openSUSE <https://en.opensuse.org/openSUSE:Bugreport_application_crashed>`__ +- Fedora: `Capturing Stack + Traces <https://fedoraproject.org/wiki/StackTraces>`__ +- Gentoo: `Debugging using + GDB <https://wiki.gentoo.org/wiki/Debugging_with_GDB>`__ diff --git a/docs/contributing/debugging/stacktrace_windbg.rst b/docs/contributing/debugging/stacktrace_windbg.rst new file mode 100644 index 0000000000..a0d2abfc25 --- /dev/null +++ b/docs/contributing/debugging/stacktrace_windbg.rst @@ -0,0 +1,232 @@ +How to get a stacktrace with WinDbg +=================================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +Introduction +------------ + +Sometimes you need to get a stacktrace (call stack) for a crash or hang +but `Breakpad <http://kb.mozillazine.org/Breakpad>`__ fails because it's +a special crash or a hang. This article describes how to get a +stacktrace in those cases with WinDbg on Windows. (To get a stacktrace +for Thunderbird or some other product, substitute the product name where +ever you see Firefox in this instructions.) + +Requirements +------------ + +To get such a stacktrace you need to install the following software: + +Debugging Tools for Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Microsoft distributes the Debugging Tools for Windows for free, those +include WinDbg which you will need here. Download it from `Install +Debugging Tools for +Windows <https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk>`__. +(*You'll want the 32-bit version*, even if you are using a 64-bit +version of Windows) Then install it, the standard settings in the +installation process are fine. + +A Firefox nightly or release +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You need a Firefox version for which symbols are availables from the +:ref:`symbol server <Using The Mozilla Symbol Server>` to use +with WinDbg. You can use any `official nightly +build <https://ftp.mozilla.org/pub/firefox/nightly/>`__ or released +version of Firefox from Mozilla. You can find the latest trunk nightly +builds under +`http://ftp.mozilla.org/pub/mozilla.o.../latest-trunk/ <https://ftp.mozilla.org/pub/firefox/nightly/latest-mozilla-central/>`__. + + +Debugging +--------- + +To begin debugging, ensure that Firefox is not already running and open +WinDbg from the Start menu. (Start->All Programs->Debugging Tools for +Windows->WinDbg) Next, open the **"File"** menu and choose **"Open +Executable..."**. In the file chooser window that appears, open the +firefox.exe executable in your Firefox program folder (C:\Program +Files\Mozilla Firefox). + +You should now see a "Command" text window with debug output at the top +and an input box at the bottom. Before debugging can start, several +commands must be entered into the one-line input box at the bottom of +the Command window. + +.. note:: + + Tip: All commands must be entered exactly as written, one line at a + time, into the bottom of the Command box. + + - Copying and pasting each line is the easiest method to avoid + mistakes + - Some commands start with a period (.) or a pipe character (|), + which is required. (The keystroke for a pipe character on US + keyboards is SHIFT+\) + - Submit the log file on a bug or via the support site, even if + nothing seems to happen during the debug process + + +Start debugging +~~~~~~~~~~~~~~~ + +Now that Firefox is opened in the debugger, you need to configure your +WinDbg to download symbols from the Mozilla symbol server. To load the +symbols, enter the three commands below, pressing enter after each one. +(More details are available at :ref:`symbol server <Using The Mozilla Symbol Server>`.) + +:: + + .sympath SRV*c:\symbols*http://symbols.mozilla.org/firefox;SRV*c:\symbols*http://msdl.microsoft.com/download/symbols + .symfix+ c:\symbols + .reload /f + +Now wait for the symbols to download. This may take some time depending +on your connection speed; the total size of the Mozilla and Microsoft +symbols download is around 1.4GB. WinDbg will show "Busy" at the bottom +of the application window until the download is complete. + +Once the download is complete, you need to configure WinDbg to examine +child processes, ignore a specific event caused by Flash Player, and +record a log of loaded modules. You will also want to open a log file to +save data you collect. To do this, enter these four commands, pressing +enter after each one. + +:: + + .logopen /t c:\temp\firefox-debug.log + .childdbg 1 + .tlist + sxn gp + lm + +If you see firefox.exe listed in the output from .tlist more than once, +then you are already running the application and need to close the +running instance first before you start debugging, otherwise you won't +get useful results. + +Now run Firefox by opening the **Debug** menu and clicking **Go**. +**While Firefox is running, you will not be able to type any commands +into the debugger.** After it starts, try to reproduce the crash or +hanging issue that you are seeing. + +.. note:: + + If Firefox fails to start, and you see lines of text followed by a + command prompt in the debugger, a "breakpoint" may have been + triggered. If you are prompted for a command but don't see an error + about a crash, go back to the **Debug** menu and press **Go**. + +Once the browser crashes, you will see an error (such as "Access +violation") in the WinDbg Command window. If Firefox hangs and there is +no command prompt available in the debugger, open the **Debug** menu and +choose **Break.** Once the browser has crashed or been stopped, continue +with the steps below. + + +After the crash or hang +~~~~~~~~~~~~~~~~~~~~~~~ + +You need to capture the debug information to include in a bug comment or +support request. Enter these three commands, one at a time, to get the +stacktrace, crash/hang analysis and log of loaded modules. (Again, press +Enter after each command.) + +:: + + ~* kp + !analyze -v -f + lm + +After these steps are completed, find the file +**c:\temp\firefox-debug-(Today's Date).txt** on your hard drive. To +provide the information to the development community, submit this file +with a `support request <https://support.mozilla.com/>`__ or attach it +to a related bug on `Bugzilla <https://bugzilla.mozilla.org/>`__. + + +Producing a minidump +~~~~~~~~~~~~~~~~~~~~ + +Sometimes the stacktrace alone is not enough information for a developer +to figure out what went wrong. A developer may ask you for a "minidump" +or a "full memory dump", which are files containing more information +about the process. :ref:`You can easily produce minidumps from WinDBG and +provide them to developers <Capturing a minidump>`. + +FAQ + +Q: I am running Windows 7 (32-bit or 64-bit) and I see an exception in +the WinDbg command window that says 'ntdll32!LdrpDoDebuggerBreak+0x2c' +or 'ntdll32!LdrpDoDebuggerBreak+0x30'. What do I do now? + +A: If you see 'int 3' after either of those exceptions, you will need to +execute the following commands in WinDbg. + +:: + + bp ntdll!LdrpDoDebuggerBreak+0x30 + bp ntdll!LdrpDoDebuggerBreak+0x2c + eb ntdll!LdrpDoDebuggerBreak+0x30 0x90 + eb ntdll!LdrpDoDebuggerBreak+0x2c 0x90 + +| Make sure you enter them one at a time and press enter after each one. + If you use the 64-bit version of Windows, you need to replace "ntdll" + in these commands with "ntdll32". +| Q: The first four frames of my stack trace look like this: + +:: + + 0012fe20 7c90e89a ntdll!KiFastSystemCallRet + 0012fe24 7c81cd96 ntdll!ZwTerminateProcess+0xc + 0012ff20 7c81cdee kernel32!_ExitProcess+0x62 + + 0012ff34 6000179e kernel32!ExitProcess+0x14 + +This looks wrong to me?! + +A: You ran the application without the "Debug child processes also" +check box being checked. You need to detach the debugger and open the +application again, this time with the check box being checked. + +Q: WinDbg tells me that it is unable to verify checksum for firefox.exe. +Is this normal? + +A: Yes, this is normal and can be ignored. + +Q: Should I click yes or no when WinDbg asks me to "Save information for +workspace?" + +A: Click yes and WinDbg will save you from having to enter in the symbol +location for Firefox.exe in the future. Click no if you'd rather not +having WinDbg save this information. + +Q: I'm seeing "wow64" on top of each thread, is that ok ? + +A: No, you are running a 64 bit version of Windbg and trying to debug a +32 bit version of the mozilla software. Redownload and install the 32 +bit version of windbg. + + +Troubleshooting: Symbols will not download +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If symbols will not download no matter what you do, the problem may be +that Internet Explorer has been set to the **Work Offline** mode. You +will not receive any warnings of this in Windbg, Visual C++ or Visual +Studio. Even using the command line with symchk.exe to download symbols +will fail. This is because Microsoft uses Internet Explorer's internet & +proxy settings to download the symbol files. Check the File menu of +Internet Explorer to ensure "Work Offline" is unchecked. + + +See also +-------- + +- :ref:`symbol server <Using The Mozilla Symbol Server>` Maps addresses to human readable strings. +- :ref:`source server <Using The Mozilla Source Server>` Maps addresses to source code lines diff --git a/docs/contributing/debugging/understanding_crash_reports.rst b/docs/contributing/debugging/understanding_crash_reports.rst new file mode 100644 index 0000000000..9f8e5bbe03 --- /dev/null +++ b/docs/contributing/debugging/understanding_crash_reports.rst @@ -0,0 +1,325 @@ +Understanding Crash Reports +=========================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +If a user experiences a crash they will be prompted to submit a raw +crash report, which is generated by Breakpad. The raw crash report is +received by `Socorro <https://github.com/mozilla/socorro>`__ which +`creates <https://github.com/mozilla/socorro/blob/master/socorro/processor/mozilla_processor_2015.py>`__ +a processed crash report. The processed crash report is based on the raw +crash report but also has a signature, classifications, and a number of +improved fields (e.g. OS, product, version). Many of the fields in both +the raw crash report and the processed crash report are viewable and +searchable on `crash-stats <https://crash-stats.mozilla.org/>`__. +Although there are two distinct crash reports, the raw and the +processed, people typically talk about a single "crash report" because +crash-stats mostly presents them in a combined way. + +Each crash report contains a wealth of data about the crash +circumstances. Despite this, many crash reports lack sufficient data for +a developer to understand why the crash occurred. As well as providing a +general overview, this page aims to highlight parts of a crash report +that may provide non-obvious insights. + +Note that most crash report fields are visible, but a few +privacy-sensitive parts of it are only available to users who are logged +in and have "minidump access". A relatively small number of users have +minidump access, and they are required to follow certain rules. For +access, see the `Protected Data Access docs on Crash Stats +<https://crash-stats.mozilla.org/documentation/protected_data_access/>`__. + +Each crash report has the following tabs: Details, Metadata, Modules, +Raw Dump, Extensions, and (optional) Correlations. + +Details tab +----------- + +The Details tab is the first place to look because it contains the most +important pieces of information. + +Primary fields +~~~~~~~~~~~~~~ + +| The first part of the Details tab shows a table containing the most + important crash report fields. It includes such things as when the + crash occurred, in which product and version, the crash kind, and + various details about the OS and configuration of the machine on which + the crash occurred. The following screenshot shows some of these + fields. +| |Example fields in the "Details" tab of a crash report| + +All fields have a tool-tip. For many fields, the tool-tip describes its +meaning. For all fields, the tool-tip indicates the key to use when you +want to do searches involving this field. (The field name is usually but +not always similar to the search key. E.g. the field "Adapter Device ID" +has the search key "adapter_device_id".) These descriptions are shown in +the `SuperSearchFields +API <https://crash-stats.mozilla.org/api/SuperSearchFields/>`__ and can be +`modified in super_search_fields.py <https://github.com/mozilla-services/socorro/blob/main/socorro/external/es/super_search_fields.py>`__ +or by writing up a `bug in Socorro <https://bugzilla.mozilla.org/enter_bug.cgi?format=__standard__&product=Socorro>`__. + +The fields present in this tab vary depending on the crash kind. Not all +fields are always present. + +The "Signature" field is the main identifier or label for a crash report. +Rather than considering each crash report in isolation, we want to put +crash reports into clusters so we can deal with groups of them at once. +An ideal clustering algorithm would put all crash reports with the same +root cause into a single cluster, and all crash reports with different +root causes into different clusters. The crash signature is our +imperfect but still useful attempt at such an algorithm. Most crash +signatures are based on the crashing stack trace, but some +special-purpose annotations are used to indicate particular kinds of +crashes. + +- ``Abort``: A controlled abort, e.g. via ``NS_RUNTIMEABORT``. + (Controlled aborts that occur via ``MOZ_CRASH`` or + ``MOZ_RELEASE_ASSERT`` currently don't get an ``Abort`` annotation, + but they do get a "MOZ_CRASH Reason" field.) +- ``OOM | <size>``, where ``<size>`` is one of ``large``, ``small``, + ``unknown``: an out-of-memory (OOM) abort. The ``<size>`` annotation + is determined by the "OOM Allocation Size" field; if that field is + missing ``<size>`` will be ``unknown``. +- ``hang``: a hang prior to shutdown. +- ``shutdownhang``: a hang during shutdown. +- ``IPCError-browser``: a problem involving IPC. If the parent Firefox + process detects that the child process has sent broken or + unprocessable IPDL data, or is not shutting down in a timely manner, + it kills the child process with a crash report. These crashes will + now have a signature that indicates why the process was killed, + rather than the child stack at the moment. + +When no special-purpose annotation is present and the signature begins +with a stack frame, it's usually a vanilla uncontrolled crash. The crash +cause can be determined from the "Crash Reason" field. Most commonly +it's a bad memory access. In that case, on Windows you can tell from the +reason field if the crash occurred while reading, writing or executing +memory (e.g. ``EXCEPTION_VIOLATION_ACCESS_READ`` indicates a bad memory +read). On Mac and Linux the reason will be SIGSEGV or SIGBUS and you +cannot tell from this field what kind of memory access it was. + +See `this +file <https://github.com/mozilla-services/socorro/blob/master/socorro/signature/README.rst>`__ +for a detailed explanation of the crash report signature generation +procedure, and for information on how modify this procedure. + +There are no fields that uniquely identify the user that a crash report +came from, but if you want to know if multiple crashes come from a +single user the "Install Time" field is a good choice. Use it in +conjunction with other fields that don't change, such as those +describing the OS or graphics card, for additional confidence. + +For bad memory accesses, the "Crash Address" field can give additional +indications what went wrong. + +- 0x0 is probably a null pointer deference[*]. +- Small addresses like 0x8 can indicate an object access (e.g. + ``this->mFoo``) via a null ``this`` pointer. +- Addresses like 0xfffffffffd8 might be stack accesses, depending on + the platform[*]. +- Addresses like 0x80cdefd3 might be heap accesses, depending on the + platform. +- Addresses may be poisoned: 0xe4 indicates the address comes from + memory that has been allocated by jemalloc but not yet initialized; + 0xe5 indicates the address comes from memory freed by jemalloc. The + JS engine also has multiple poison values defined in + ``js/src/jsutil.h``. + +[*] Note that due to the way addressing works on x86-64, if the crash +address is 0x0 for a Linux/macOS crash report, or 0xffffffffffffffff for +a Windows crash report, it's highly likely that the value is incorrect. +(There is a `bug +report <https://bugzilla.mozilla.org/show_bug.cgi?id=1493342>`__ open +for this problem.) You can sanity-check these crashes by looking at the +raw dump or minidump in the Raw Dump tab (see below). + +Note that for non-release builds the "Version" field represents multiple +different builds since nightly and beta version numbers are reused for +builds created over a series of days until the version number is bumped. +(The "Build ID" field can disambiguate.) It's not currently possible to +`restrict searches to a given version or +later <https://bugzilla.mozilla.org/show_bug.cgi?id=1401517>`__ (using +>= with a build ID and a given release channel may work around this). + +Some fields, such as "URL" and "Email Address", are privacy-sensitive +and are only visible to users with minidump access. + +The Windows-only "Total Virtual Memory" field indicates if the Firefox +build and OS are 32-bit or 64-bit. + +- A value of 2 GiB indicates 32-bit Firefox on 32-bit Windows. +- A value of 3 or 4 GiB indicates 32-bit Firefox on 64-bit Windows + (a.k.a. "WoW64"). Such a user could switch to 64-bit Firefox. +- A value much larger than 4 GiB (e.g. 128 TiB) indicates 64-bit + Firefox. (The "Build Architecture" field should be "amd64" in this + case.) + +Some crash reports might contain a memory report. This memory report will +have been made some time before the crash, at a time when available +memory was low. In this case, a number of key measurements from the +memory report are shown in the Details tab, each one having a field name +starting with "MR:", short for "memory report". The full memory report +can be obtained in the Raw Dump tab (see below). + +Bug-related information +~~~~~~~~~~~~~~~~~~~~~~~ + +The second part of the Details tab shows bug-related information, as the +following screenshot shows. + +|Information relating to bug reports in the "Details" tab of a crash +report| + +The "Report this bug in" links can be used to easily file bug reports. +Each one links to a Bugzilla bug report creation page that has various +fields pre-filled, such as the crash signature. + +The "Related Bugs" section shows related bug reports, as determined by +the crash signature. + +Stack traces +~~~~~~~~~~~~ + +The third part of the Details tab shows the stack trace and thread +number of the crashing thread, as the following screenshot shows. + +|Information relating to threads in the "Details" tab of a crash report| + +Each stack frame has a link to the source code, when possible. If a +crash is new, the regressing changeset can often be identified by +looking for recent changes in the blame annotations for one or more of +the top stack frames. Blame annotations are also good for identifying +who might know about the code in question. + +Sometimes the highlighted source code is puzzling, e.g. the identified +line may not touch memory even though the crash is memory-related. This +can be caused by compiler optimizations. It's often better to look at +the disassembly (e.g. in a minidump) to understand exactly what code is +being executed. + +Stack frame entries take on a variety of forms. + +- The simplest are functions names, such as ``NS_InitXPCOM2``. +- Name/address pairs such as ``nss3.dll@0x1eb720`` are within system + libraries. +- Names such as ``F1398665248_____________________________`` ('F' + followed by many numbers then many underscores) are in Flash. +- Addresses such as ``@0xe1a850ac`` may indicate an address that wasn't + part of any legitimate code. If an address such as this occurs in the + first stack frame, the crash may be + `exploitable <https://developer.mozilla.org/en-US/docs/Mozilla/Security/Exploitable_crashes>`__. + +Stack traces for other threads can be viewed by clicking on the small +"Show other threads" link. + +If the crash report is for a hang, the crashing thread will be the +"watchdog" thread, which exists purely to detect hangs; its top stack +frame will be something +like\ :literal:`mozilla::`anonymous namespace'::RunWatchdog`. In that +case you should look at the other threads' stack traces to determine the +problem; many of them will be waiting on some kind of response, as shown +by a top stack frame containing a function like +``NtWaitForSingleObject`` or ``ZwWaitForMultipleObjects``. + +Metadata tab +------------ + +The Metadata tab is similar to the first part of the Details tab, +containing a table with various fields. These are the fields from the +raw crash report, ordered alphabetically by field name, but with +privacy-sensitive fields shown only to users with minidump access. There +is some overlap with the fields shown in the Details tab. + +Modules tab +----------- + +The modules tab shows all the system libraries loaded at the time of the +crash, as the following screenshot shows. + +|Table of modules in the "Modules" tab of a crash report| + +On Windows these are mostly DLLs, on Mac they are mostly ``.dylib`` +files, and on Linux they are mostly ``.so`` files. + +This information is most useful for Windows crashes, because DLLs loaded +by antivirus software or malware often cause Firefox to crash. +Correlations between loaded modules and crash signatures can be seen in +the "Correlations" tab (see below). + +`This page <https://support.mozilla.org/en-US/kb/helping-crashes>`__ +says that files lacking version/debug identifier/debug filename are +likely to be malware. + +Raw Dump tab +------------ + +The first part of the Raw Dump tab shows the raw crash report, in JSON +format. Once again, privacy-sensitive fields are shown only to users +with minidump access. + +|JSON data in the "Raw Dump" tab of a crash report| + +For users with minidump access, the second part of the Raw Dump tab has +some links, as the following screenshot shows. + +|Links to downloadable files in the "Raw Dump" tab of a crash report| + +These links are to the following items. + +#. A minidump. Minidumps can be extremely useful in understanding a + crash report; see :ref:`this page <Debugging A Minidump>` for an + explanation how to use them. +#. The aforementioned JSON raw crash report. +#. The memory report contained within the crash report. +#. The unredacted crash report, which has additional information. + +Extensions tab +-------------- + +The Extensions tab shows which extensions are installed and enabled. + +|Table of extensions in the "Extensions" tab of a crash report| + +Usually it just shows an ID rather than the proper extension name. + +Note that several extensions ship by default with Firefox and so will be +present in almost all crash reports. (The exact set of default +extensions depends on the release channel.) The least obvious of these +has an Id of ``{972ce4c6-7e08-4474-a285-3208198ce6fd}``, which is the +default Firefox theme. Some (but not all) of the other extensions +shipped by default have the following Ids: ``webcompat@mozilla.org``, +``e10srollout@mozilla.org``, ``firefox@getpocket.com``, +``flyweb@mozilla.org``, ``loop@mozilla.org``. + +If an extension only has a hexadecimal identifier, a Google search of +that identifier is usually enough to identify the extension's name. + +This information is useful because some crashes are caused by +extensions. Correlations between extensions and crash signatures can be +seen in the "Correlations" tab (see below). + +Correlations tab +---------------- + +This tab is only shown when crash-stats identifies correlations between +a crash and modules or extensions that are present, which happens +occasionally. + +See also +-------- + +- `A talk about understanding crash + reports <https://air.mozilla.org/a-talk-about-understanding-crash-reports/>`__, + by David Baron, from March 2016. +- :ref:`A guide to searching crash reports` + +.. |Example fields in the "Details" tab of a crash report| image:: https://mdn.mozillademos.org/files/13579/Details1.png +.. |Information relating to bug reports in the "Details" tab of a crash report| image:: https://mdn.mozillademos.org/files/13581/Details2.png +.. |Information relating to threads in the "Details" tab of a crash report| image:: https://mdn.mozillademos.org/files/13583/Details3.png +.. |Table of modules in the "Modules" tab of a crash report| image:: https://mdn.mozillademos.org/files/13593/Modules1.png +.. |JSON data in the "Raw Dump" tab of a crash report| image:: https://mdn.mozillademos.org/files/13595/RawDump1.png +.. |Links to downloadable files in the "Raw Dump" tab of a crash report| image:: https://mdn.mozillademos.org/files/14047/raw-dump-links.png +.. |Table of extensions in the "Extensions" tab of a crash report| image:: https://mdn.mozillademos.org/files/13599/Extensions1.png diff --git a/docs/contributing/directory_structure.rst b/docs/contributing/directory_structure.rst new file mode 100644 index 0000000000..fd447278c2 --- /dev/null +++ b/docs/contributing/directory_structure.rst @@ -0,0 +1,565 @@ +Firefox Source Code Directory Structure +======================================= + +This article provides an overview of what the various directories contain. + +To simply take a look at the Firefox source code, you do not need to +download it. You can look at the source directly with your web browser +using Searchfox (start at https://searchfox.org/mozilla-central/source for +the complete firefox source code of branch HEAD). + +In order to modify the source, you have to acquire it either by +downloading a :ref:`snapshot <Mercurial Overview>` of the sources or +by checking out the current sources from +:ref:`the repository <Firefox Contributors' Quick Reference>`. + +This document describes the directory structure -- i.e., directories that +are used by at least some of the +Mozilla project's client products. There are other directories in the +other Mozilla repository, such as those for Web tools and those for the +Classic codebase. + +See the `more detailed overview of the pieces of Gecko <https://wiki.mozilla.org/Gecko:Overview>`__. + +.cargo +------ + +Configuration files for the `Cargo package +manager <https://crates.io/>`__. + +.vscode +------- + +Configuration files used by the `Visual Studio Code +IDE <https://code.visualstudio.com/>`__ when working in the +mozilla-central tree. + +accessible +---------- + +Files for accessibility (i.e., MSAA (Microsoft Active Accessibility), +ATK (Accessibility Toolkit, used by GTK) support files). See +`Accessibility <https://developer.mozilla.org/docs/Web/Accessibility>`__. + + +browser +------- + +Contains the front end code (in XUL, Javascript, XBL, and C++) for the +Firefox desktop browser. Many of these files started off as a copy of files in +`xpfe <#xpfe>`__. + +browser/extensions +------------------ + +Contains `PDF.js <https://mozilla.github.io/pdf.js/>`__ and +`WebCompat <https://github.com/mozilla/webcompat-addon>`__ built-in extensions. + +browser/themes +-------------- + +Contains images and CSS files to skin the browser for each OS (Linux, +Mac and Windows) + +build +----- + +Miscellaneous files used by the build process. See also `config <#config>`__. + +caps +---- + +Capability-based web page security management. It contains C++ interfaces +and code for determining the capabilities of content based on the +security settings or certificates (e.g., VeriSign). See `Component +Security <https://www.mozilla.org/projects/security/components/>`__ . + +chrome +------ + +:ref:`Chrome registry <Chrome Registration>` used with `toolkit <#toolkit>`__/. +These files were originally copies of files in `rdf/chrome/`. + +config +------ + +More files used by the build process, common includes for the makefiles, +etc. + + +devtools +-------- + +The Firefox Developer Tools server and client components. See :ref:`contributor <devtools-contributor-doc>` and :ref:`user <devtools-user-doc>` documentation. + + +docs +---- + +Contains the documentation configuration (`Sphinx <http://www.sphinx-doc.org/>`__ based), the index page +and the contribution pages. + + +docshell +-------- + +Implementation of the docshell, the main object managing things related +to a document window. Each frame has its own docshell. It contains +methods for loading URIs, managing URI content listeners, etc. It is the +outermost layer of the embedding API used to embed a Gecko browser into +an application. + +dom +--- + +- :ref:`IDL definitions <XPIDL>` of the interfaces defined by + the DOM specifications and Mozilla extensions to those interfaces + (implementations of these interfaces are primarily, but not + completely, in `content <#content>`__). +- The parts of the connection between JavaScript and the + implementations of DOM objects that are specific both to JavaScript + and to the DOM. +- Implementations of a few of the core "DOM Level 0" objects, such as + `window <https://developer.mozilla.org/docs/Web/API/Window>`__ , `window.navigator <https://developer.mozilla.org/docs/Web/API/Window/navigator>`__, `window.location <https://developer.mozilla.org/docs/Web/API/Window/location>`__, etc. + +editor +------ + +The editor directory contains XUL/Javascript for the embeddable editor +component, which is used for the HTML Editor("Composer"), for plain and +HTML mail composition, and for text fields and text areas throughout the +product. The editor is designed like a +"browser window with editing features": it adds some special classes for +editing text and managing transaction undo/redo, but reuses browser code +for nearly everything else. + +extensions +---------- + +Contains several extensions to mozilla, which can be enabled at +compile-time using the ``--enable-extensions`` configure argument. + +Note that some of these are now built specially and not using the +``--enable-extensions`` option. For example, disabling xmlextras is done +using ``--disable-xmlextras``. + + +extensions/auth +--------------- + +Implementation of the negotiate auth method for HTTP and other +protocols. Has code for SSPI, GSSAPI, etc. See `Integrated +Authentication <https://www.mozilla.org/projects/netlib/integrated-auth.html>`__. + + +extensions/pref +--------------- + +Preference-related extensions. + +extensions/spellcheck +--------------------- + +Spellchecker for mailnews and composer. + +extensions/universalchardet +--------------------------- + +Detects the character encoding of text. + +gfx +--- + +Contains interfaces that abstract the capabilities of platform specific +graphics toolkits, along with implementations on various platforms. +These interfaces provide methods for things like drawing images, text, +and basic shapes. It also contains basic data structures such as points +and rectangles used here and in other parts of Mozilla. + +gradle +------ + +Containing files related to a Java build system. + +hal +--- + +Contains platform specified functions (e.g. obtaining battery status, +sensor information, memory information, Android +alarms/vibrate/notifications/orientation, etc) + +image +----- + +Image rendering library. Contains decoders for the image formats Firefox +supports. + +intl +---- + +Internationalization and localization support. See +`L10n:NewProjects <https://wiki.mozilla.org/L10n:NewProjects>`__. + +intl/locale +----------- + +Code related to determination of locale information from the operating +environment. + +intl/lwbrk +---------- + +Code related to line breaking and word breaking. + +intl/strres +----------- + +Code related to string resources used for localization. + +intl/uconv +---------- + +Code that converts (both ways: encoders and decoders) between UTF-16 and +many other character encodings. + +intl/unicharutil +---------------- + +Code related to implementation of various algorithms for Unicode text, +such as case conversion. + +ipc +--- + +Container for implementations of IPC (Inter-Process Communication). + +js/src +------ + +The JavaScript engine, also known as +:ref:`SpiderMonkey <SpiderMonkey>`. +See also `JavaScript <https://developer.mozilla.org/docs/JavaScript>`__. + +js/xpconnect +------------ + +Support code for calling JavaScript code from C++ code and C++ code from +JavaScript code, using XPCOM interfaces. See +`XPConnect <https://developer.mozilla.org/docs/XPConnect>`__. + +layout +------ + +Code that implements a tree of rendering objects that describe the types +and locations of the objects that are displayed on the screen (such as +CSS boxes, tables, form controls, XUL boxes, etc.), and code that +manages operations over that rendering tree (such as creating and +destroying it, doing layout, painting, and event handling). See +`documentation <https://www.mozilla.org/newlayout/doc/>`__ and `other +information <https://www.mozilla.org/newlayout/>`__. + +layout/base +----------- + +Code that deals with the rendering tree. + +layout/forms +------------ + +Rendering tree objects for HTML form controls. + +layout/generic +-------------- + +The basic rendering object interface and the rendering tree objects for +basic CSS boxes. + +layout/mathml +------------- + +Rendering tree objects for `MathML <https://developer.mozilla.org/docs/Web/MathML>`__. + +layout/svg +---------- + +Rendering tree objects for `SVG <https://developer.mozilla.org/docs/Web/SVG>`__. + +layout/tables +------------- + +Rendering tree objects for CSS/HTML tables. + +layout/xul +---------- + +Additional rendering object interfaces for `XUL <https://developer.mozilla.org/docs/XUL>`__ and +the rendering tree objects for XUL boxes. + +media +----- + +Contains sources of used media libraries for example *libpng*. + +memory +------ + +Cross-platform wrappers for *memallocs* functions etc. + +mfbt +---- + +Implementations of classes like *WeakPtr*. Multi-platform *assertions* +etc. + +mobile +------ + +mobile/android +-------------- + +Firefox for Android and Geckoview + +modules +------- + +Compression/Archiving, math library, font (and font compression), +Preferences Library + +modules/libjar +-------------- + +Code to read zip files, used for reading the .jar files that contain the +files for the mozilla frontend. + +modules/libpref +--------------- + +Library for reading and writing preferences. + +modules/zlib +------------ + +Source code of zlib, used at least in the networking library for +compressed transfers. + +mozglue +------- + +Glue library containing various low-level functionality, including a +dynamic linker for Android, a DLL block list for Windows, etc. + +netwerk +------- + +:ref:`Networking library <Networking>`, also known as Necko. +Responsible for doing actual transfers from and to servers, as well as +for URI handling and related stuff. + +netwerk/cookie +-------------- + +Permissions backend for cookies, images, etc., as well as the user +interface to these permissions and other cookie features. + +nsprpub +------- + +Netscape Portable Runtime. Used as an abstraction layer to things like +threads, file I/O, and socket I/O. See :ref:`NSPR`. + +nsprpub/lib +----------- + +Mostly unused; might be used on Mac? + +other-licenses +-------------- + +Contains libraries that are not covered by the MPL but are used in some +Firefox code. + +parser +------ + +Group of structures and functions needed to parse files based on +XML/HTML. + +parser/expat +------------ + +Copy of the expat source code, which is the XML parser used by mozilla. + +parser/html +----------- + +The HTML parser (for everything except about:blank). + +parser/htmlparser +----------------- + +The legacy HTML parser that's still used for about:blank. Parts of it +are also used for managing the conversion of the network bytestream into +Unicode in the XML parsing case. + +parser/xml +---------- + +The code for integrating expat (from parser/expat) into Gecko. + +python +------ + +Cross module python code. + +python/mach +----------- + +The code for the :ref:`Mach` building tool. + +security +-------- + +Contains NSS and PSM, to support cryptographic functions in mozilla +(like S/MIME, SSL, etc). See :ref:`Network Security Services (NSS)` +and +`Personal Security Manager +(PSM) <https://www.mozilla.org/projects/security/pki/psm/>`__. + +services +-------- + +Firefox accounts and sync (history, preferences, tabs, bookmarks, +telemetry, startup time, which addons are installed, etc). See +`here <https://docs.services.mozilla.com/>`__. + +servo +----- + +`Servo <https://servo.org/>`__, the parallel browser engine project. + +startupcache +------------ + +XXX this needs a description. + +storage +------- + +`Storage <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Storage>`__: XPCOM wrapper for sqlite. Wants to +unify storage of all profile-related data. Supersedes mork. See also +`Unified Storage <https://wiki.mozilla.org/Mozilla2:Unified_Storage>`__. + +taskcluster +----------- + +Scripts and code to automatically build and test Mozilla trees for the +continuous integration and release process. + +testing +------- + +Common testing tools for mozilla codebase projects, test suite +definitions for automated test runs, tests that don't fit anywhere else, +and other fun stuff. + +third_party +----------- + +Vendored dependencies maintained outside of Mozilla. + +toolkit +------- + +The "new toolkit" used by Thunderbird, Firefox, etc. This contains +numerous front-end components shared between applications as well as +most of the XBL-implemented parts of the XUL language (most of which was +originally forked from versions in `xpfe/`). + +toolkit/mozapps/extensions/test/xpinstall +----------------------------------------- + +The installer, which contains code for installing Mozilla and for +installing XPIs/extensions. This directory also contains code needed to +build installer packages. See `XPInstall <https://developer.mozilla.org/docs/XPInstall>`__ and +the `XPInstall project +page <https://www.mozilla.org/projects/xpinstall/>`__. + +tools +----- + +Some tools which are optionally built during the mozilla build process. + +tools/lint +---------- + +The linter declarations and configurations. +See `linting documentation </code-quality/lint/>`_ + +uriloader +--------- + +uriloader/base +-------------- + +Content dispatch in Mozilla. Used to load uris and find an appropriate +content listener for the data. Also manages web progress notifications. +See `Document Loading: From Load Start to Finding a +Handler <https://www.mozilla.org/docs/docshell/uri-load-start.html>`__ +and `The Life Of An HTML HTTP +Request <https://www.mozilla.org/docs/url_load.html>`__. + + +uriloader/exthandler +-------------------- + +Used to handle content that Mozilla can't handle itself. Responsible for +showing the helper app dialog, and generally for finding information +about helper applications. + +uriloader/prefetch +------------------ + +Service to prefetch documents in order to have them cached for faster +loading. + +view +---- + +View manager. Contains cross-platform code used for painting, scrolling, +event handling, z-ordering, and opacity. Soon to become obsolete, +gradually. + +widget +------ + +A cross-platform API, with implementations on each platform, for dealing +with operating system/environment widgets, i.e., code related to +creation and handling of windows, popups, and other native widgets and +to converting the system's messages related to painting and events into +the messages used by other parts of Mozilla (e.g., `view/` and +`content/`, the latter of which converts many of the +messages to yet another API, the DOM event API). + +xpcom +----- + +`Cross-Platform Component Object Model </en-US/docs/XPCOM>`__. Also +contains data structures used by the rest of the mozilla code. See also +`XPCOM Project <https://www.mozilla.org/projects/xpcom/>`__. + +xpfe +---- + +XPFE (Cross Platform Front End) is the SeaMonkey frontend. It contains +the XUL files for the browser interface, common files used by the other +parts of the mozilla suite, and the XBL files for the parts of the XUL +language that are implemented in XBL. Much of this code has been copied +to `browser/` and `toolkit/` for use in +Firefox, Thunderbird, etc. + + +xpfe/components +--------------- + +Components used by the Mozilla frontend, as well as implementations of +interfaces that other parts of mozilla expect. diff --git a/docs/contributing/editor.rst b/docs/contributing/editor.rst new file mode 100644 index 0000000000..1ce083d4fc --- /dev/null +++ b/docs/contributing/editor.rst @@ -0,0 +1,26 @@ +Editor / IDE integration +======================== + +You can use any editor or IDE to contribute to Firefox, as long as it can edit +text files. However, there are some steps specific to mozilla-central that may +be useful for a better development experience. This page attempts to document +them. + +.. note:: + + Visual Studio Code is the recommended editor for Firefox development. + Not because it is better than the other editors but because we decided to + focus our energy on a single editor. + +.. note:: + + This page is a work in progress. Please enhance this page with instructions + for your favourite editor. + +.. toctree:: + :maxdepth: 1 + + editors/vscode + editors/emacs + editors/vim + editors/others diff --git a/docs/contributing/editors/emacs.rst b/docs/contributing/editors/emacs.rst new file mode 100644 index 0000000000..fbd41195a1 --- /dev/null +++ b/docs/contributing/editors/emacs.rst @@ -0,0 +1,121 @@ +Emacs +===== + +ESLint +------ + +See `the devtools documentation <https://wiki.mozilla.org/DevTools/CodingStandards#Running_ESLint_in_Emacs>`__ +that describes how to integrate ESLint into Emacs. + +C/C++ Development Packages +-------------------------- + +General Guidelines to Emacs C++ Programming +------------------------------------------- + +The following guides give an overview of the C++ editing capabilities of emacs. + +It is worth reading through these guides to see what features are available. +The rest of this section is dedicated to Mozilla/Gecko specific setup for +packages. + + + * `C/C++ Development Environment for Emacs <https://tuhdo.github.io/c-ide.html>`__ + * `Emacs as C++ IDE <https://syamajala.github.io/c-ide.html>`__ + +rtags (LLVM/Clang-based Code Indexing) +-------------------------------------- + +Instructions for the installation of rtags are available at the +`rtags github repo <https://github.com/Andersbakken/rtags>`__. + +rtags requires a :ref:`compilation database <CompileDB back-end-compileflags>`. + +In order for rtags to index correctly, included files need to be copied and +unified compilation files need to be created. Either run a full build of the +tree, or if you only want indexes to be generated for the moment, run the +following commands (assuming you're in the gecko repo root): + +.. code:: + + cd gecko_build_directory + make export + ./config.status + +To increase indexing speed, it's best to remove unified build files and test +files from database updates. This can be done by creating a :code:`~/.rdmrc` +file with the following contents, with :code:`[src_dir]` replaced with either +the repo or build directory for your checkout: + +.. code:: + + -X */[src_dir]/*Unified*;*/[src_dir]/*/test/*;*/[src_dir]/*/tests/* + +Once the rdm daemon is running, the compilation database can be added to rtags +like so: + +.. code:: + + rc -J [gecko_build_directory]/compile_commands.json + +Note that this process will take a while initially. However, once the database +is built, it will only require incremental updates. As long as the rdm daemon +is running in the background, the database will be updated based on changes to +files. + +irony (LLVM/Clang-based Code Completion) +---------------------------------------- + +Instructions on the installation of irony-mode are available at the +`irony-mode github repo <https://github.com/Sarcasm/irony-mode>`__. + +irony-mode requires a :ref:`compilation database <CompileDB back-end-compileflags>`. + +Note that irony-mode, by default, uses elisp to parse the +:code:`compile_commands.json` file. As gecko is a very large codebase, this +file can easily be multiple megabytes, which can make irony-mode take multiple +seconds to load on a gecko file. + +It is recommended to use `this fork of irony-mode <https://github.com/Hylen/irony-mode/tree/compilation-database-guessing-4-pull-request>`__, +which requires the boost System and Filesystem libraries. + +`Checking the bug to get this patch into the mainline of irony-mode <https://github.com/Sarcasm/irony-mode/issues/176>`__ +is recommended, to see if the fork can be used or if the mainline repo can be +used. Using the Boost version of the irony-mode server brings file load times +to under 1s. + +Projectile (Project Management) +------------------------------- + +Instructions on the installation of projectile are available at the +`projectile github repo <https://github.com/bbatsov/projectile>`__. + +Projectile comes preconfigured for many project types. Since, gecko uses its +own special build system (mach), a new project type needs to be added. This can +be done via adding the following elisp configuration command to your emacs +configuration file. + +.. code:: + + (projectile-register-project-type 'gecko + '("mach" "moz.build") + "python mach --log-no-times build" + "python mach mochitest" + "python mach run") + +Assuming projectile-global-mode is on, this will allow projectile to run the +correct commands whenever it is working in a gecko repo. + +gdb +^^^ + +Emacs comes with great integration with gdb, especially when using +`gdb-many-windows <https://www.gnu.org/software/emacs/manual/html_node/emacs/GDB-User-Interface-Layout.html>`__. + +However, when gdb is invoked via mach, some special arguments +need to be passed in order to make sure the correct display mode is used. To +use M-x gdb with mach on firefox, use the following command: + +.. code:: + + gecko_repo_directory/mach run --debug --debugparams=-i=mi diff --git a/docs/contributing/editors/others.rst b/docs/contributing/editors/others.rst new file mode 100644 index 0000000000..b753ff1042 --- /dev/null +++ b/docs/contributing/editors/others.rst @@ -0,0 +1,41 @@ +Eclipse +======= + +You can generate an Eclipse project by running: + +.. code:: + + ./mach ide eclipse + +See also the `Eclipse CDT <https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Eclipse/Eclipse_CDT>`__ docs on MDN. + +Visual Studio +============= + +You can run a Visual Studio project by running: + +.. code:: + + ./mach ide visualstudio + +.. _CompileDB back-end-compileflags: + +CompileDB back-end / compileflags +================================= + +You can generate a :code:`compile_commands.json` in your object directory by +running: + +.. code:: + + ./mach build-backend --backend=CompileDB + +This file, the compilation database, is understood by a variety of C++ editors / IDEs +to provide auto-completion capabilities. You can also get an individual compile command by +running: + +.. code:: + + ./mach compileflags path/to/file + +This is how the :ref:`VIM <VIM>` integration works, for example. diff --git a/docs/contributing/editors/vim.rst b/docs/contributing/editors/vim.rst new file mode 100644 index 0000000000..0cce21d4e9 --- /dev/null +++ b/docs/contributing/editors/vim.rst @@ -0,0 +1,75 @@ +Vim / Neovim +============ + +AutoCompletion +-------------- + +For C++, anything that can use an LSP like :code:`coc.nvim`, +:code:`nvim-lspconfig`, or what not, should work as long as you generate a +:ref:`compilation database <CompileDB back-end-compileflags>` and point to it. + +Additionally, `YouCompleteMe <https://github.com/ycm-core/YouCompleteMe/>`__ +works without the need of a C++ compilation database as long as you have run +:code:`./mach build` or :code:`./mach configure`. Configuration for this lives +in :searchfox:`.ycm_extra_conf <.ycm_extra_conf>` at the root of the repo. + +Rust auto-completion should work both with Rust's LSP :code:`rust-analyzer`. + +Make sure that the LSP is configured in a way that it detects the root of the +tree as a workspace, not the crate you happen to be editing. For example, the +default of :code:`nvim-lspconfig` is to search for the closest +:code:`Cargo.toml` file, which is not what you want. You'd want something like: + +.. code :: + + root_dir = lspconfig.util.root_pattern(".git", ".hg") + +You also need to set some options to get full diagnostics: + +.. code :: + + "rust-analyzer.server.extraEnv": { + "CARGO_TARGET_DIR": "/path/to/objdir" + }, + "rust-analyzer.check.overrideCommand": [ "/path/to/mach", "--log-no-times", "cargo", "check", "--all-crates", "--message-format-json" ], + "rust-analyzer.cargo.buildScripts.overrideCommand": [ "/path/to/mach", "--log-no-times", "cargo", "check", "--all-crates", "--message-format-json" ], + +The easiest way to make these work out of the box is using +`neoconf <https://github.com/folke/neoconf.nvim/>`__, which +automatically supports importing VSCode configuration files. +:code:`./mach ide vscode --no-interactive` will then generate the right +configuration for you. + +ESLint +------ + +The easiest way to integrate ESLint with VIM is using the `Syntastic plugin +<https://github.com/vim-syntastic/syntastic>`__. + +In order for VIM to detect jsm files as JS you might want something like this +in your :code:`.vimrc`: + +.. code:: + + autocmd BufRead,BufNewFile *.jsm set filetype=javascript + +:code:`mach eslint --setup` installs a specific ESLint version and some ESLint +plugins into the repositories' :code:`node_modules`. + +You need something like this in your :code:`.vimrc` to run the checker +automatically on save: + +.. code:: + + autocmd FileType javascript,html,xhtml let b:syntastic_checkers = ['javascript/eslint'] + +You need to have :code:`eslint` in your :code:`PATH`, which you can get with +:code:`npm install -g eslint`. You need at least version 6.0.0. + +You can also use something like `eslint_d +<https://github.com/mantoni/eslint_d.js#editor-integration>`__ which should +also do that automatically: + +.. code:: + + let g:syntastic_javascript_eslint_exec = 'eslint_d' diff --git a/docs/contributing/editors/vscode.rst b/docs/contributing/editors/vscode.rst new file mode 100644 index 0000000000..9830dcbe4f --- /dev/null +++ b/docs/contributing/editors/vscode.rst @@ -0,0 +1,179 @@ +Visual Studio Code +================== + +.. toctree:: + :maxdepth: 1 + :glob: + +General Knowledge +----------------- + +`VSCode <https://code.visualstudio.com/>`__ is a multi-platform open-source programming editor developed by Microsoft and volunteers. +It has support for many programming languages using extensions. +This is the recommended editor for Firefox development. + +For more general information on the VSCode project see the `repository <https://github.com/Microsoft/vscode/>`__. + +Recommended extensions +---------------------- + +VS Code provides number of extensions for JavaScript, Rust, etc. By default, +Firefox source tree comes with its own set of recommendations of Visual Studio +Code extensions. They will be offered when you first open the project. + +If you need to refer to them later, the extensions are listed in +`.vscode/extensions.json <https://searchfox.org/mozilla-central/source/.vscode/extensions.json>`__. + +For Rust development, the `rust-analyzer <https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer>`__ extension is recommended. +`See the manual <https://rust-analyzer.github.io/manual.html>`__ for more information. + +Getting setup +------------- + +Close `VS Code` if it is already open, then build the configuration for `VS Code` +by simplying running from the terminal: + +.. code:: + + ./mach ide vscode + +This will automatically set some of the recommended preferences for the workspace, +and if you are set up for a full build, it will enable clangd and rust integrations. + +If successful, `VS Code` will open at the end. You do not need to run this command +every time to open `VS Code`, you may open it in the normal way. + +If you are running full builds, the command above will set up the `Clangd` +integration so that subsequent invocations of ``./mach build`` run and update the +integration. + +.. note:: + + If `VS Code` is already open with a previous configuration generated, please make sure to + restart `VS Code` otherwise the new configuration will not be used, and the `compile_commands.json` + needed by `clangd` server will not be refreshed. This is a known `bug <https://github.com/clangd/vscode-clangd/issues/42>`__ + in `clangd-vscode` extension + +Ignore Files in Mercurial Repositories +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using Mercurial in mozilla-central, VS Code will treat your build directories as ordinary directories by default, causing some undesirable behavior including long indexing times, Go to Definition will open files in the build directory instead of the source tree, and Search Files by Name will find duplicate files from the source tree and the build directory (note: when using Git, VS Code will not do this since it reads ``.gitignore``). You can follow these directions to have VS Code largely ignore your build directories: + +#. Go to Preferences -> Settings +#. Search "exclude" in the Settings +#. (optional) Select "Workspace" below the search bar to only change this setting for the mozilla-central repository +#. Under "Files: Exclude", click "Add Pattern", type ``obj-*`` (assuming your build directory names start with the default text, ``obj-``), and click "OK" +#. Repeat the step above for the "Files: Watcher Exclude" setting +#. Reload VS Code: the easiest way to do this is to quit and reopen it. + +Despite excluding the build directories above, Go to Definition will still correctly open files that only appear in the build directory such as generated source code. See `Bug 1790517 <https://bugzilla.mozilla.org/show_bug.cgi?id=1790517>`_ for our effort to automatically exclude the build directories. + +Recommended Preferences +~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + These are automatically set when running ``./mach ide vscode`` but may be + changed manually. These are set only for particular file types. + +* ``"editor.formatOnSave": true`` + * This will turn on automatically fixing formatting issues when you save a file. +* ``"editor.defaultFormatter": "esbenp.prettier-vscode"`` + * This sets the default formatter to prettier using the recommended prettier + extension. + +``*.jsm`` and ``*.sjs`` file extensions should also be associated with JavaScript: + +.. code:: + + "files.associations": { + "*.jsm": "javascript", + "*.sjs": "javascript", + }, + +C/C++ Features and Support +-------------------------- + +For C++ support we offer an out of the box configuration based on +`clangd <https://clangd.llvm.org>`__. + +Leveraging the `clang` toolchain compiler we now have support in the IDE for the following features: + +**1.** Syntax highlighting + +**2.** IntelliSense with comprehensive code completion and suggestion + +.. image:: ../img/auto_completion.gif + +**3.** Go-to definition and Go-to declaration + +.. image:: ../img/goto_definition.gif + +**4.** Find all references + +.. image:: ../img/find_references.gif + +**5.** Open type hierarchy + +.. image:: ../img/type_hierarchy.gif + +**6.** Rename symbol, all usages of the symbol will be renamed, including declaration, definition and references + +.. image:: ../img/rename_symbol.gif + +**7.** Code formatting, based on `clang-format` that respects our coding standard using the `.clang-format` and `.clang-format-ignore` files. Format can be performed on an entire file or on a code selection + +.. image:: ../img/format_selection.gif + +**8.** Inline parsing errors with limited auto-fix hints + +.. image:: ../img/diagnostic_error.gif + +**9.** Basic static-code analysis using `clang-tidy` and our list of enabled checkers. (This is still in progress not all checkers are supported by `clangd`) + +Clangd-specific Commands +------------------------ + +Clangd supports some commands that are specific to C/C++: + +.. code:: + + "clangd.switchheadersource" + +This command navigates from the currently open header file to its corresponding source file (if there is one), or vice versa. + +This command can be invoked from the command menu (activated via ``F1``), or using its keybinding of ``Alt+o`` (``Alt+cmd+o`` on Mac). The keybinding can also be customized in ``Keyboard Shortcuts``. + +Remote Development over SSH +--------------------------- + +VS Code provides an `extension <https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh>`__ that lets you use any remote machine with a SSH server as your development environment. No matter if it's Linux based, macOS or Windows, as long as the target machine offers a SSH connection, it can be used for development. + +No source code needs to be on your local machine to use VS Code remotely since the extension runs commands and other extensions directly on the remote machine. + +In order to setup a connection please follow these steps: + +**1.** Open VS Code and select from the left side panel ``Remote Explorer`` + +.. image:: ../img/remote_explorer.png + +**2.** From the ``Remote Explorer`` panel select ``SSH Targets`` and click on ``Add`` and enter the connection details + +.. image:: ../img/remote_explorer_add.png + +.. image:: ../img/remote_explorer_add_wind.png + +**3.** Click on the connection that you just configured at the previous step + +**4.** Finally you should be connected to the desired remote SSH server + +.. image:: ../img/connection_done.png + +Please note that during the first connection VS Code will install itself remotely and also install all of the needed dependencies. + + + +Filing Bugs +----------- + +Bugs should be filed in the `Firefox Build System` product under `Developer Environment Integration`, preferably blocking `Bug 1662709 <https://bugzilla.mozilla.org/show_bug.cgi?id=1662709>`__. diff --git a/docs/contributing/engineering_show_and_tell.rst b/docs/contributing/engineering_show_and_tell.rst new file mode 100644 index 0000000000..87c2013bb8 --- /dev/null +++ b/docs/contributing/engineering_show_and_tell.rst @@ -0,0 +1,83 @@ +Engineering Show and Tell +========================= + +The engineering teams at Mozilla have put together a series of 5 minute long +tips and tricks to help boost productivity. You can find the recordings below. + +August 2021 +----------- + +`Link to the August 2021 recording <https://mozilla.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=bd0c503d-903f-4829-9c9d-ad7c011cee9b>`_ + +Links + +- Mossop: Mercurial Tips n Tricks + + - https://github.com/Mossop/dotfiles/blob/main/shared/hg/hgrc + - https://mikeconley.github.io/documents/How_mconley_uses_Mercurial_for_Mozilla_code + +- mak: Gmail filtering with Google Apps Script + + - https://script.google.com/home + - https://paste.mozilla.org/9zEDnAiA#L9 + - https://developers.google.com/apps-script/reference/ + +- mhowell: Windows Tools You Might Not Know About + + - https://docs.google.com/document/d/1DyeTPIEz3SIcw7ldvSGKUVp4XP34Ue-_pV8lYmRJX6I/ + +- bryce: Debugging Remote Resources Via Proxy + + - https://www.telerik.com/fiddler + - https://www.charlesproxy.com/ + - https://mitmproxy.org/ + +- jody: CircleCI for VS Code + + - https://marketplace.visualstudio.com/items?itemName=jodyh.circleci-vscode + +- sfink: Moz workflow aids for post-landing pruning, taskcluster job replication & more + + - https://github.com/hotsphink/sfink-tools + - https://hg.sr.ht/~sfink/sfink-tools + +- mconley: Multiple mozconfigs with mozconfigwrapper + + - https://github.com/ahal/mozconfigwrapper + +February 2021 +------------- + +`Link to the February 2021 recording <https://mozilla.zoom.us/rec/share/RvN62-Y3ByGmeyQChmsqXy6WXAE3iJETeB2yNj1xq4-z3c80ewwFaz-EAVnoHSo-.8FbmZF3nQEWBPFSr>`_ + +Slide decks: + +- `bash scripts and keyboard shortcuts <https://docs.google.com/presentation/d/1T8z99Hy0rI-_W3wJIZsG-edKRiicxgl-QeBoJuM90qQ/edit?usp=sharing>`_ +- `sccache-dist <https://docs.google.com/presentation/d/1_mN5rgV2LrzRKEOn06j4uaryYC9zRQJOdomgeBrJ8RA/edit#slide=id.g832b271044_1_1173>`_ +- `How to animate things smoothly <https://docs.google.com/presentation/d/11csNTR1GnVs2BdjN1alJcTbjXMhKyhpv9GIx2jNMJ6U/edit#slide=id.p>`_ +- `How I learned to love the M-C <https://docs.google.com/presentation/d/13O06nyDWqfbZyLeGRdLztd234zJ2SQcJu7LkBFDLnYg/edit?usp=sharing>`_ + +Links for "Editor, Lint, & More" talk: + +- :ref:`Linting` +- :ref:`lint-vcs-hook` +- https://eslint.org/docs/user-guide/integrations + +Links for "Stupid Mac Tricks" talk: + +- https://www.obdev.at/products/launchbar/index.html +- Moom: https://itunes.apple.com/app/id496437906?mt=12&ls=1 +- https://kapeli.com/dash +- https://git-fork.com/ +- https://www.usboverdrive.com/ +- https://manytricks.com/download/butler/ +- https://bjango.com/mac/istatmenus/ +- https://iterm2.com/ + +Other links: + +- https://twitter.com/asutherland/status/1274942012316319744 +- https://scootersoftware.com/ +- https://pasteapp.io/ +- https://github.com/acreskeyMoz/browsertime_scripts +- https://chuttenblog.wordpress.com/2021/01/18/doubling-the-speed-of-windows-firefox-builds-using-sccache-dist/ diff --git a/docs/contributing/how_to_submit_a_patch.rst b/docs/contributing/how_to_submit_a_patch.rst new file mode 100644 index 0000000000..0ceba7f39c --- /dev/null +++ b/docs/contributing/how_to_submit_a_patch.rst @@ -0,0 +1,245 @@ +How to submit a patch +===================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +Submitting a patch, getting it reviewed, and committed to the Firefox +source tree involves several steps. This article explains how. + +.. note:: + + We are also providing a :ref:`Firefox Contributors Quick Reference <Firefox Contributors' Quick Reference>` for contributors. + +The process of submission is illustrated by the following diagram, and +each step is detailed below: + +.. mermaid:: + + graph TD; + Preparation --> c[Working on a patch]; + c[Working on a patch] --> Testing; + Testing --> c[Working on a patch]; + Testing --> e[Submit the patch]; + e[Submit the patch] --> d[Getting Reviews] + d[Getting Reviews] -- Addressing Review comment --> c[Working on a patch]; + d[Getting Reviews] --> h[Push the change]; + + + + +Preparation +----------- + +Every change to the code is tracked by a bug report +in `bugzilla.mozilla.org <https://bugzilla.mozilla.org/>`__. Without a +bug, code will not be reviewed, and without review, code will not be +accepted. To avoid duplication, `search for an existing +bug <https://bugzilla.mozilla.org/query.cgi?format=specific>`__ about +your change, and only if none exists, file a new one. Most communication +about code changes take place in the associated code +review, so be sure the bug describes the exact problem being solved. + +Please verify the bug is for the correct product and component. For more +information, ask questions on the newsgroups, or on the #developers room +on `chat.mozilla.org <https://chat.mozilla.org>`__. + +The person working on a bug should be the 'assignee' of that bug in +Bugzilla. If somebody else is currently the assignee of a bug, email +this person to coordinate changes. If the bug is unassigned, leave a +message in the bug's comments, stating that you intend working on it, +and suggest that someone with bug-editing privileges assign it to you. + +Some teams wait for new contributors to attach their first patch before +assigning a bug. This makes it available for other contributors, in case +the new contributor is unable to level up to patch creation. By +expressing interest in a bug comment, someone from that team should +guide you through their process. + + +Module ownership +---------------- + +All code is supervised by a `module +owner <https://www.mozilla.org/en-US/about/governance/policies/module-ownership/>`__. +This person will be responsible for reviewing and accepting the change. +Before writing your code, determine the module owner, verifying your +proposed change is considered acceptable. They may want to look over any +new user interface (UI review), functions (API review), or testcases for +the proposed change. + +If module ownership is not clear, ask on the newsgroups or `on +Matrix <https://chat.mozilla.org>`__. The revision log for the relevant +file might also be helpful. For example, see the change log for +``browser/base/content/browser.js``, by clicking the "Hg Log" +link at the top of `Searchfox <https://searchfox.org/mozilla-central/source/>`__, or +by running ``hg log browser/base/content/browser.js``. The corresponding +checkin message will contain something like "r=nickname", identifying +active code submissions, and potential code reviewers. + + +Working on a patch +------------------ + +Changes to the Firefox source code are presented in the form of a patch. +A patch is a commit to version control. Firefox and related code is +stored in our `Mercurial +server <https://hg.mozilla.org/mozilla-central>`__. We have extensive +documentation on using Mercurial in our guide, :ref:`Mercurial Overview`. + +Each patch should represent a single complete change, separating +distinct changes into multiple individual patches. If your change +results in a large, complex patch, seek if it can be broken into +`smaller, easy to understand patches representing complete +steps <https://secure.phabricator.com/book/phabflavor/article/writing_reviewable_code/#many-small-commits>`__, +applied on top of each other. This makes it easier to review your +changes, `leading to quicker +reviews, <https://groups.google.com/group/mozilla.dev.planning/msg/2f99460f57f776ef?hl=en>`__ +and improved confidence in this review outcome. + +Also ensure that your commit message is formatted appropriately. A +simple commit message should look like this: + +:: + + Bug 123456 - Change this thing to work better by doing something. r=reviewers + +The ``r=reviewers`` part is optional; if you are using Phabricator, +Lando will add it automatically based on who actually granted review, +and in any case the person who does the final check-in of the patch will +make sure it's added. + +The text of the message should be what you did to fix the bug, not a +description of what the bug was. If it is not obvious why this change is +appropriate, then `explain why in the commit +message <https://mozilla-version-control-tools.readthedocs.io/en/latest/mozreview/commits.html#write-detailed-commit-messages>`__. +If this does not fit on one line, then leave a blank line and add +further lines for more detail and/or reasoning. + +You can edit the message of the current commit at any time using +``hg commit --amend`` or ``hg histedit``. + +Also look at our :ref:`Reviewer Checklist` for a list +of best practices for patch content that reviewers will check for or +require. + + +Testing +------- + +All changes must be tested. In most cases, an `automated +test <https://developer.mozilla.org/docs/Mozilla/QA/Automated_testing>`__ is required for every +change to the code. + +While we desire to have automated tests for all code, we also have a +linter tool which runs static analysis on our JavaScript, for best +practices and common mistakes. See :ref:`ESLint` for more information. + +Ensure that your change has not caused regressions, by running the +automated test suite locally, or using the `Mozilla try +server <https://wiki.mozilla.org/Build:TryServer>`__. Module owners, or +developers `on Matrix <https://chat.mozilla.org>`__ may be willing to +submit jobs for those currently without try server privileges. + + +Submit the patch +---------------- + +.. note:: + + Make sure you rebase your patch on top of the latest build before you + submit to prevent any merge conflicts. + +Mozilla uses Phabricator for code review. See the `Mozilla Phabricator +User +Guide <https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html>`__ +for instructions. + +Don't be shy in posting partial patches, demonstrating potential +approaches, and asking for preliminary feedback. It is easier for others +to comment, and offer suggestions, when a question is accompanied by +some code. + + +Getting reviews for my patch +---------------------------- + +See the dedicated page :ref:`Getting reviews` + + +Addressing review comments +-------------------------- + +It is unusual for patches to be perfect the first time around. The +reviewer may use the ‘Request Changes’ +`action <http://moz-conduit.readthedocs.io/en/latest/phabricator-user.html#reviewing-patches>`__ +and list problems that must be addressed before the patch can be +accepted. Please remember that requesting revisions is not meant to +discourage participation, but rather to encourage the best possible +resolution of a bug. Carefully work through the changes that the +reviewer recommends, attach a new patch, and request review again. + +Sometimes a reviewer will grant conditional review with the ‘Accept +Revision’ action but will also indicate minor necessary changes, such as +spelling, or indentation fixes. All recommended corrections should be +made, but a re-review is unnecessary. Make the changes and submit a new +patch. If there is any confusion about the revisions, another review +should be requested. + +Sometimes, after a patch is reviewed, but before it can be committed, +someone else makes a conflicting change. If the merge is simple, and +non-invasive, post an updated version of the patch. For all non-trivial +changes, another review is necessary. + +If at any point the review process stalls for more than two weeks, see +the previous 'Getting attention' section. + +In many open source projects, developers will accept patches in an +unfinished state, finish them, and apply the completed code. In +Mozilla's culture, **the reviewer will only review and comment on a +patch**. If a submitter declines to make the revisions, the patch will +sit idle, until someone chooses to take it on. + + +Pushing the change +------------------ + +A patch can be pushed (aka. 'landed') after it has been properly +reviewed. + +.. note:: + + Note: Be sure to build the application with the patch applied. This + ensures it runs as expected, passing automated tests, and/or runs + through the `try + server <https://wiki.mozilla.org/Build:TryServerAsBranch>`__. In the + bug, please also mention you have completed this step. + + Submitting untested patches wastes the committer's time, and may burn + the release tree. Please save everyone's time and effort by + completing all necessary verifications. + + +Ask the reviewer to land the patch for you. +For more details, see :ref:`push_a_change` + +If pushing the patch yourself, please follow :ref:`Committing rules and responsibilities`. +`Lando <https://moz-conduit.readthedocs.io/en/latest/lando-user.html>`__ is used +to automatically land your code. + + +Regressions +----------- + +It is possible your code causes functional or performance regressions. +There is a tight +`policy <https://www.mozilla.org/about/governance/policies/regressions/>`__ on +performance regressions, in particular. This means your code may be +dropped, leaving you to fix and resubmit it. Regressions, ultimately +mean the tests you ran before checking in are not comprehensive enough. +A resubmitted patch, or a patch to fix the regression, should be +accompanied by appropriate tests. + +After authoring a few patches, consider `getting commit access to +Mozilla source code <https://www.mozilla.org/about/governance/policies/commit/>`__. diff --git a/docs/contributing/img/auto_completion.gif b/docs/contributing/img/auto_completion.gif new file mode 100644 index 0000000000..4d545c29fd Binary files /dev/null and b/docs/contributing/img/auto_completion.gif differ diff --git a/docs/contributing/img/connection_done.png b/docs/contributing/img/connection_done.png new file mode 100644 index 0000000000..fc87571e4e Binary files /dev/null and b/docs/contributing/img/connection_done.png differ diff --git a/docs/contributing/img/diagnostic_error.gif b/docs/contributing/img/diagnostic_error.gif new file mode 100644 index 0000000000..25d50a7d7c Binary files /dev/null and b/docs/contributing/img/diagnostic_error.gif differ diff --git a/docs/contributing/img/example-stack.png b/docs/contributing/img/example-stack.png new file mode 100644 index 0000000000..c12265ae5f Binary files /dev/null and b/docs/contributing/img/example-stack.png differ diff --git a/docs/contributing/img/find_references.gif b/docs/contributing/img/find_references.gif new file mode 100644 index 0000000000..e986894566 Binary files /dev/null and b/docs/contributing/img/find_references.gif differ diff --git a/docs/contributing/img/format_selection.gif b/docs/contributing/img/format_selection.gif new file mode 100644 index 0000000000..28c88b3fa3 Binary files /dev/null and b/docs/contributing/img/format_selection.gif differ diff --git a/docs/contributing/img/goto_definition.gif b/docs/contributing/img/goto_definition.gif new file mode 100644 index 0000000000..9b3dcbf90f Binary files /dev/null and b/docs/contributing/img/goto_definition.gif differ diff --git a/docs/contributing/img/remote_explorer.png b/docs/contributing/img/remote_explorer.png new file mode 100644 index 0000000000..3f7a97bdc0 Binary files /dev/null and b/docs/contributing/img/remote_explorer.png differ diff --git a/docs/contributing/img/remote_explorer_add.png b/docs/contributing/img/remote_explorer_add.png new file mode 100644 index 0000000000..9faf9750fb Binary files /dev/null and b/docs/contributing/img/remote_explorer_add.png differ diff --git a/docs/contributing/img/remote_explorer_add_wind.png b/docs/contributing/img/remote_explorer_add_wind.png new file mode 100644 index 0000000000..6aa9f8d54d Binary files /dev/null and b/docs/contributing/img/remote_explorer_add_wind.png differ diff --git a/docs/contributing/img/rename_symbol.gif b/docs/contributing/img/rename_symbol.gif new file mode 100644 index 0000000000..d41fcd7ed6 Binary files /dev/null and b/docs/contributing/img/rename_symbol.gif differ diff --git a/docs/contributing/img/type_hierarchy.gif b/docs/contributing/img/type_hierarchy.gif new file mode 100644 index 0000000000..139bdf88cb Binary files /dev/null and b/docs/contributing/img/type_hierarchy.gif differ diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst new file mode 100644 index 0000000000..6dca72aa02 --- /dev/null +++ b/docs/contributing/index.rst @@ -0,0 +1,41 @@ +Working on Firefox +================== + +Welcome to the Firefox codebase. This is the home of the Firefox +development process and source code documentation. + +.. toctree:: + :caption: Making Changes To Firefox + :maxdepth: 1 + + contribution_quickref + stack_quickref + pocket-guide-shipping-firefox + editor + reviews + +.. toctree:: + :caption: The Mercurial Version Control System + :maxdepth: 1 + :glob: + + vcs/* + + +.. toctree:: + :caption: Debugging + :maxdepth: 1 + :glob: + + debugging/* + + +.. toctree:: + :caption: Additional Information + :maxdepth: 1 + + directory_structure + build/artifact_builds + build/building_mobile_firefox + build/supported + engineering_show_and_tell diff --git a/docs/contributing/pocket-guide-shipping-firefox.rst b/docs/contributing/pocket-guide-shipping-firefox.rst new file mode 100644 index 0000000000..fdd37b9620 --- /dev/null +++ b/docs/contributing/pocket-guide-shipping-firefox.rst @@ -0,0 +1,523 @@ +Pocket Guide: Shipping Firefox +============================== + +*Estimated read time:* 15min + + +Introduction +------------ + +The purpose of this document is to provide a high level understanding of +how Mozilla ships Firefox. With the intention of helping new Mozillians +(and those who would like a refresher) understand the basics of our +release process, tools, common terms, and mechanisms employed in +shipping Firefox to our users. Often this document will introduce a +concept, explain how it fits into the process, and then provide a link +to learn more if interested. + +Repositories & Channels +----------------------- + +Shipping Firefox follows a software release :ref:`train model <train model>` +along 3 primary code :ref:`repositories <repositories>`; mozilla-central +(aka “m-c”), mozilla-beta, and mozilla-release. Each of these repositories are +updated within a defined cadence and built into one of our Firefox +products which are released through what is commonly referred to as +:ref:`Channels <channels>`: Firefox Nightly, Firefox Beta, and Firefox Release. + +`Firefox Nightly <https://whattrainisitnow.com/release/?version=nightly>`__ offers access to the latest cutting edge features +still under active development. Released every 12 hours with all the +changes that have :ref:`landed <landing>` on mozilla-central for Desktop and on +`main in firefox-android <https://github.com/mozilla-mobile/firefox-android/tree/main>`__ for Android. + +Every `4 weeks <https://whattrainisitnow.com/calendar/>`__, we +:ref:`merge <merge>` the code from mozilla-central to our +mozilla-beta branch. +For Android, we branch from main on firefox-android to a release branch. +New code or features can be added to mozilla-beta +outside of this 4 week cadence but will be required to land in +mozilla-central and then be :ref:`uplifted <uplift>` into +mozilla-beta. +Similarly for Android, uplifts are required to land in main on firefox-android before +backporting to the firefox-android release branch. + +`Firefox Beta <https://whattrainisitnow.com/release/?version=beta>`__ is for developers and early adopters who want to see +and test what’s coming next in Firefox. We release a new Desktop/Android Beta version +three times a week. + +.. note:: + + The first and second beta builds of a new cycle are shipped to a + subset of our Beta population. The full Beta population gets updated + starting with Beta 3 only.* + +Each Beta cycle lasts a total of 4 weeks where a final build is +validated by our QA and tagged for release into the mozilla-release +branch for Desktop. On Android we release from the same release branch +used during the Beta cycle. + +.. note:: + + **Firefox Developer Edition** *is a separate product based on + the mozilla-beta repo and is specifically tailored for Web Developers.* + +`Firefox Release <https://whattrainisitnow.com/release/?version=release>`__ is released every 4 weeks and is the end result +of our Beta cycle. This is our primary product shipping to hundreds of +millions of users. While a release is live, interim updates (dot releases) +are used to ship important bug fixes to users prior to the next major release. +These can happen on an as-needed basis when there is an important-enough +:ref:`driver <dot release drivers>` to do so (such as a critical bug severely +impairing the usability of the product for some users). In order to provide +better predictability, there is also a planned dot release scheduled for two +weeks after the initial go-live for less-critical fixes and other +:ref:`ride-along fixes <ride alongs>` deemed low-risk enough to include. + +.. note:: + `Firefox ESR (Extended Support Release) <https://whattrainisitnow.com/release/?version=esr>`__ *is a separate + product intended for Enterprise use. Major updates are rolled out once + per year to maintain stability and predictability. ESR also + contains a number of policy options not available in the standard + Firefox Release. Minor updates are shipped in sync with the Firefox + Release schedule for security and select quality fixes only.* + +Further Reading/Useful links: + +- `Firefox + Trains <https://whattrainisitnow.com/>`__ +- `Release + Calendar <https://whattrainisitnow.com/calendar/>`__ +- `Firefox Release + Process <https://wiki.mozilla.org/Release_Management/Release_Process>`__ +- `Firefox Delivery + dashboard <https://mozilla.github.io/delivery-dashboard/>`__ + +Landing Code and Shipping Features +---------------------------------- + +Mozillians (those employed by MoCo and the broader community) land lots +of code in the Mozilla repositories: fixes, enhancements, compatibility, +new features, etc. and is managed by :ref:`Mercurial <Mercurial Overview>` (aka +hg). All new code is tracked in :ref:`Bugzilla <bugzilla>`, reviewed +in :ref:`Phabricator <Phabricator>`, and then checked into the +mozilla-central repository using :ref:`Lando <Lando>`. + +.. note:: + + Some teams use :ref:`GitHub <github>` during development + but will still be required to use Phabricator (tracked in Bugzilla) to + check their code into the mozilla-central hg repository. + +The standard process for code to be delivered to our users is by ‘riding +the trains’, meaning that it’s landed in mozilla-central where it waits +for the next Beta cycle to begin. After merging to Beta the code will +stabilize over a 4 week period (along with everything else that merged +from mozilla-central). At the end of the beta cycle a release candidate +(:ref:`RC <rc>`) build will be generated, tested thoroughly, and +eventually become the next version of Firefox. + +Further Reading/Useful links: + +- `Phabricator and why we use it <https://wiki.mozilla.org/Phabricator>`__ +- `Firefox Release Notes Process <https://wiki.mozilla.org/Release_Management/Release_Notes>`__ +- `Firefox Release Notes Nomination <https://wiki.mozilla.org/Release_Management/Release_Notes_Nomination>`__ + +An exception to this process... +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Not all code can simply wait for the normal train model to be included +in a Firefox build. There are a variety of reasons for this; critical +fixes, security concerns, stabilizing a feature that’s already in Beta, +shipping high priority features faster, and so on. + +In these situations an uplift can be requested to take a recent landing +in mozilla-central and merge specific bits to another repository outside +the standard train model. After the request is made within Bugzilla, +:ref:`Release Management <release management>` will assess the potential risk +and will make a decision on whether it’s accepted. + +Further Reading/Useful links: + +- `Patch uplifting + rules <https://wiki.mozilla.org/Release_Management/Uplift_rules>`__ +- `Requesting an + uplift <https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift>`__ + +Ensuring build stability +~~~~~~~~~~~~~~~~~~~~~~~~ + +Throughout the process of landing code in mozilla-central to riding the +trains to Firefox Release, there are many milestones and quality +checkpoints from a variety of teams. This process is designed to ensure +a quality and compelling product will be consistently delivered to our +users with each new version. See below for a distilled list of those +milestones. + +=========================================== ================ ================= =============================================================================== +Milestone Week Day of Week +------------------------------------------- ---------------- ----------------- ------------------------------------------------------------------------------- +Merge Day Nightly W1 Monday Day 1 of the new Nightly Cycle +PI Request deadline Nightly W1 Friday Manual QA request deadline for high risk features +Feature technical documentation due Nightly W2 Friday Deadline for features requiring manual QA +Beta release notes draft Nightly W4 Wednesday +Nightly features Go/No-Go decisions Nightly W4 Wednesday +Feature Complete Milestone Nightly W4 Wednesday Last day to land risky patches and/or enable new features +Nightly soft code freeze start Nightly W4 Thursday Stabilization period in preparation to merge to Beta +String freeze Nightly W4 Thursday Modification or deletion of strings exposed to the end-users is not allowed +QA pre-merge regression testing completed Nightly W4 Friday +Merge Day Beta W1 Monday Day 1 of the new Beta cycle +Pre-release sign off Beta W3 Friday Final round of QA testing prior to Release +Firefox RC week Beta W4 Monday Validating Release Candidate builds in preparation for the next Firefox Release +Release Notes ready Beta W4 Tuesday +What’s new page ready Beta W4 Wednesday +Firefox go-live @ 6am PT Release W1 Tuesday Day 1 of the new Firefox Release to 25% of Release users +Firefox Release bump to 100% Release W1 Thursday Increase deployment of new Firefox Release to 100% of Release users +Scheduled dot release approval requests due Release W2 Friday All requests required by EOD +Scheduled dot release go-live Release W3 Tuesday By default, ships when ready. Specific time available upon request. +=========================================== ================ ================= =============================================================================== + + +The Release Management team (aka “Relman”) monitors and enforces this +process to protect the stability of Firefox. Each member of Relman +rotates through end-to-end ownership of a given :ref:`release +cycle <release cycle>`. The Relman owner of a cycle will focus on the +overall release, blocker bugs, risks, backout rates, stability/crash +reports, etc. Go here for a complete overview of the `Relman Release +Process +Checklist <https://wiki.mozilla.org/Release_Management/Release_Process_Checklist_Documentation>`__. + +.. note:: + + While Relman will continually monitor the overall health of each + Release it is the responsibility of the engineering organization to + ensure the code they are landing is of high quality and the potential + risks are understood. Every Release has an assigned :ref:`Regression + Engineering Owner <reo>` (REO) to ensure a decision is made + about each regression reported in the release.* + +Further Reading/Useful links: + +- `Release Tracking + Rules <https://wiki.mozilla.org/Release_Management/Tracking_rules>`__ +- `Release + Owners <https://wiki.mozilla.org/Release_Management/Release_owners>`__ +- `Regression Engineering + Owners <https://wiki.mozilla.org/Platform#Regression_Engineering_Owner_.28REO.29>`__ +- `Commonly used Bugzilla queries for all + Channels <https://trainqueries.herokuapp.com/>`__ + +Enabling/Disabling code (Prefs) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Within Firefox we allow the ability to Enable/Disable bits of code or +entire features using `Preferences <preferences>`. There are many +reasons why this is useful. Here are some examples: + +- Continual development over multiple release cycles without exposing + partially completed features to our users +- Provide the ability to quickly disable a feature if there is a + problem found during the release process +- Control features which are experimental or not ready to be shown to a + specific channel population (e.g. enabled for Beta but disabled for + Release) +- A/B testing via :ref:`telemetry <telemetry>` experiments + +.. note:: + + :ref:`Normandy <normandy>` Pref Rollout is a feature that + allows Mozilla to change the state of a preference for a targeted set of + users, without deploying an update to Firefox. This is especially useful + when conducting experiments or a gradual rollout of high risk features + to our Release population. + +Further Reading/Useful links: + +- `Brief guide to Mozilla + preferences <https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences>`__ +- `Normandy Pref + rollout <https://wiki.mozilla.org/Firefox/Normandy/PreferenceRollout>`__ + +Release & Feature QA +~~~~~~~~~~~~~~~~~~~~ + +Release QA is performed regularly and throughout the Release Cycle. +Organized in two-week sprints its primary goals are: + +- Qualifying builds for release +- Feature testing +- Product Integrity requests +- Bug work +- Community engagement + +Features that can have significant impact and/or pose risk to the code +base should be nominated for QA support by the :ref:`feature +owner <feature owner>` in its intended release. This process is kicked +off by filing a :ref:`Product Integrity <product integrity>` team request +:ref:`PI request <pi request>`. These are due by the end of week 2 +of the Nightly cycle. + +.. note:: + + Manual QA testing is only required for features as they go + through the Beta cycle. Nightly Feature testing is always optional. + +Further Reading/Useful links: + +- `QA Feature + Testing <https://wiki.mozilla.org/QA/Feature_Testing_v2>`__ +- `Release QA + overview <https://docs.google.com/document/d/1ic_3TO9-kNmZr11h1ZpyQbSlgiXzVewr3kSAP5ML4mQ/edit#heading=h.pvvuwlkkvtc4>`__ +- `PI Request template and + overview <https://mana.mozilla.org/wiki/pages/viewpage.action?spaceKey=PI&title=PI+Request>`__ + +Experiments +~~~~~~~~~~~ + +As we deliver new features to our users we continually ask ourselves +about the potential impacts, both positive and negative. In many new +features we will run an experiment to gather data around these impacts. +A simple definition of an experiment is a way to measure how a change to +our product affects how people use it. + +An experiment has three parts: + +1. A new feature that can be selectively enabled +2. A group of users to test the new feature +3. Telemetry to measure how people interact with the new feature + +Experiments are managed by an in-house tool called +`Experimenter <https://experimenter.services.mozilla.com/>`__. + +Further Reading/Useful links: + +- `More about experiments and + Experimenter <https://github.com/mozilla/experimenter>`__ +- `Requesting a new + Experiment <https://experimenter.services.mozilla.com/experiments/new/>`__ + (Follow the ‘help’ links to learn more) +- `Telemetry <https://wiki.mozilla.org/Telemetry>`__ + +Definitions +----------- + +.. _approval flag: + +**Approval Flag** - A flag that represents a security approval or uplift +request on a patch. + +.. _bugzilla: + +**Bugzilla** - Web-based general purpose bug tracking system and testing +tool. + +.. _channel: + +**Channel** - Development channels producing concurrent releases of +Firefox for Windows, Mac, Linux, and Android. + +.. _chemspill: + +**Chemspill** - Short for Chemical Spill. A chemspill is a rapid +security-driven or critical stsbility dot release of our product. + +.. _channel meeting: + +**Channel Meeting** - A twice weekly time to check in on the status +of the active releases with the release team. + +.. _dot release drivers: + +**Dot Release Drivers** - Issues/Fixes that are significant enough to +warrant a minor dot release to the Firefox Release Channel. Usually to +fix a stability (top-crash) or Security (Chemspill) issue. + +.. _early beta: + +**Early Beta** - Beta releases with the features gated by EARLY_BETA_OR_EARLIER +enabled. The first 2 weeks of Beta releases during the cycle are early beta releases. + +.. _feature owner: + +**Feature Owner** - The person who is ultimately responsible for +developing a high quality feature. This is typically an Engineering +Manager or Product Manager. + +.. _fenix: + +**Fenix** - Also known as Firefox Preview is an all-new browser for +Android based on GeckoView and Android Components + +.. _github: + +**Github** - Web-based version control and collaboration platform for +software developers + +.. _gtb: + +**GTB** - Acronym for Go to build. Mostly used in the release schedule +communication ("Go to build on March 18"), this means that we initiate the +building of a specific release. + +.. _landing: + +**Landing** - A general term used for when code is merged into a +particular source code repository + +.. _lando: + +**Lando** - Automated code lander for Mozilla. It is integrated with +our `Phabricator instance <https://phabricator.services.mozilla.com>`__ +and can be used to land revisions to various repositories. + +.. _mercurial: + +**Mercurial** - A source-code management tool (just like git) +which allows users to keep track of changes to the source code +locally and share their changes with others. It is also called hg. + +.. _merge: + +**Merge** - General term used to describe the process of integrating and +reconciling file changes within the mozilla repositories + +.. _nightly soft code freeze: + +**Nightly Soft Code Freeze** - Last week of the nightly cycle on mozilla-central +just before the merge to beta during which landing risky or experimental code +in the repository is discouraged. + +.. _normandy: + +**Normandy** - Normandy is a collection of servers, workflows, and +Firefox components that enables Mozilla to remotely control Firefox +clients in the wild based on precise criteria + +.. _nucleus: + +**Nucleus** - Name of the internal application used by release managers +to prepare and publish release notes. The data in this application is +fetched by mozilla.org. + +.. _orange_factor: + +**Orange** - Also called flaky or intermittent tests. Describes a state +when a test or a testsuite can intermittently fail. + +.. _phabricator: + +**Phabricator** - Mozilla’s instance of the web-based software +development collaboration tool suite. Read more about `Phabricator as a +product <https://phacility.com/phabricator/>`__. + +.. _pi request: + +**PI Request** - Short for Product Integrity Request is a form +submission request that’s used to engage the PI team for a variety of +services. Most commonly used to request Feature QA it can also be used +for Security, Fuzzing, Performance, and many other services. + +.. _preferences: + +**Preferences** - A preference is any value or defined behavior that can +be set (e.g. enabled or disabled). Preference changes via user interface +usually take effect immediately. The values are saved to the user’s +Firefox profile on disk (in prefs.js). + +.. _rc: + +**Release Candidate** - Beta version with potential to be a final +product, which is ready to release unless significant bugs emerge. + +.. _rc week: + +**RC Week** - The week prior to release go-live is known as RC week. +During this week an RC is produced and tested. + +.. _release cycle: + +**Release Cycle** - The sum of stages of development and maturity for +the Firefox Release Product. + +.. _reo: + +**Regression Engineering Owner** - A partner for release management +assigned to each release. They both keep a mental state of how we are +doing and ensure a decision is made about each regression reported in +the release. AKA *REO*. + +.. _release engineering: + +**Release engineering** - Team primarily responsible for maintaining +the build pipeline, the signature mechanisms, the update servers, etc. aka *releng* + +.. _release management: + +**Release Management** - Team primarily responsible for the process of +managing, planning, scheduling and controlling a software build through +different stages and environments. aka *relman*. + +.. _relnotes: + +**Relnotes** - Short for release notes. Firefox Nightly, Beta, and Release each ship +with release notes. + +.. _Repository: + +**Repository** - a collection of stored data from existing databases +merged into one so that it may be shared, analyzed or updated throughout +an organization. + +.. _ride alongs: + +**Ride Alongs** - Bug fixes that are impacting release users but not +considered severe enough to ship without an identified dot release +driver. + +.. _rollout: + +**Rollout** - Shipping a release to a percentage of the release population. + +.. _status flags: + +**Status Flags** - A flag that represents the status of the bug with +respect to a Firefox release. + +.. _string freeze: + +**String Freeze** - Period during which the introduction, modification, or +deletion of strings exposed to the end-users is not allowed so as to allow our +localizers to translate our product. + +.. _taskcluster: + +**taskcluster** - Our execution framework to build, run tests on multiple +operating system, hardware and cloud providers. + +.. _telemetry: + +**Telemetry** - Firefox measures and collects non-personal information, +such as performance, hardware, usage and customizations. This +information is used by Mozilla to improve Firefox. + +.. _train model: + +**Train model** - a form of software release schedule in which a number +of distinct series of versioned software releases are released as a +number of different "trains" on a regular schedule. + +.. _tracking flags: + +**Tracking Flags** - A Bugzilla flag that shows whether a bug is being investigated +for possible resolution in a Firefox release. Bugs marked tracking-Firefox XX are +bugs that must be resolved one way or another before a particular release ship. + +.. _throttle unthrottle: + +**Throttle/Unthrottle a rollout** - Throttle is restricting a release rollout to 0% +of the release population, users can still choose to update but are not updated +automatically. Unthrottle is removing the release rollout restriction. + +.. _uplift: + +**Uplift** - the action of taking parts from a newer version of a +software system (mozilla-central or mozilla-beta) and porting them to an +older version of the same software (mozilla-beta, mozilla-release or ESR) diff --git a/docs/contributing/reviewer_checklist.rst b/docs/contributing/reviewer_checklist.rst new file mode 100644 index 0000000000..cfe772dba9 --- /dev/null +++ b/docs/contributing/reviewer_checklist.rst @@ -0,0 +1,181 @@ +Reviewer Checklist +================== + + Submitting patches to Mozilla source code needn't be complex. This + article provides a list of best practices for your patch content that + reviewers will check for or require. Following these best practices + will lead to a smoother, more rapid process of review and acceptance. + + +Good web citizenship +-------------------- + +- Make sure new web-exposed APIs actually make sense and are either + standards track or preffed off by default. +- In C++, wrapper-cache as needed. If your object can be gotten from + somewhere without creating it in the process, it needs to be + wrapper-cached. + + +Correctness +----------- + +- The bug being fixed is a valid bug and should be fixed. +- The patch fixes the issue. +- The patch is not unnecessarily complicated. +- The patch does not add duplicates of existing code ('almost + duplicates' could mean a refactor is needed). Commonly this results + in "part 0" of a bug, which is "tidy things up to make the fix easier + to write and review". +- If QA needs to verify the fix, you should provide steps to reproduce + (STR). + + +Quality +------- + +- If you can unit-test it, you should unit-test it. +- If it's JS, try to design and build so that xpcshell can exercise + most functionality. It's quicker. +- Make sure the patch doesn't create any unused code (e.g., remove + strings when removing a feature) +- All caught exceptions should be logged at the appropriate level, + bearing in mind personally identifiable information, but also + considering the expense of computing and recording log output. + [Fennec: Checking for log levels is expensive unless you're using + Logger.] + + +Style +----- + +- Follow the `style + guide <https://firefox-source-docs.mozilla.org/code-quality/coding-style/index.html>`__ + for the language and module in question. +- Follow local style for the surrounding code, even if that local style + isn't formally documented. +- New files have license declarations and modelines. +- New JS files should use strict mode. +- Trailing whitespace (git diff and splinter view both highlight this, + as does hg with the color extension enabled). Whitespace can be fixed + easily in Mercurial using the `CheckFiles + extension <https://www.mercurial-scm.org/wiki/CheckFilesExtension>`__. + In git, you can use git rebase --whitespace=fix. + + +Security issues +--------------- + +- There should be no writing to arbitrary files outside the profile + folder. +- Be careful when reading user input, network input, or files on disk. + Assume that inputs will be too big, too short, empty, malformed, or + malicious. +- Tag for sec review if unsure. +- If you're writing code that uses JSAPI, chances are you got it wrong. + Try hard to avoid doing that. + + +Privacy issues +-------------- + +- There should be no logging of URLs or content from which URLs may be + inferred. +- [Fennec: Android Services has Logger.pii() for this purpose (e.g., + logging profile dir)]. +- Tag for privacy review if needed. + + +Resource leaks +-------------- + +- In Java, memory leaks are largely due to singletons holding on to + caches and collections, or observers sticking around, or runnables + sitting in a queue. +- In C++, cycle-collect as needed. If JavaScript can see your object, + it probably needs to be cycle-collected. +- [Fennec: If your custom view does animations, it's better to clean up + runnables in onDetachFromWindow().] +- Ensure all file handles and other closeable resources are closed + appropriately. +- [Fennec: When writing tests that use PaintedSurface, ensure the + PaintedSurface is closed when you're done with it.] + + +Performance impact +------------------ + +- Check for main-thread IO [Fennec: Android may warn about this with + strictmode]. +- Remove debug logging that is not needed in production. + + +Threading issues +---------------- + +- Enormous: correct use of locking and volatility; livelock and + deadlock; ownership. +- [Fennec: All view methods should be touched only on UI thread.] +- [Fennec: Activity lifecycle awareness (works with "never keep + activities"). Also test with oom-fennec + (`https://hg.mozilla.org/users/blassey_mozilla.com/oom-fennec/) <https://hg.mozilla.org/users/blassey_mozilla.com/oom-fennec/%29>`__]. + + +Compatibility +------------- + +- Version files, databases, messages +- Tag messages with ids to disambiguate callers. +- IDL UUIDs are updated when the interface is updated. +- Android permissions should be 'grouped' into a common release to + avoid breaking auto-updates. +- Android APIs added since Froyo should be guarded by a version check. + + +Preffability +------------ + +- If the feature being worked on is covered by prefs, make sure they + are hooked up. +- If working on a new feature, consider adding prefs to control the + behavior. +- Consider adding prefs to disable the feature entirely in case bugs + are found later in the release cycle. +- [Fennec: "Prefs" can be Gecko prefs, SharedPreferences values, or + build-time flags. Which one you choose depends on how the feature is + implemented: a pure Java service can't easily check Gecko prefs, for + example.] + + +Strings +------- + +- There should be no string changes in patches that will be uplifted + (including string removals). +- Rev entity names for string changes. +- When making UI changes, be aware of the fact that strings will be + different lengths in different locales. + + +Documentation +------------- + +- The commit message should describe what the patch is changing (not be + a copy of the bug summary). The first line should be a short + description (since only the first line is shown in the log), and + additional description, if needed, should be present, properly + wrapped, in later lines. +- Adequately document any potentially confusing pieces of code. +- Flag a bug with dev-doc-needed if any addon or web APIs are affected. +- Use Javadocs extensively, especially on any new non-private methods. +- When moving files, ensure blame/annotate is preserved. + + +Accessibility +------------- + +- For HTML pages, images should have the alt attribute set when + appropriate. Similarly, a button that is not a native HTML button + should have role="button" and the aria-label attribute set. +- [Fennec: Make sure contentDescription is set for parts of the UI that + should be accessible] diff --git a/docs/contributing/reviews.rst b/docs/contributing/reviews.rst new file mode 100644 index 0000000000..0cb0dfb59c --- /dev/null +++ b/docs/contributing/reviews.rst @@ -0,0 +1,145 @@ +Getting reviews +=============== + + +Thorough code reviews are one of Mozilla's ways of ensuring code quality. +Every patch must be reviewed by the module owner of the code, or one of their designated peers. + +To request a review, you will need to specify a review group (starts with #). If there is not, you should select one or more usernames either when you submit the patch, or afterward in the UI. +If you have a mentor, the mentor can usually either also review or find a suitable reviewer on your behalf. + +For example, the syntax to request review from a group should be: + +.. code-block:: + + Bug xxxx - explain what you are doing and why r?#group-name + + or + + Bug xxxx - explain what you are doing and why r?developer-nickname + +Getting attention: If a reviewer doesn't respond within a week, or so of the review request: + + * Contact the reviewer directly (either via e-mail or on Matrix). + * Join developers on `Mozilla's Matrix server <https://chat.mozilla.org>`_, and ask if anyone knows why a review may be delayed. Please link to the bug too. + * If the review is still not addressed, mail the reviewer directly, asking if/when they'll have time to review the patch, or might otherwise be able to review it. + +For simple documentation changes, reviews are not required. + +For more information about the review process, see the :ref:`Code Review FAQ`. + +Review groups +------------- + + +.. list-table:: + :header-rows: 1 + + * - Name + - Owns + - Members + * - #anti-tracking + - `Core: Anti-Tracking </mots/index.html#core-anti-tracking>`__ + - `Member list <https://phabricator.services.mozilla.com/project/members/157/>`__ + * - #build or #firefox-build-system-reviewers + - The configure & build system + - `Member list <https://phabricator.services.mozilla.com/project/members/20/>`__ + * - #cookies + - `Core: Cookies </mots/index.html#core-cookies>`__ + - `Member list <https://phabricator.services.mozilla.com/project/members/177/>`__ + * - #dom-workers-and-storage-reviewers + - DOM Workers & Storage + - `Member list <https://phabricator.services.mozilla.com/project/members/115/>`__ + * - #devtools-reviewers + - Firefox DevTools + - `Member list <https://phabricator.services.mozilla.com/project/members/153/>`__ + * - #fluent-reviewers + - Changes to Fluent (FTL) files (translation). + - `Member list <https://phabricator.services.mozilla.com/project/members/105/>`__ + * - #firefox-source-docs-reviewers + - Documentation files and its build + - `Member list <https://phabricator.services.mozilla.com/project/members/118/>`__ + * - #firefox-ux-team + - User experience (UX) + - `Member list <https://phabricator.services.mozilla.com/project/members/91/>`__ + * - #firefox-svg-reviewers + - SVG-related changes + - `Member list <https://phabricator.services.mozilla.com/project/members/97/>`__ + * - #geckoview-reviewers + - Changes to GeckoView + - `Member list <https://phabricator.services.mozilla.com/project/members/92/>`__ + * - #gfx-reviewers + - Changes to Graphics code + - `Member list <https://phabricator.services.mozilla.com/project/members/122/>`__ + * - #webgpu-reviewers + - Changes to WebGPU code + - `Member list <https://phabricator.services.mozilla.com/project/members/170/>`__ + * - #intermittent-reviewers + - Test manifest changes + - `Member list <https://phabricator.services.mozilla.com/project/members/110/>`__ + * - #layout-reviewers + - Layout changes. + - `Member list <https://phabricator.services.mozilla.com/project/members/126/>`__ + * - #linter-reviewers + - tools/lint/* + - `Member list <https://phabricator.services.mozilla.com/project/members/119/>`__ + * - #mac-reviewers + - Changes to Mac-specific code + - `Member list <https://phabricator.services.mozilla.com/project/members/149/>`__ + * - #mozbase + - Changes to Mozbase + - `Member list <https://phabricator.services.mozilla.com/project/members/113/>`__ + * - #mozbase-rust + - Changes to Mozbase in Rust + - `Member list <https://phabricator.services.mozilla.com/project/members/114/>`__ + * - #necko-reviewers + - Changes to network code (aka necko, aka netwerk) + - `Member list <https://phabricator.services.mozilla.com/project/members/127/>`__ + * - #nss-reviewers + - Changes to Network Security Services (NSS) + - `Member list <https://phabricator.services.mozilla.com/project/members/156/>`__ + * - #perftest-reviewers + - Perf Tests + - `Member list <https://phabricator.services.mozilla.com/project/members/102/>`__ + * - #permissions or #permissions-reviewers + - `Permissions </mots/index.html#core-permissions>`__ + - `Member list <https://phabricator.services.mozilla.com/project/members/158/>`__ + * - #platform-i18n-reviewers + - Platform Internationalization + - `Member list <https://phabricator.services.mozilla.com/project/members/150/>`__ + * - #preferences-reviewers + - Firefox for Desktop Preferences (Options) user interface + - `Member list <https://phabricator.services.mozilla.com/project/members/132/>`__ + * - #remote-debugging-reviewers + - Remote Debugging UI & tools + - `Member list <https://phabricator.services.mozilla.com/project/members/108/>`__ + * - #spidermonkey-reviewers + - SpiderMonkey JS/Wasm Engine + - `Member list <https://phabricator.services.mozilla.com/project/members/173/>`__ + * - #static-analysis-reviewers + - Changes related to Static Analysis + - `Member list <https://phabricator.services.mozilla.com/project/members/120/>`__ + * - #style or #firefox-style-system-reviewers + - Firefox style system (servo, layout/style). + - `Member list <https://phabricator.services.mozilla.com/project/members/90/>`__ + * - #webcompat-reviewers + - System addons maintained by the Web Compatibility team + - `Member list <https://phabricator.services.mozilla.com/project/members/124/>`__ + * - #webdriver-reviewers + - Marionette and geckodriver (including MozBase Rust), and Remote Protocol with WebDriver BiDi, and CDP. + - `Member list <https://phabricator.services.mozilla.com/project/members/103/>`__ + * - #webidl + - Changes related to WebIDL + - `Member list <https://phabricator.services.mozilla.com/project/members/112/>`__ + * - #xpcom-reviewers + - Changes related to XPCOM + - `Member list <https://phabricator.services.mozilla.com/project/members/125/>`__ + * - #media-playback-reviewers + - `Media playback <https://wiki.mozilla.org/Modules/All#Media_Playback>`__ + - `Member list <https://phabricator.services.mozilla.com/project/profile/159/>`__ + * - #cubeb-reviewers + - Changes related to cubeb, Gecko's audio input/output library and associated projects (audioipc, cubeb-rs, rust cubeb backends) + - `Member list <https://phabricator.services.mozilla.com/project/profile/129/>`__ + +To create a new group, fill a `new bug in Conduit::Administration <https://bugzilla.mozilla.org/enter_bug.cgi?product=Conduit&component=Administration>`__. +See `bug 1613306 <https://bugzilla.mozilla.org/show_bug.cgi?id=1613306>`__ as example. diff --git a/docs/contributing/stack_quickref.rst b/docs/contributing/stack_quickref.rst new file mode 100644 index 0000000000..cd298fde1a --- /dev/null +++ b/docs/contributing/stack_quickref.rst @@ -0,0 +1,166 @@ +Working with stack of patches Quick Reference +============================================= + +Working on Firefox, we strongly recommend working with stack of patches. +Patches should be small and could be landed in the order used to push them. +This also helps to breakdown the work for different reviewers. + +As it can be complex for new comers, this documentation explains the +various commands. + +In Phabricator, the stack can be seen in the `Revision Contents` section. +The top of the stack (most recent change) is first in the list. + +This is also sometimes called "stack of revisions", "stack of commits" or "series of commits". + +**Example:** + +.. image:: img/example-stack.png + + +For the overall quick reference guide, see the :ref:`Firefox Contributors Quick Reference <Firefox Contributors' Quick Reference>` + +Visualize the stack +------------------- + +.. code-block:: shell + + # Mercurial + $ hg wip + + # Git + $ git log + + +Merge two patches +----------------- + +It can happen that, instead of updating a patch, a new revision is +created on Phabricator. For this, merge the patches locally: + +.. code-block:: shell + + # Mercurial + # Mark the patch to be merged with "roll" (key: "r") + # or "fold" (key: "f") + $ hg histedit + + # Git + # Replace "pick" by "squash" or "fixup" + $ git rebase -i + +Then, push to Phabricator and abandon the old change. + + +Submitting the first patch on the stack +--------------------------------------- + +There are times when you are working on multiple patches and +just want to submit the first one. For this, you can use: + +.. code-block:: shell + + $ moz-phab submit . + + +Reorder the stack +----------------- + +Sometimes, we want to change the order the patches in the stack. +Fortunately, VCS support this easily. + +.. code-block:: shell + + # Mercurial + # Just change the order the patch. The tool should highlight + # potential risks of conflicts. + # Note that ctrl+c works well if used + $ hg histedit + + # Git + # In the editor, just move the line below/above + # Remove everything if you want to cancel the operation + $ git rebase -i + + +Make a change on a patch at the beginning of the stack +------------------------------------------------------ + +In some cases, the reviewer is asking for a change at the bottom of the stack (ie not at the top). +So, a simple `hg/git commit --amend` would not work. + +In such case, the following approach can be used: + +.. code-block:: shell + + # Mercurial + # hg will try to guess in which an unambiguous prior commit + $ hg absorb + + # if this doesn't work, create a temporary commit + # and merge it using "fold" or "roll" + $ hg histedit + + # Git + $ git commit --fixup <hash of the commit> + + +Removing patches in the stack +----------------------------- + +To remove a patch in the stack: + +.. code-block:: shell + + # Mercurial + # select "drop" (letter "d") + $ hg histedit + + # Git + # Replace "pick" by "drop" + # Or simply remove the line for this commit + $ git rebase -i + + +Rebasing the stack +------------------ + +As the codebase moves fast, it can be necessary to pull changes from +mozilla-central before landing the changes. + +.. code-block:: shell + + # Mercurial + # First, see where your patches are in the stack + $ hg wip + # Then, rebase it: + # If you are a beginner, don't hesitate to add "--dry-run" + $ hg pull + $ hg rebase -b . -d central + + + # Git + $ git remote update + $ git rebase mozilla/central + + +Reorganizing the stack in Phabricator +------------------------------------- + +.. code-block:: shell + + $ moz-phab reorg [start_rev] [end_rev] + +allows you to reorganize the stack in Phabricator. + +If you've changed the local stack by adding, removing or moving the commits around, you need to change the parent/child relation of the revisions in Phabricator. + +.. code-block:: shell + + $ moz-phab reorg + +command will compare the stack, display what will be changed and ask for permission before taking any action. + +.. note:: + + Note that reviewbot will not restart the analysis. diff --git a/docs/contributing/vcs/mercurial.rst b/docs/contributing/vcs/mercurial.rst new file mode 100644 index 0000000000..f5f7cef39d --- /dev/null +++ b/docs/contributing/vcs/mercurial.rst @@ -0,0 +1,194 @@ +Mercurial Overview +================== + +Mercurial is a source-code management tool which allows users to keep track of changes to the source code locally and share their changes with others. +We use it for the development of Firefox. + +Installation +------------ + +See `Mercurial Page <https://www.mercurial-scm.org/downloads>`__ for installation. + + +Using `hg clone` +---------------- + +If you are not worried about network interruptions, then you can simply +use Mercurial to directly clone the repository you're interested in +using its URL, as given below. For example, to use the command line to +clone ``mozilla-central`` into a directory called ``firefox-source``, +you would use the following: + +.. code-block:: shell + + hg clone https://hg.mozilla.org/mozilla-central/ firefox-source + cd firefox-source + +Using Mercurial bundles +----------------------- + +If you are worried that your Internet connection is not fast or robust +enough to download such a large amount of data all in one go without +being interrupted and cannot clone using the command given above, then you are recommended to try :ref:`Mercurial bundles <Mercurial bundles>`. If interrupted, they can be resumed (continued without downloading +from the beginning) if the app you're using to download supports it. For +example, in Firefox you would right click on the download and select +`Resume` once your connection to the Internet was reestablished. + +Basic configuration +------------------- + +You should configure Mercurial before submitting patches to Mozilla. + +If you will be pulling the Firefox source code or one of the derived repositories, the easiest way to configure Mercurial is to run the vcs-setup mach command: + +.. code-block:: shell + + $ ./mach vcs-setup + +This command starts an interactive wizard that will help ensure your Mercurial is configured with the latest recommended settings. This command will not change any files on your machine without your consent. + + +Other configuration tips +------------------------ + +If you don't have the Firefox source code available, you should edit your Mercurial configuration file to look like the following: + +.. code-block:: shell + + [ui] + username = Your Real Name <user@example.com> + merge = your-merge-program (or internal:merge) + + [diff] + git = 1 + showfunc = 1 + unified = 8 + + [defaults] + commit = -v + +These settings can be added to ``$HOME/.hgrc`` (Linux/macOS) or ``$HOME\Mercurial.ini`` (Windows). + +You can configure the editor to use for commit messages using the `editor` option in the `[ui]` section or by setting the `EDITOR` environment variable. + +If you are trying to access the repository through a proxy server, see `these +instructions <http://www.selenic.com/mercurial/hgrc.5.html#http-proxy>`__ + + +Selecting a repository (tree) +----------------------------- + +There are multiple hg repositories hosted at mozilla.org to choose from. +A summary of the main trees is given below, but see +https://hg.mozilla.org/ for the full list. + +mozilla-central +--------------- + +This is the main development tree for Firefox. Most developers write +patches against mozilla-central. + +URL: https://hg.mozilla.org/mozilla-central/ + + +mozilla-beta +------------ + +The source for the current beta version of Firefox (and the next and all +previous betas). This code represents the expected next release of the +Firefox browser, and should be pretty stable. + +URL: https://hg.mozilla.org/releases/mozilla-beta/ + +mozilla-release +--------------- + +The source for the current release of Firefox (and the next and all +previous releases). + +URL: https://hg.mozilla.org/releases/mozilla-release/ + +autoland +-------- + +This is the integration tree for Firefox. Patches land in this repository first, +and then are merged by the sheriffs in mozilla-central. + +URL: https://hg.mozilla.org/integration/autoland/ + +L10n repos +---------- + +Mainly useful for localizers working on localizing Firefox. Code for all +l10n projects lives here and is organized into separate repos that (in +most cases) have the locale's two character ISO code. To get the repo +that you need look for the repo you're interested in on the following +page. + +URL: https://hg.mozilla.org/l10n-central/ + +Unified Repositories +-------------------- + +It is common for advanced users to want to interact with more than one +firefox repository. If you get to the point where having individual +copies of repositories is annoying you, then see +https://mozilla-version-control-tools.readthedocs.org/en/latest/hgmozilla/unifiedrepo.html +for instructions on doing this efficiently. + +Selecting a revision to build +----------------------------- + +Most of the time the `tip` revision of most repositories will build +without issue. If you are worried about it not, then you may want to +stick to mozilla-central. + +Building +-------- + +By default with no configuration a similar-to-release build is done. If +you wish you can :ref:`configure <Configuring Build Options>` the build using a ``.mozconfig`` file +and ``mach build``. +Different OSs have different prerequisites for a successful build, +please refer to the :ref:`build documentation <Getting Set Up To Work On The Firefox Codebase>` +to verify they are available on your build machine. + +Extensions +---------- + +There's a number of extensions you can enable. See http://mercurial.selenic.com/wiki/UsingExtensions. Almost everyone should probably enable the following, most of them are enabled by ``mach boostrap``: + +#. color - Colorize terminal output +#. histedit - Provides git rebase --interactive behavior. +#. rebase - Ability to easily rebase patches on top of other heads. +#. evolve - Enable and enhance the inprogress ChangesetEvolution work. +#. firefoxtree - Enhances the interaction with Firefox repositories. + +These can all be turned on by just adding this to your `.hgrc` file: + +.. code-block:: shell + + [extensions] + color = + rebase = + histedit = + firefoxtree = + evolve = + +In addition, there are some 3rd party extensions that are incredibly +useful for basic development: + +`mozext <https://hg.mozilla.org/hgcustom/version-control-tools/file/default/hgext/mozext>`__ + Mozilla-specific functionality to aid in developing Firefox/Gecko. + +Configuring the try repository +------------------------------ + +About :ref:`Pushing to Try <Pushing to Try>`. + +Learning to use Mercurial +------------------------- + +If you are new to Mercurial, you should start with the `official guide <https://www.mercurial-scm.org/guide>`__. + +Then, move on to the `version control tool docs <https://mozilla-version-control-tools.readthedocs.io/en/latest/hgmozilla/>`__ for Mozilla-centric Mercurial information. diff --git a/docs/contributing/vcs/mercurial_bundles.rst b/docs/contributing/vcs/mercurial_bundles.rst new file mode 100644 index 0000000000..66d6c26c72 --- /dev/null +++ b/docs/contributing/vcs/mercurial_bundles.rst @@ -0,0 +1,65 @@ +Mercurial Bundles +================= + +If you have a poor network connection that is preventing ``hg clone`` from completing, you may want to try downloading a bundle of the repository you're interested in. This is useful since a file download, unlike ``hg clone``, can be resumed if the connection is interrupted. Once you have the bundle, staying up-to-date shouldn't take much time at all, if you keep up with it regularly. + +This document explains the steps to setup the `mozilla-unified <https://hg.mozilla.org/mozilla-unified/>`__ repository using a bundle file. Be sure to replace "``mozilla-unified``" with the project you're working with as appropriate. + +Download the bundle +------------------- + +1. Open https://hg.cdn.mozilla.net/ : + +It lists up-to-date bundles for some of the repositories listed at https://hg.mozilla.net/ . +Each row corresponds to each repository, and each column corresponds to each compression format. + +2. Download the bundle file for the ``mozilla-unified`` repository: + +Click the link in the "mozilla-unified" row, the "zstd (max)" column. + +Setting up the repository +------------------------- + +Once you have downloaded the repository bundle, follow the steps below to recreate the repository locally based upon that bundle. + +1. Initialize a new repository (in a directory called ``mozilla-unified`` here): + +.. code-block:: shell + + mkdir mozilla-unified + hg init mozilla-unified + +2. Un-bundle the bundle file to that repository: + +Move the bundle file next to ``mozilla-unified`` directory, and rename it to ``bundle.hg``. + +.. code-block:: shell + + cd mozilla-unified + hg unbundle ../bundle.hg + +Get comfortable. Grab a coffee (or your favorite tasty beverage). Maybe a nap. This unbundling process is going to take quite a lot of time. + +3. Create the repository's config file ``.hg/hgrc``, and add the following lines, so that Mercurial will automatically know where to pull changes from future updates. You can open the template config file in your editor by running ``hg config --local --edit`` or ``EDITOR=<editor-of-your-choice> hg config --local --edit`` + +.. code-block:: shell + + [paths] + default = https://hg.mozilla.org/mozilla-unified/ + +4. Update the repository to get all the changes since the bundle was created (this step also doubles as a check of the bundle integrity since if its contents are not exactly the same as what's in the official repository then the ``hg pull`` will fail): + +.. code-block:: shell + + hg pull + +5. Check out a working copy from your new up to date repository: + +.. code-block:: shell + + hg update + +You now have a clone of ``mozilla-unified`` that is identical to one made via ``hg clone``. You can adjust your build settings, or you can go straight ahead and build Firefox! + +If at any point you are stuck, feel free to ask on Riot/Matrix at `https://chat.mozilla.org <https://chat.mozilla.org>`__ +in `#introduction <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`__ channel. diff --git a/docs/crash-reporting/img/default-search-results.png b/docs/crash-reporting/img/default-search-results.png new file mode 100644 index 0000000000..394f997554 Binary files /dev/null and b/docs/crash-reporting/img/default-search-results.png differ diff --git a/docs/crash-reporting/img/default-search-results2.png b/docs/crash-reporting/img/default-search-results2.png new file mode 100644 index 0000000000..03fb33d8c3 Binary files /dev/null and b/docs/crash-reporting/img/default-search-results2.png differ diff --git a/docs/crash-reporting/img/facet-search-results.png b/docs/crash-reporting/img/facet-search-results.png new file mode 100644 index 0000000000..a53db96b65 Binary files /dev/null and b/docs/crash-reporting/img/facet-search-results.png differ diff --git a/docs/crash-reporting/img/facet-search-results2.png b/docs/crash-reporting/img/facet-search-results2.png new file mode 100644 index 0000000000..7166302974 Binary files /dev/null and b/docs/crash-reporting/img/facet-search-results2.png differ diff --git a/docs/crash-reporting/img/facet-search-results3.png b/docs/crash-reporting/img/facet-search-results3.png new file mode 100644 index 0000000000..bc96d30ee9 Binary files /dev/null and b/docs/crash-reporting/img/facet-search-results3.png differ diff --git a/docs/crash-reporting/img/narrower-search-results.png b/docs/crash-reporting/img/narrower-search-results.png new file mode 100644 index 0000000000..38b410b362 Binary files /dev/null and b/docs/crash-reporting/img/narrower-search-results.png differ diff --git a/docs/crash-reporting/img/super-search-form.png b/docs/crash-reporting/img/super-search-form.png new file mode 100644 index 0000000000..63b35a23ad Binary files /dev/null and b/docs/crash-reporting/img/super-search-form.png differ diff --git a/docs/crash-reporting/img/super-search-form2.png b/docs/crash-reporting/img/super-search-form2.png new file mode 100644 index 0000000000..02dd3a541e Binary files /dev/null and b/docs/crash-reporting/img/super-search-form2.png differ diff --git a/docs/crash-reporting/img/super-search-form3.png b/docs/crash-reporting/img/super-search-form3.png new file mode 100644 index 0000000000..473706e548 Binary files /dev/null and b/docs/crash-reporting/img/super-search-form3.png differ diff --git a/docs/crash-reporting/index.rst b/docs/crash-reporting/index.rst new file mode 100644 index 0000000000..c1273c6927 --- /dev/null +++ b/docs/crash-reporting/index.rst @@ -0,0 +1,52 @@ +Crash reporting +=============== + +Firefox ships with an open-source crash reporting system. This system is +combination of projects: + +- `Google + Breakpad <https://chromium.googlesource.com/breakpad/breakpad>`__ + client and server libraries +- Mozilla-specific crash reporting user interface and bootstrap code +- `Socorro <https://github.com/mozilla-services/socorro>`__ Collection + and reporting server + + +Where did my crash get submitted? +--------------------------------- + +Crash data submitted using the Mozilla Crash Reporter is located on +`crash-stats <https://crash-stats.mozilla.org/>`__. If you want to find +a specific crash that you submitted, you first need to find the Crash ID +that the server has assigned your crash. Type ``about:crashes`` into +your location bar to get a page listing both submitted and unsubmitted +crash reports. For more information, see :ref:`How to get a stacktrace for a bug report`. + + +Reports and queries +------------------- + +crash-stats has built-in reports of "topcrashes" for each release +grouped by signature. There is also a `custom query tool <https://crash-stats.mozilla.org/search/>`__ +which allows users to limit searches on more precise information. + +Finally, a set of Mozilla employees have access to directly query the +underlying data in either SQL summary or using mapreduce on the storage +cluster. If you are interested in obtaining this advanced access, read +`Crash Stats Documentation: Protected Data Access <https://crash-stats.mozilla.org/documentation/protected_data_access/>`__ + + +See also +-------- + +- :ref:`Understanding crash reports` +- :ref:`A guide to searching crash reports` +- `crash-stats <https://crash-stats.mozilla.org/>`__ +- `Crash pings (Telemetry) and crash reports (Socorro/Crash + Stats) <https://bluesock.org/~willkg/blog/mozilla/crash_pings_crash_reports.html>`__ +- :ref:`Building with Debug Symbols` +- :ref:`Environment variables affecting crash reporting <Crash Reporter#Environment variables affecting crash reporting>` +- :ref:`Uploading symbols to Mozilla's symbol server` +- :ref:`Crash reporter` +- :ref:`Crash manager` +- :ref:`Crash ping` diff --git a/docs/crash-reporting/searching_crash_reports.rst b/docs/crash-reporting/searching_crash_reports.rst new file mode 100644 index 0000000000..0668a03654 --- /dev/null +++ b/docs/crash-reporting/searching_crash_reports.rst @@ -0,0 +1,257 @@ +A guide to searching crash reports +================================== + +.. note:: + + Please read the :ref:`documentation about individual crash + reports <Understanding crash reports>` before reading + this page. + +The Mozilla `crash-stats <https://crash-stats.mozilla.org/>`__ site +provides facilities for investigating large numbers of Firefox `crash +reports <Understanding crash reports>`__. This guide to +searching through crash reports may help you locate the crash reports +that will help you find and fix the Firefox bug you're working on. + +Specifically, crash-stats offers two basic functions: + +Searching + You can search the crash reports database by over 100 criteria: crash + signature, date, platform, product, version, etc. +Grouping + You can cluster the results of each search into groups using the same + criteria. + +To achieve full power and flexibility requires a good understanding of +both of these functions. Search is easy to understand, but the grouping +capabilities are easy to overlook. + +Searching +--------- + +The search form +~~~~~~~~~~~~~~~ + +You can get to the `search +page <https://crash-stats.mozilla.org/search/?product=Firefox&_dont_run=1>`__ +by clicking on the "Super Search" link near the toolbar at the top right +of any page in crash-stats. This brings up a search form like the one in +the following screenshot. + +|Search in crash-stats| + +Fields are provided for four common search criteria: product, version, +platform, and process type. The product field is pre-populated with +"Firefox" because that is a common case. As the fine print says, the +default date range is the past week. + +The default search: Signature facet +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you click on the "Search" button, you will get +`results <https://crash-stats.mozilla.org/search/?product=Firefox&_sort=-date&_facets=signature&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform#facet-signature>`__ +like the ones in the following screenshot. + +|Results of a default search in crash-stats| + +By default, the "Signature facet" tab is selected. ("Facet" is a term +that means "group".) In these results, the found crash reports are +grouped according to crash signature and ranked by group size. The +columns show each group's rank, signature, size (both a count and a +proportion of matching crash reports), and finally a list of bugs that +have been marked as relating to this signature. + +The numbers are large because this search matched all Firefox crash +reports from the past seven days. The first group has over 100,000 crash +reports, which accounts for 7.77% of all matching crashes. This +indicates there are over 1.3 million crash reports matching this search. + +You can reorder the groups in various ways by clicking on the column +headers. The links within the results do the following things. + +- The first link in each "Signature" column cell links to a signature + report, which contains additional details about crash reports with + that signature. +- The "Add term" link in each "Signature" column cell lets you perform + a narrower subsequent search among crash reports with that signature. +- The links in each "Bugs" column cell link to bug reports in Bugzilla. + +The default search: Crash reports +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you switch to the "Crash Reports" tab you will see +`results <https://crash-stats.mozilla.org/search/?product=Firefox&_sort=-date&_facets=signature&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform#crash-reports>`__ +like the ones in the following screenshot. + +|Results of a default search in crash-stats (crash reports tab)| + +This is a list of all the individual crash reports that match the search +criteria. If the number of matches is large -- in this case it exceeds +1.3 million, just as we saw in the "Signature facet" tab -- the results +will be spread across multiple pages, which you can visit by clicking +the links at the top right of the tab. + +The links within the results do the following things. + +- The link in each "Crash ID" column cell links to an individual crash + report. +- The links in each "Signature" column cell have the same effect that + they did in the "Signature facet" tab. +- The links in the remaining column cells also let you perform a + narrower subsequent search with that link's value added to the search + criteria. + +A narrower search +~~~~~~~~~~~~~~~~~ + +You can add criteria to perform a narrower search. For example, to +perform a search for all Mac crash reports that occurred while +JavaScript garbage collection was running, do the following. + +- Add "Mac OS X" to the "Platform" field. +- Select "New line", and then choose a field ("is garbage collecting") + and an operator ("is true"). The operators available for each field + depends on its type. + +With these criteria added the search form looks like the following +screenshot. + +|crash-stats Super Search form with additional criteria| + +After clicking on "Search" we get +`results <https://crash-stats.mozilla.org/search/?is_garbage_collecting=__true__&product=Firefox&platform=Mac%20OS%20X&_sort=-date&_facets=signature&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform>`__ +like those in the following screenshot. + +|Results of a narrower search in crash-stats| + +The number of crash reports matching this search is in the thousands, +i.e. much smaller than the previous search. + +Proto signature +~~~~~~~~~~~~~~~ + +The "proto signature" field is just the raw unprocessed crash stack +concatenated together. + +You can do things like: + +- Search for crashes where the signature is Foo, and the proto + signature contains Bar. This is helpful if you have a fairly generic + signature and you want to see how many of them are a particular case + of it that you've come across. Or instead of a signature Foo, a moz + crash reason or something else. +- Use it as a facet. This lets you skim the full signatures of crashes + at a glance, bucketed together a bit. Note that because the proto + signature includes the entire signature, things aren't grouped all + that well. + +Grouping +-------- + +In the previous section we saw one example of grouping, in the +"Signature facet" tab that is shown by default. But there are many other +interesting ways to group searches. + +Facets in the search form +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To do a search with non-signature grouping first click on the "More +options..." text, which reveals the additional fields shown in the +following screenshot. + +|crash-stats Super Search form with different facets| + +(The "Show columns" and "Sort by" fields are straightforward. They apply +to the "Crash reports" tab of any search results, and are not related to +grouping.) + +The "Facet on" field is the one that controls grouping. By default, it +contains the value "signature", which explains why we saw a "Signature +facet" tab in the earlier search results. But we can change the values +in this field and get different facet tabs in the search results. + +Grouping by platform +~~~~~~~~~~~~~~~~~~~~ + +For example, if we start with a default search for all Firefox crashes +in the past week, but then replace the "signature" facet with "platform" +and "moz crash reason", we get search results with two facet tabs. The +first of these is a "Platform facet" tab, with +`results <https://crash-stats.mozilla.org/search/?product=Firefox&_sort=-date&_facets=platform&_facets=moz_crash_reason&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform#facet-platform>`__ +like those shown in the following screenshot. + +|Results of a faceted search in crash-stats| + +This has the same columns as the "Signature facet" tab we saw earlier, +except for the "Bugs" column, because that is a special column that only +applies to the signature facet. This tab shows the distribution of crash +reports across the various platforms. Crash reports always include a +platform field (though it may be empty if something has gone wrong) and +so the percentages add up to 100. + +Grouping by "moz crash reason" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The second facet tab is a "Moz crash reason facet" tab, with +`results <https://crash-stats.mozilla.org/search/?product=Firefox&_sort=-date&_facets=platform&_facets=moz_crash_reason&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform#facet-moz_crash_reason>`__ +like those shown in the following screenshot. + +|Results of a faceted search in crash-stats (moz crash reason tab)| + +This immediately shows which ``MOZ_CRASH`` calls are being hit +frequently by users. Only a subset of crash reports have the "moz crash +reason" field -- those that crashed due to hitting a ``MOZ_CRASH`` call +-- so all crashes that lack that field are omitted from this tab. For +that reason, the percentages do not add up to 100. + +An example of less useful grouping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The usefulness of grouping varies from field to field. In particular, +fields that can have many possible values (such as numeric fields) often +don't group well. For example, if we do a default search grouped by +uptime we get +`results <https://crash-stats.mozilla.org/search/?product=Firefox&_sort=-date&_facets=uptime&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform#facet-uptime>`__ +like those in the following screenshot. + +|Results of a faceted search in crash-stats (uptime)| + +In this example the top 10 groups account for less than 12% of all +crashes, and there is an extremely long tail. These results would be +improved by using numeric ranges instead of individual values, but +unfortunately that isn't supported. + +Advanced Usage +-------------- + +The combination of searching and grouping is powerful. Searches find +crash reports that match particular criteria, and grouping organizes +those crash reports into interesting groups. + +When a search is performed, the page's URL is updated to include the +search parameters. This means that the results of any search can be +easily shared by copying and pasting the page's URL. + +To become an expert at searching and grouping requires understanding the +full range of the 100+ fields available for searching and grouping. One +way to learn about them is to read lots of individual crash reports; +note that all fields shown in the Details tab of an individual crash +report have a tool-tip that indicates its key for search. Alternatively, +you can browse the `complete +list <https://crash-stats.mozilla.org/documentation/supersearch/api/#section-filters>`__. + +There is also an API through which searches can be performed +programmatically. See the `API +documentation <https://crash-stats.mozilla.org/documentation/supersearch/>`__ +for full details; note that it uses the term "aggregation" for +grouping/faceting. + +.. |Search in crash-stats| image:: img/super-search-form.png +.. |Results of a default search in crash-stats| image:: img/default-search-results.png +.. |Results of a default search in crash-stats (crash reports tab)| image:: img/default-search-results2.png +.. |crash-stats Super Search form with additional criteria| image:: img/super-search-form2.png +.. |Results of a narrower search in crash-stats| image:: img/narrower-search-results.png +.. |crash-stats Super Search form with different facets| image:: img/super-search-form3.png +.. |Results of a faceted search in crash-stats| image:: img/facet-search-results.png +.. |Results of a faceted search in crash-stats (moz crash reason tab)| image:: img/facet-search-results2.png +.. |Results of a faceted search in crash-stats (uptime)| image:: img/facet-search-results3.png diff --git a/docs/crash-reporting/uploading_symbol.rst b/docs/crash-reporting/uploading_symbol.rst new file mode 100644 index 0000000000..1a7624ba07 --- /dev/null +++ b/docs/crash-reporting/uploading_symbol.rst @@ -0,0 +1,49 @@ +Uploading symbols to Mozilla's symbol server +============================================ + +As a third-party releasing your own builds of Firefox or B2G, you should +consider uploading debug symbols from the builds to Mozilla's symbol +server. If you have not disabled crash reporting in your builds, crash +reports will be submitted to `Mozilla's crash reporting +server <https://crash-stats.mozilla.org/>`__. Without the debug symbols +that match your build the crash reports will not contain actionable +information. + +Symbols can be uploaded either via a web browser or a web API. + + +Building a Symbol Package +------------------------- + +To upload symbols, you need to build a symbol package. This is a +.zip file which contains the symbol files in a specific directory structure. + +If you are building Firefox,or a similar application using the Mozilla +build system, you can build the symbol package using a make target: + +:: + + ./mach buildsymbols + +This will create a symbol package in ``dist/`` named something like +``firefox-77.0a1.en-US.linux-x86_64.crashreporter-symbols.zip`` . + +This step requires the ``dump_syms`` tool which should have been automatically +installed when you setup the Firefox build with ``./mach bootstrap``. If for +some reason it's missing or outdated running the bootstrap step again will +retrieve and install an up-to-date version of the tool. + +Uploading symbols +----------------- + +Symbols are uploaded via your account on symbols.mozilla.org. Visit +https://symbols.mozilla.org and log in. Then request upload +permission by filing a bug in the Socorro component using `this +template <https://bugzilla.mozilla.org/enter_bug.cgi?assigned_to=nobody%40mozilla.org&bug_ignored=0&bug_severity=--&bug_status=NEW&bug_type=task&cc=gsvelto%40mozilla.com&cc=willkg%40mozilla.com&cf_fx_iteration=---&cf_fx_points=---&comment=What%20e-mail%20account%20are%20you%20requesting%20access%20for%3F%0D%0A...%0D%0A%0D%0AWhat%20symbols%20will%20you%20be%20uploading%20using%20this%20account%3F%0D%0A...%0D%0A%0D%0AIs%20there%20somebody%20at%20Mozilla%20who%20can%20vouch%20for%20you%3F%0D%0A...%0D%0A&component=Upload&contenttypemethod=list&contenttypeselection=text%2Fplain&defined_groups=1&filed_via=standard_form&flag_type-4=X&flag_type-607=X&flag_type-800=X&flag_type-803=X&flag_type-936=X&form_name=enter_bug&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Unspecified&priority=--&product=Tecken&rep_platform=Unspecified&short_desc=Symbol-upload%20permission%20for%20%3CPerson%3E&target_milestone=---&version=unspecified>`__. +If you don't have an account yet use the template to request one. + +After symbol upload is turned on, you can upload the symbol archive +directly using the web form at https://symbols.mozilla.org/uploads. +It is also possible to upload via automated scripts: see the `symbol upload API +docs <https://tecken.readthedocs.io/en/latest/>`__ for more +details. diff --git a/docs/gtest/index.rst b/docs/gtest/index.rst new file mode 100644 index 0000000000..2e3eb2d37f --- /dev/null +++ b/docs/gtest/index.rst @@ -0,0 +1,312 @@ +GTest +===== + +GTest (googletest) is Google's framework for writing C++ tests on a +variety of platforms (Linux, Mac OS X, Windows, ...). +Based on the xUnit architecture, it supports automatic test +discovery, a rich set of assertions, user-defined assertions, death +tests, fatal and non-fatal failures, value- and type-parameterized +tests, various options for running the tests, and XML test report +generation. + +Integration +----------- + +GTest is run as a standard test task on Win/Mac/Linux and Android, under +treeherder symbol 'GTest'. + + +Running tests +------------- + +The Firefox build process will build GTest on supported platforms as +long as you don't disable tests in your mozconfig. However xul-gtest will +only be built when tests are required to save an expensive second +linking process. + +To run the unit tests use 'mach gtest' when invoking Gecko. + +Running selected tests +~~~~~~~~~~~~~~~~~~~~~~ + +Tests can be selected using mach. You can also use environment variables +support by GTest. See `Running Test Programs: Running a Subset of the +Tests <https://github.com/google/googletest/blob/master/docs/advanced.md#running-a-subset-of-the-tests>`__ +for more details. + +:: + + mach gtest Moz2D.* + + +Configuring GTest +~~~~~~~~~~~~~~~~~ + +GTest can be controlled from other environment variables. See `Running +Test Programs: Advanced +Options <https://github.com/google/googletest/blob/master/docs/advanced.md#running-test-programs-advanced-options>`__ +for more details. + + +Debugging a GTest Unit Test +--------------------------- + +To debug a gtest, pass --debug to the normal command. + +.. code-block:: shell + + ./mach gtest --debug [ Prefix.Test ] + +If that doesn't work, you can try running the firefox binary under the +debugger with the MOZ_RUN_GTEST environment variable set to 1. + +.. code-block:: shell + + MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb] + +.. warning:: + + Don't forget to build + run 'mach gtest' to relink when using + MOZ_RUN_GTEST since it's not part of a top level build. + +Note that this will load an alternate libxul - the one which has the +test code built in, which resides in a gtest/subdirectory of your +objdir. This gtest-enabled libxul is not built as part of the regular +build, so you must ensure that it is built before running the above +command. A simple way to do this is to just run "mach gtest" which will +rebuild libxul and run the tests. You can also extract the commands +needed to just rebuild that libxul `from +mach <https://hg.mozilla.org/mozilla-central/file/3673d2c688b4/python/mozbuild/mozbuild/mach_commands.py#l486>`__ +and run those directly. Finally, note that you may have to run through +the tests once for gdb to load all the relevant libraries and for +breakpoint symbols to resolve properly. + +Note that you can debug a subset of the tests (including a single test) +by using the GTEST_FILTER environment variable: + +.. code-block:: shell + + GTEST_FILTER='AsyncPanZoom*' MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb] + + +Debugging with Xcode +~~~~~~~~~~~~~~~~~~~~ + +See `Debugging on Mac OS +X </en-US/docs/Mozilla/Debugging/Debugging_on_Mac_OS_X>`__ for initial +setup. You'll likely want to create a separate scheme for running GTest +("Product" > "Scheme" > "New Scheme…"). In addition to GTEST_FILTER, Set +the following environment variables: + +:: + + MOZ_XRE_DIR=/path-to-object-directory/obj-ff-dbg/dist/bin + MOZ_RUN_GTEST=True + +and under the "Options" tab for the scheme, set the working directory +to: + +:: + + ☑️ Use custom working directory: /path-to-object-directory/obj-ff-dbg/_tests/gtest + + +Debugging with Visual Studio Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Add a configuration like this to your launch.json file (you can edit it +via Run / Open Configurations): + +:: + + { + "name": "(gdb) Launch gtest", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/dist/bin/firefox", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/_tests/gtest", + "environment": [{"name": "MOZ_RUN_GTEST", "value": "True"}, + {"name": "GTEST_FILTER", "value": "AsyncPanZoom*"}], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + + +Writing a GTest Unit Test +------------------------- + +Most of the `GTest +documentation <https://github.com/google/googletest/blob/master/googletest/README.md>`__ +will apply here. The `GTest +primer <https://github.com/google/googletest/blob/master/docs/primer.md>`__ +is a recommended read. + +.. warning:: + + GTest will run tests in parallel. Don't add unit tests that are not + threadsafe, such as tests that require focus or use specific sockets. + +.. warning:: + + GTest will run without initializing mozilla services. Initialize and + tear down any dependencies you have in your test fixtures. Avoid + writing integration tests and focus on testing individual units. + +See https://hg.mozilla.org/mozilla-central/rev/ed612eec41a44867a for an +example of how to add a simple test. + +If you're converting an existing C++ unit test to a GTest, `this +commit <https://hg.mozilla.org/mozilla-central/rev/40740cddc131>`__ may +serve as a useful reference. + + +Setting prefs for a test +~~~~~~~~~~~~~~~~~~~~~~~~ + +If tests cover functionality that is disabled by default, you'll have to +change the relevant preferences either in the individual test: + +:: + + bool oldPref = Preferences::GetBool(prefKey); + Preferences::SetBool(prefKey, true); + … // test code + Preferences::SetBool(prefKey, oldPref); + +or, if it applies more broadly, the change can be applied to the whole +fixture (see `the GTest +docs <https://github.com/google/googletest/blob/master/googletest/README.md>`__, +or +`AutoInitializeImageLib <https://searchfox.org/mozilla-central/search?q=AutoInitializeImageLib%3A%3AAutoInitializeImageLib&path=>`__ +as an example). + + +Adding a test to the build system +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Find a gtest directory appropriate for the module. If none exist create +a directory using the following convention: '<submodule>/tests/gtest'. +Create a moz.build file (in the newly created directory) with a module +declaration, replacing gfxtest with a unique name, and set +UNIFIED_SOURCES to contain all of the test file names. + +What we're doing here is creating a list of source files that will be +compiled and linked only against the gtest version of libxul. This will +let these source files call internal xul symbols without making them +part of the binary we ship to users. + +.. code-block:: + + # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- + # vim: set filetype=python: + # This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, you can obtain one at https://mozilla.org/MPL/2.0/. + + Library('gfxtest') + + UNIFIED_SOURCES = [ + <ListTestFiles>, + ] + + FINAL_LIBRARY = 'xul-gtest' + +Update '<submodule>/moz.build' in the parent directory to build your new +subdirectory in: + +.. code-block:: python + + TEST_DIRS += [ + "gtest", + ] + +When adding tests to an existing moz.build file (it has FINAL_LIBRARY = +'xul-gtest'), add the following. That's it--there is no test manifest +required. Your tests will be automatically registered using a static +constructor. + +.. code-block:: python + + UNIFIED_SOURCES = [ + 'TestFoo.cpp', + ] + +Notes +~~~~~ + +The include file for the class you are testing may not need to be +globally exported, but it does need to be made available to the unit +test you are writing. In that case, add something like this to the +Makefile.in inside of the testing directory. + +.. code-block:: python + + LOCAL_INCLUDES += [ + '/gfx/2d', + '/gfx/2d/unittest', + '/gfx/layers', + ] + +Gtests currently run from the test package under the **GTest** symbol on +`Treeherder <https://treeherder.mozilla.org/>`__ if you want to verify +that your test is working. Formerly they were run under the **B** +symbol, during \`make check`. + + +MozGTestBench +------------- + +A Mozilla GTest Microbench is just a GTest that reports the test +duration to perfherder. It's an easy way to add low level performance +test. Keep in mind that there's a non-zero cost to monitoring +performance test so use them sparingly. You can still perform test +assertions. + + +Writing a Microbench GTest +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use 'MOZ_GTEST_BENCH' instead of 'TEST' to time the execution of your +test. Example: + +.. code-block:: cpp + + #include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH + + ... + + MOZ_GTEST_BENCH(GfxBench, TEST_NAME, []{ + // Test to time the execution + }); + +Make sure this file is registered with the file system using the +instructions above. If everything worked correctly you should see this +in the GTest log for your corresponding test: + +.. code-block:: js + + PERFHERDER_DATA: {"framework": {"name": "platform_microbench"}, "suites": [{"name": "GfxBench", "subtests": [{"name": "CompositorSimpleTree", "value": 252674, "lowerIsBetter": true}]}]} + + +Sheriffing policy +~~~~~~~~~~~~~~~~~ + +Microbench tests measure the speed of a very specific operation. A +regression in a micro-benchmark may not lead to a user visible +regression and should not be treated as strictly as a Talos regression. +Large changes in microbench scores will also be expected when the code +is directly modified and should be accepted if the developer intended to +change that code. Micro-benchmarks however provide a framework for +adding performance tests for platform code and regression tests for +performance fixes. They will catch unintended regressions in code and +when correlated with a Talos regression might indicate the source of the +regression. diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000000..3a4afdb408 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,71 @@ +================================= +Firefox Source Tree Documentation +================================= + +.. toctree:: + :caption: Getting Started + :maxdepth: 1 + + {setup_doc} + +.. toctree:: + :caption: Working On Firefox + :maxdepth: 2 + + {contributing_doc} + +.. toctree:: + :caption: Firefox User Guide + :maxdepth: 2 + + {user_guide} + +.. toctree:: + :caption: Source Code Documentation + :maxdepth: 2 + + {source_doc} + +.. toctree:: + :caption: The Firefox Build System + :maxdepth: 1 + + {build_doc} + +.. toctree:: + :caption: Testing & Test Infrastructure + :maxdepth: 1 + + {testing_doc} + +.. toctree:: + :caption: Releases & Updates + :maxdepth: 1 + + {release_doc} + +.. toctree:: + :caption: Localization & Internationalization + :maxdepth: 2 + + {l10n_doc} + +.. toctree:: + :caption: Firefox and Python + :maxdepth: 1 + + {python_doc} + +.. toctree:: + :caption: Metrics Collected in Firefox + :maxdepth: 1 + + {metrics_doc} + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/jsdoc.json b/docs/jsdoc.json new file mode 100644 index 0000000000..b4cfae277c --- /dev/null +++ b/docs/jsdoc.json @@ -0,0 +1,5 @@ +{ + "source": { + "includePattern": ".+\\.m?jsm?$" + } +} diff --git a/docs/metrics/index.md b/docs/metrics/index.md new file mode 100644 index 0000000000..50e9c897ab --- /dev/null +++ b/docs/metrics/index.md @@ -0,0 +1,6 @@ +# Metrics + +The metrics collected by Firefox using the +[Glean SDK](https://mozilla.github.io/glean/book/index.html) +are documented in +[The Glean Dictionary](https://dictionary.telemetry.mozilla.org/apps/firefox_desktop/). diff --git a/docs/nspr/about_nspr.rst b/docs/nspr/about_nspr.rst new file mode 100644 index 0000000000..622bdeac52 --- /dev/null +++ b/docs/nspr/about_nspr.rst @@ -0,0 +1,154 @@ +About NSPR +========== + +NetScape Portable Runtime (NSPR) provides platform independence for +non-GUI operating system facilities. These facilities include threads, +thread synchronization, normal file and network I/O, interval timing and +calendar time, basic memory management (malloc and free) and shared +library linking. + +History +~~~~~~~ + +A good portion of the library's purpose, and perhaps the primary purpose +in the Gromit environment, was to provide the underpinnings of the Java +VM, more or less mapping the *sys layer* that Sun defined for the +porting of the Java VM to various platforms. NSPR went beyond that +requirement in some areas and since it was also the platform independent +layer for most of the servers produced by Netscape. It was expected and +preferred that existing code be restructured and perhaps even rewritten +in order to use the NSPR API. It is not a goal to provide a platform for +the porting into Netscape of externally developed code. + +At the time of writing the current generation of NSPR was known as +NSPR20. The first generation of NSPR was originally conceived just to +satisfy the requirements of porting Java to various host environments. +NSPR20, an effort started in 1996, built on that original idea, though +very little is left of the original code. (The "20" in "NSPR20" does not +mean "version 2.0" but rather "second generation".) Many of the concepts +have been reformed, expanded, and matured. Today NSPR may still be +appropriate as the platform dependent layer under Java, but its primary +application is supporting clients written entirely in C or C++. + +.. _How_It_Works: + +How It Works +~~~~~~~~~~~~ + +NSPR's goal is to provide uniform service over a wide range of operating +system environments. It strives to not export the *lowest common +denominator*, but to exploit the best features of each operating system +on which it runs, and still provide a uniform service across a wide +range of host offerings. + +Threads +^^^^^^^ + +Threads are the major feature of NSPR. The industry's offering of +threads is quite sundry. NSPR, while far from perfect, does provide a +single API to which clients may program and expect reasonably consistent +behavior. The operating systems provide everything from no concept of +threading at all up to and including sophisticated, scalable and +efficient implementations. NSPR makes as much use of what the systems +offer as it can. It is a goal of NSPR that NSPR impose as little +overhead as possible in accessing those appropriate system features. + +.. _Thread_synchronization: + +Thread synchronization +^^^^^^^^^^^^^^^^^^^^^^ + +Thread synchronization is loosely based on Monitors as described by +C.A.R. Hoare in *Monitors: An operating system structuring concept* , +Communications of the ACM, 17(10), October 1974 and then formalized by +Xerox' Mesa programming language ("Mesa Language Manual", J.G. Mitchell +et al, Xerox PARC, CSL-79-3 (Apr 1979)). This mechanism provides the +basic mutual exclusion (mutex) and thread notification facilities +(condition variables) implemented by NSPR. Additionally, NSPR provides +synchronization methods more suited for use by Java. The Java-like +facilities include monitor *reentrancy*, implicit and tightly bound +notification capabilities with the ability to associate the +synchronization objects dynamically. + +.. _I.2FO: + +I/O +^^^ + +NSPR's I/O is a slightly augmented BSD sockets model that allows +arbitrary layering. It was originally intended to export synchronous I/O +methods only, relying on threads to provide the concurrency needed for +complex applications. That method of operation is preferred though it is +possible to configure the network I/O channels as *non-blocking* in the +traditional sense. + +.. _Network_addresses: + +Network addresses +^^^^^^^^^^^^^^^^^ + +Part of NSPR deals with manipulation of network addresses. NSPR defines +a network address object that is Internet Protocol (IP) centric. While +the object is not declared as opaque, the API provides methods that +allow and encourage clients to treat the addresses as polymorphic items. +The goal in this area is to provide a migration path between IPv4 and +IPv6. To that end it is possible to perform translations of ASCII +strings (DNS names) into NSPR's network address structures, with no +regard to whether the addressing technology is IPv4 or IPv6. + +Time +^^^^ + +Timing facilities are available in two forms: interval timing and +calendar functions. + +Interval timers are based on a free running, 32-bit, platform dependent +resolution timer. Such timers are normally used to specify timeouts on +I/O, waiting on condition variables and other rudimentary thread +scheduling. Since these timers have finite namespace and are free +running, they can wrap at any time. NSPR does not provide an *epoch* , +but expects clients to deal with that issue. The *granularity* of the +timers is guaranteed to be between 10 microseconds and 1 millisecond. +This allows a minimal timer *period* in of approximately 12 hours. But +in order to deal with the wrap-around issue, only half that namespace +may be utilized. Therefore, the minimal usable interval available from +the timers is slightly less than six hours. + +Calendar times are 64-bit signed numbers with units of microseconds. The +*epoch* for calendar times is midnight, January 1, 1970, Greenwich Mean +Time. Negative times extend to times before 1970, and positive numbers +forward. Use of 64 bits allows a representation of times approximately +in the range of -30000 to the year 30000. There is a structural +representation (*i.e., exploded* view), routines to acquire the current +time from the host system, and convert them to and from the 64-bit and +structural representation. Additionally there are routines to convert to +and from most well-known forms of ASCII into the 64-bit NSPR +representation. + +.. _Memory_management: + +Memory management +^^^^^^^^^^^^^^^^^ + +NSPR provides API to perform the basic malloc, calloc, realloc and free +functions. Depending on the platform, the functions may be implemented +almost entirely in the NSPR runtime or simply shims that call +immediately into the host operating system's offerings. + +Linking +^^^^^^^ + +Support for linking (shared library loading and unloading) is part of +NSPR's feature set. In most cases this is simply a smoothing over of the +facilities offered by the various platform providers. + +Where It's Headed +~~~~~~~~~~~~~~~~~ + +NSPR is applicable as a platform on which to write threaded applications +that need to be ported to multiple platforms. + +NSPR is functionally complete and has entered a mode of sustaining +engineering. As operating system vendors issue new releases of their +operating systems, NSPR will be moved forward to these new releases by +interested players. diff --git a/docs/nspr/creating_a_cookie_log.rst b/docs/nspr/creating_a_cookie_log.rst new file mode 100644 index 0000000000..06a0e90596 --- /dev/null +++ b/docs/nspr/creating_a_cookie_log.rst @@ -0,0 +1,65 @@ +Creating a cookie log +===================== + +Creating a cookie log is often necessary to troubleshoot problems with +Firefox's cookie handling. If you are reading this, you have probably +been directed here from a bug report. Please follow the instructions +below to run Firefox with cookie logging enabled. + +.. _Enabling_Cookie_Logging: + +Enabling Cookie Logging +~~~~~~~~~~~~~~~~~~~~~~~ + +Windows +^^^^^^^ + +Open a command prompt (this is under Programs or Programs/Accessories in +normal installations of Windows). + +#. Change to your Firefox directory (usually C:\Program Files\Mozilla + Firefox) +#. Type "set NSPR_LOG_FILE=C:\temp\cookie-log.txt", enter +#. Type "set NSPR_LOG_MODULES=cookie:4" and press Enter +#. Run Firefox by typing "firefox.exe" and pressing Enter. + +Linux +^^^^^ + +Start a command shell (these instructions are for bash, if you use +something else, you probably know how to modify these instructions +already). + +#. Change to the installation directory for Firefox. +#. Type "export NSPR_LOG_FILE=~/cookie-log.txt" and press Enter. +#. Type "export NSPR_LOG_MODULES=cookie:4" and press Enter. +#. Run Firefox by typing "./firefox" and pressing Enter + +Mac OS X +^^^^^^^^ + +Open Terminal.app, which is located in the /Applications/Utilities +folder (these instructions are for bash, the default shell in Mac OS X +10.3 and higher; if you use something else, you probably know how to +modify these instructions already). + +#. Change to the installation directory for Firefox, e.g. type "cd + /Applications/Firefox.app/Contents/MacOS" and press Return. +#. Type "export NSPR_LOG_FILE=~/Desktop/cookie-log.txt" and press + Return. +#. Type "export NSPR_LOG_MODULES=cookie:4" and press Return. +#. Run Firefox by typing "./firefox-bin" and pressing Return (note that + Firefox will launch behind windows for other applications). + +Creating the Log +~~~~~~~~~~~~~~~~ + +Now that you have Firefox running with logging enabled, please try to +replicate the bug using the steps to reproduce from the bug report. Once +you have reproduced the bug, shut down Firefox. Close out of the command +prompt/shell/Terminal, and then launch Firefox normally. Finally, attach +the cookie-log.txt file to the bug where it was requested (by clicking +on Create New Attachment). It should be in C:\temp on Windows, your home +directory on Linux, or the Desktop on Mac OS X. + +Thanks for helping us make Firefox better! diff --git a/docs/nspr/index.rst b/docs/nspr/index.rst new file mode 100644 index 0000000000..89e81d2517 --- /dev/null +++ b/docs/nspr/index.rst @@ -0,0 +1,66 @@ +NSPR +==== + +**Netscape Portable Runtime (NSPR)** provides a platform-neutral API for +system level and libc-like functions. The API is used in the Mozilla +clients, many of Red Hat's and Oracle's server applications, and other +software offerings. + +Documentation +------------- + +:ref:`About NSPR` + This topic describes, in general terms, the goals of NSPR and a bit + about how it does it. +:ref:`NSPR API Reference` + The reference describes each API public macro, structure and function + in the NSPR API. +:ref:`NSPR build instructions` + How to checkout and build from source. +:ref:`NSPR listing` + All NSPR pages + +.. _Getting_NSPR: + +Getting NSPR +------------ + +NSPR is available in various source and binary packages, depending on +your platform: + +- **Windows:** Build the source package, using the :ref:`NSPR build + instructions`. +- **Mac:** Install the `MacPorts <http://www.macports.org/>`__ *nspr* + package, or the `Homebrew <http://brew.sh>`__ *nspr* package. +- **Ubuntu:** Install the *libnspr4-dev* package via ``apt-get.`` +- **Debian:** Install the *libnspr4-dev* package via ``apt-get``. +- **openSUSE Linux:** Install one or more of the following via ``yast`` + or ``zypper`` : + + - *mozilla-nspr* : Binary libraries for your platform + - *mozilla-nspr-32bit* : Binary libraries needed to run 32-bit + programs on a 64-bit OS + - *mozilla-nspr-devel* : Files needed (in addition to the above + libraries) to compile programs using NSPR + - *mozilla-nspr-debuginfo* : Debug information (including build + symbols) for package *mozilla-nspr* + - *mozilla-nspr-debuginfo-32bit* : Debug information (including + build symbols) for package *mozilla-nspr-32bit* + - *mozilla-nspr-debugsource* : Debug sources for all of the above + +Community +--------- + +View Mozilla forums: + +- `Mailing list <https://lists.mozilla.org/listinfo/dev-tech-nspr>`__ +- `Newsgroup <http://groups.google.com/group/mozilla.dev.tech.nspr>`__ +- `RSS + feed <http://groups.google.com/group/mozilla.dev.tech.nspr/feeds>`__ + +.. _Related_Topics: + +Related Topics +-------------- + +- :ref:`Networking`, :ref:`Network Security Services (NSS)` diff --git a/docs/nspr/layeredpoll.rst b/docs/nspr/layeredpoll.rst new file mode 100644 index 0000000000..6f5cb80efe --- /dev/null +++ b/docs/nspr/layeredpoll.rst @@ -0,0 +1,118 @@ +PR_Poll() and the layered I/O +============================= + +*[last edited by AOF 8 August 1998]* +This memo discusses some of the nuances of using PR_Poll() in +conjunction with *layered I/O*. This is a relatively new feature in NSPR +2.0, not that it hasn't been in the source tree for a while, but in that +it has had no clients. + +Implementation +-------------- + +NSPR provides a public API function, PR_Poll() that is modeled after +UNIX' ``poll()`` system call. + +The implementation of :ref:`PR_Poll` is somewhat complicated. Not only +does it map the :ref:`PRPollDesc` array into structures needed by the +underlying OS, it also must deal with layered I/O. This is done despite +the fact that :ref:`PR_Poll` itself is *not* layered. For every element +of the :ref:`PRPollDesc` array that has a non-NULL :ref:`PRFileDesc` and whose +``in_flags`` are not zero, it calls the file descriptor's +``poll() method``. +The ``poll()`` method is one of the vector contained in the +:ref:`PRIOMethods` table. In the case of layered I/O, the elements (the +methods) of the methods table may be overridden by the implementor of +that layer. The layers are then *stacked.* I/O using that *stack* will +call through the method at the top layer, and each layer may make +altering decisions regarding how the I/O operation should proceed. + +The purpose of the ``poll()`` method is to allow a layer to modify the +flags that will ultimately be used in the call to the underlying OS' +``poll()`` (or equivalent) function. Such modification might be useful +if one was implementing an augmented stream protocol (*e.g.,* **SSL**). +SSL stands for **Secure Socket Layer**, hence the obvious applicability +as an example. But it is way to complicated to describe in this memo, so +this memo will use a much simpler layered protocol. +The example protocol is one that, in order to send *n* bytes, it must +first ask the connection's peer if the peer is willing to receive that +many bytes. The form of the request is 4 bytes (binary) stating the +number of bytes the sender wishes to transmit. The peer will send back +the number of bytes it is willing to receive (in the test code there are +no error conditions, so don't even ask). + +The implication of the protocol is obvious. In order to do a +:ref:`PR_Send` operation, the layer must first do a *different* send and +then *receive* a response. Doing this and keeping the *stack's* client +unaware is the goal. **It is not a goal of NSPR 2.0 to hide the nuances +of synchronous verses non-blocking I/O**. + +The layered methods +------------------- + +Each layer must implement a suitable function for *every* element of the +methods table. One can get a copy of default methods by calling +:ref:`PR_GetDefaultIOMethods` These methods simply pass all calls +through the layer on to the next lower layer of the stack. + +A layer implementor might copy the elements of the ``PRIOMethods`` +acquired from this function into a methods table of its own, then +override just those methods of interest. *Usually* (with only a single +exception) a layered method will perform its design duties and then call +the next lower layer's equivalent function. + +Layered ``poll()`` +------------------ + +One of the more interesting methods is the ``poll()``. It is called by +the runtime whenever the client calls :ref:`PR_Poll`. It may be called at +the *top* layer for *every* file descriptor in the poll descriptor. It +may be called zero or more times. The purpose of the ``poll()`` method +is to provide the layer an opportunity to adjust the polling bits as +needed. For instance, if a client (*i.e.*, top layer) is calling +:ref:`PR_Poll` for a particular file descriptor with a *read* poll +request, a lower layer might decide that it must perform a *write* +first. +In that case, the layer's ``poll()`` method would be called with +**``in_flags``** including a ``PR_POLL_READ`` flag. However, the +``poll()`` method would call the next lower layer's ``poll()`` method +with a ``PR_POLL_WRITE`` bit set. This process of re-assigning the poll +flags can happen as many times as there are layers in the stack. It is +the final value, the one returned to the caller of the top layer's +``poll()`` method (:ref:`PR_Poll`) that will be used by the runtime when +calling the OS' ``poll()`` (or equivalent) system call. + +It is expected that the modification of the polling bits propagate from +the top of the stack down, allowing the layer closest to the bottom of +the stack to provide the final setting. The implication is that there +should be no modifications of the **``in_flags``** during the *return* +phase of the layered function. + +For example: + +It is not advised to modify the ``final_in_flags`` between the call to +the lower layer's ``poll()`` method and the ``return`` statement. +The third argument of the ``poll()`` method is a pointer to a 16-bit +word. If the layer sets a value in memory through that pointer *and* +returns with a value that has *corresponding* bits, the runtime assumes +that the file descriptor is ready immediately. + +There are two important deviations from the normal. First, this is the +one (known) exception to having a layered routine call the stack's next +lower layer method. If bits are set in the ``out_flags`` the method +should return *directly*. Second, the runtime will observe that the +layer claims this file descriptor is ready and suppress the call to the +OS' ``poll()`` system call. + +At this time the only known use for this feature is to allow a layer to +indicate it has buffered *input*. Note that it is not appropriate for +buffered *output* since in order to write/send output the runtime must +still confirm with the OS that such an operation is permitted. + +Since the ``poll()`` method may be called zero or more times it must +therefore be *idempotent* or at least *functional*. It will need to look +at the layer's state, but must not make modifications to that state that +would cause subsequent calls within the same :ref:`PR_Poll` call to +return a different answer. Since the ``poll()`` method may not be called +at all, so there is not guarantee that any modifications that would have +been performed by the routine will every happen. diff --git a/docs/nspr/listing.rst b/docs/nspr/listing.rst new file mode 100644 index 0000000000..33d0359e01 --- /dev/null +++ b/docs/nspr/listing.rst @@ -0,0 +1,10 @@ +NSPR listing +============ + +This page lists all the NSPR page. + +.. toctree:: + :glob: + + * + reference/* diff --git a/docs/nspr/nonblocking_io_in_nspr.rst b/docs/nspr/nonblocking_io_in_nspr.rst new file mode 100644 index 0000000000..a5ba816412 --- /dev/null +++ b/docs/nspr/nonblocking_io_in_nspr.rst @@ -0,0 +1,153 @@ +Nonblocking IO in NSPR +====================== + + +Introduction +------------ + +Previously, all I/O in the NetScape Portable Runtime (NSPR) was +*blocking* (or *synchronous*). A thread invoking an io function is +blocked until the io operation is finished. The blocking io model +encourages the use of multiple threads as a programming model. A thread +is typically created to attend to one of the simultaneous I/O operations +that may potentially block. + +In the *nonblocking* io model, a file descriptor may be marked as +nonblocking. An io function on a nonblocking file descriptor either +succeeds immediately or fails immediately with +<tt>PR_WOULD_BLOCK_ERROR</tt>. A single thread is sufficient to attend +to multiple nonblocking file descriptors simultaneously. Typically, this +central thread invokes <tt>PR_Poll()</tt> on a set of nonblocking file +descriptors. (Note: <tt>PR_Poll()</tt> also works with blocking file +descriptors, although it is less useful in the blocking io model.) When +<tt>PR_Poll()</tt> reports that a file descriptor is ready for some io +operation, the central thread invokes that io function on the file +descriptor. + +.. _Creating_a_Nonblocking_Socket: + +Creating a Nonblocking Socket +----------------------------- + +*Only sockets can be made nonblocking*. Regular files always operate in +blocking mode. This is not a serious constraint as one can assume that +disk I/O never blocks. Fundamentally, this constraint is due to the fact +that nonblocking I/O and <tt>select()</tt> are only available to sockets +on some platforms (e.g., Winsock). + +In NSPR, a new socket returned by <tt>PR_NewTCPSocket()</tt> or +<tt>PR_NewUDPSocket()</tt> is always created in blocking mode. One can +make the new socket nonblocking by using <tt>PR_SetSockOpt()</tt> as in +the example below (error checking is omitted for clarity): + +| +| <tt>PRFileDesc \*sock;</tt> +| **<tt>PRIntn optval = 1;</tt>** + +<tt>sock = PR_NewTCPSocket();</tt> + +:: + + /* + * Make the socket nonblocking + */ + + PR_SetSockOpt(sock, PR_SockOpt_Nonblocking, &optval, sizeof(optval)); + +.. _Programming_Constraints: + +Programming Constraints +----------------------- + +There are some constraints due to the use of NT asynchronous I/O in the +NSPR. In NSPR, blocking sockets on NT are associated with an I/O +completion port. Once associated with an I/O completion port, we can't +disassociate the socket from the I/O completion port. I have seen some +strange problems with using a nonblocking socket associated with an I/O +completion port. So the first constraint is: + + **The blocking/nonblocking io mode of a new socket is committed the + first time a potentially-blocking io function is invoked on the + socket. Once the io mode of a socket is committed, it cannot be + changed.** + +The potentially-blocking io functions include <tt>PR_Connect()</tt>, +<tt>PR_Accept()</tt>, <tt>PR_AcceptRead()</tt>, <tt>PR_Read()</tt>, +<tt>PR_Write()</tt>, <tt>PR_Writev()</tt>, <tt>PR_Recv()</tt>, +<tt>PR_Send()</tt>, <tt>PR_RecvFrom()</tt>, <tt>PR_SendTo()</tt>, and +<tt>PR_TransmitFile(),</tt> and do not include <tt>PR_Bind()</tt> and +<tt>PR_Listen()</tt>. + +In blocking mode, any of these potentially-blocking functions requires +the use of the NT I/O completion port. So at that point we must +determine whether to associate the socket with the I/O completion or +not, and that decision cannot be changed later. + +There is a second constraint, due to the use of NT asynchronous I/O and +the recycling of used sockets: + + **The new socket returned by <tt>PR_Accept()</tt> or + <tt>PR_AcceptRead()</tt> inherits the blocking/nonblocking io mode of + the listening socket and this cannot be changed.** + +The socket returned by <tt>PR_Accept()</tt> or <tt>PR_AcceptRead()</tt> +on a blocking, listening socket may be a recycled socket previously used +in a <tt>PR_TransmitFile()</tt> call. Since <tt>PR_TransmitFile()</tt> +only operates in blocking mode, this recycled socket can only be reused +in blocking mode, hence the above constraint. + +Because these constraints only apply to NT, it is advised that you test +your cross-platform code that uses nonblocking io on NT early in the +development cycle. These constraints are enforced in the debug NSPR +library by assertions. + +.. _Differences_from_Blocking_IO: + +Differences from Blocking IO +---------------------------- + +- In nonblocking mode, the timeout argument for the io functions is + ignored. +- <tt>PR_AcceptRead()</tt> and <tt>PR_TransmitFile()</tt> only work on + blocking sockets. They do not make sense in nonblocking mode. +- <tt>PR_Write()</tt>, <tt>PR_Send()</tt>, <tt>PR_Writev()</tt> in + blocking mode block until the entire buffer is sent. In nonblocking + mode, they cannot block, so they may return with just sending part of + the buffer. + +.. _PR_Poll()_or_PR_Select(): + +PR_Poll() or PR_Select()? +------------------------- + +<tt>PR_Select()</tt> is deprecated, now declared in +<tt>private/pprio.h</tt>. Use <tt>PR_Poll()</tt> instead. + +The current implementation of <tt>PR_Select()</tt> simply calls +<tt>PR_Poll()</tt>, so it is sure to have worse performance. Also, +native file descriptors (socket handles) cannot be added to +<tt>PR_fd_set</tt>, i.e., the functions <tt>PR_FD_NSET</tt>, +<tt>PR_FD_NCLR</tt>, <tt>PR_FD_NISSET</tt> do not work. + +PR_Available() +-------------- + +When <tt>PR_Available()</tt> returns 0, it may mean one of two things: + +- There is no data available for reading on that socket. I.e., + <tt>PR_Recv()</tt> would block (a blocking socket) or fail with + <tt>PR_WOULD_BLOCK_ERROR</tt> (a nonblocking socket). +- The TCP connection on that socket has been closed (end of stream). + +These two cases can be distinguished by <tt>PR_Poll()</tt>. If +<tt>PR_Poll()</tt> reports that the socket is readable (i.e., +<tt>PR_POLL_READ</tt> is set in <tt>out_flags</tt>), and +<tt>PR_Available()</tt> returns 0, this means that the socket connection +is closed. + +.. _Current_Status: + +Current Status +-------------- + +Implemented across all supported platforms. diff --git a/docs/nspr/nonblockinglayeredio.rst b/docs/nspr/nonblockinglayeredio.rst new file mode 100644 index 0000000000..19de77a888 --- /dev/null +++ b/docs/nspr/nonblockinglayeredio.rst @@ -0,0 +1,94 @@ +Non-blocking layered I/O +======================== + +*[last edited by AOF 24 March 1998 14:15]* +I've recently been working on a long standing issue regarding NSPR's I/O +model. For a long time I've believed that the non-blocking I/O prevalent +in classic operating systems (e.g., UNIX) was the major determent for +having an reasonable layered protocols. Now that I have some first hand +experience, albeit just a silly little test program, I am more convinced +that ever of this truth. + +This memo is some of what I think must be done in NSPR's I/O subsystem +to make layered, non-blocking protocols workable. It is just a proposal. +There is an API change. + +Layered I/O +----------- + +NSPR 2.0 defines a structure by which one may define I/O layers. Each +layer looks basically like any other in that it still uses a +:ref:`PRFileDesc` as a object identifier, complete with the +**``IOMethods``** table of functions. However, each layer may override +default behavior of a particular operation to implement other services. +For instance, the experiment at hand is one that implements a little +reliable echo protocol; the client sends *n* bytes, and the same bytes +get echoed back by the server. In the non-layered design of this it is +straight forward. +The goal of the experiment was to put a layer between the client and +the network, and not have the client know about it. This additional +layer is one that, before sending the client's data, must ask permission +from the peer layer to send that many bytes. It imposes an additional +send and response inside of each client visible send operation. The +receive operations parallel the sends. Before actually receiving real +client data, the layer receives a notification that the other would like +to send some bytes. The layer is responsible for granting permission for +that data to be sent, then actually receiving the data itself, which is +delivered to the client. + +The synchronous form of the layer's operation is straight forward. A +call to receive (:ref:`PR_Recv`) first receives the request to send, +sends (:ref:`PR_Send`) the grant, then receives the actual data +(:ref:`PR_Recv`). All the client of the layer sees is the data coming +in. Similar behavior is observed on the sending side. + +Non-blocking layered +-------------------- + +The non-blocking method is not so simple. Any of the I/O operations +potentially result in an indication that no progress can be made. The +intermediate layers cannot act directly on this information, but must +store the state of the I/O operation until it can be resumed. The method +for determining that a I/O operation can make progress is to call +:ref:`PR_Poll` and indicating what type of progress is desired, +either input or output (or some others). Therein lies the problem. +The intermediate layer is performing operations that the client is +unaware. So when the client calls send (:ref:`PR_Send`) and is told +that the operation would block, it is possible that the layer below is +actually doing a receive (:ref:`PR_Recv`). The problem is that the +flag bits passed to :ref:`PR_Poll` are only reflective of the +client's knowledge and desires. This is further complicated by the fact +that :ref:`PR_Poll` is not layered. That is each layer does not have +the opportunity to override the behavior. It operates, not on a single +file descriptor (:ref:`PRFileDesc`), but on an arbitrary collection of +file descriptors. + +Into the picture comes another I/O method, **``poll()``**. Keep in mind +that all I/O methods are those that are part of the I/O methods table +structure (:ref:`PRIOMethods`). These functions are layered, and layers +may and sometimes must override their behavior by offering unique +implementations. The **``poll()``** method is used to provide two +modifying aspects to the semantics of :ref:`PR_Poll`: redefining the +polling bits (i.e., what to poll for) and to indicate that a layer is +already able to make progress in the manner suggested by the polling +bits. + +The **``poll()``** method is called by :ref:`PR_Poll` as the latter +is building the structure to provide the operating system call. The +stack's top layer will be called first. Each layer's implementation is +responsible for performing appropriate operations and possibly calling +the next lower layer's **``poll()``** method. +What the poll method is returning are the appropriate flags to assign to +the operating system's call. A layer would compute these based on the +values of the argument **``in_flags``** and possibly some state +maintained by the layer for the particular file descriptor. + +Additionally, if the layer has buffered data that will allow the +operation defined by **``in_flags``** to make progress, it will set +corresponding bits in **``out_flags``**. For instance, if +**``in_flags``** indicates that the client (or higher layer) wishes to +test for read ready and the layer has input data buffered, it would set +the read bits in the **``out_flags``**. If that is the case, then it +should also suppress the calling of the next lower layer's +**``poll()``** method and return a value equal to that of +**``in_flags``**. diff --git a/docs/nspr/nspr_build_instructions.rst b/docs/nspr/nspr_build_instructions.rst new file mode 100644 index 0000000000..d927a6bd05 --- /dev/null +++ b/docs/nspr/nspr_build_instructions.rst @@ -0,0 +1,136 @@ +NSPR build instructions +======================= + +Prerequisites +~~~~~~~~~~~~~ + +On Windows, the NSPR build system needs GNU make and a Unix command-line +utility suite such as MKS Toolkit, Cygwin, and MSYS. The easiest way to +get these tools is to install the +:ref:`MozillaBuild` package. + +Introduction +~~~~~~~~~~~~ + +The top level of the NSPR source tree is the ``mozilla/nsprpub`` +directory. Although ``nsprpub`` is a subdirectory under ``mozilla``, +NSPR is independent of the Mozilla client source tree. + +Building NSPR consists of three steps: + +#. run the configure script. You may override the compilers (the CC + environment variable) or specify options. +#. build the libraries +#. build the test programs + +For example, + +:: + + # check out the source tree from Mercurial + hg clone https://hg.mozilla.org/projects/nspr + # create a build directory + mkdir target.debug + cd target.debug + # run the configure script + ../nspr/configure [optional configure options] + # build the libraries + gmake + # build the test programs + cd pr/tests + gmake + +On Mac OS X, use ``make``, which is GNU ``make``. + +.. _Configure_options: + +Configure options +~~~~~~~~~~~~~~~~~ + +Although NSPR uses autoconf, its configure script has two default values +that are different from most open source projects. + +#. If the OS vendor provides a compiler (for example, Sun and HP), NSPR + uses that compiler instead of GCC by default. +#. NSPR build generates a debug build by default. + +.. _--disable-debug_--enable-optimize: + +--disable-debug --enable-optimize +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Specify these two options to generate an optimized (release) build. + +These two options can actually be used independently, but it's not +recommended. + +--enable-64bit +^^^^^^^^^^^^^^ + +On a dual 32-bit/64-bit platform, NSPR build generates a 32-bit build by +default. To generate a 64-bit build, specify the ``--enable-64bit`` +configure option. + +.. _--targetx86_64-pc-mingw32: + +--target=x86_64-pc-mingw32 +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For 64-bit builds on Windows, when using the mozbuild environment. + +.. _--enable-win32-target.3DWIN95: + +--enable-win32-target=WIN95 +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This option is only used on Windows. NSPR build generates a "WINNT" +configuration by default on Windows for historical reasons. We recommend +most applications use the "WIN95" configuration. The "WIN95" +configuration supports all versions of Windows. The "WIN95" name is +historical; it should have been named "WIN32". + +To generate a "WIN95" configuration, specify the +``--enable-win32-target=WIN95`` configure option. + +.. _--enable-debug-rtl: + +--enable-debug-rtl +^^^^^^^^^^^^^^^^^^ + +This option is only used on Windows. NSPR debug build uses the release C +run-time library by default. To generate a debug build that uses the +debug C run-time library, specify the ``--enable-debug-rtl`` configure +option. + +.. _Makefile_targets: + +Makefile targets +~~~~~~~~~~~~~~~~ + +- all (default) +- clean +- realclean +- distclean +- install +- release + +.. _Running_the_test_programs: + +Running the test programs +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The tests were built above, in the ``pr/tests`` directory. + +On Mac OS X, they can be executed with the following: + +.. code:: + + /bin/sh: + + $ cd pr/tests + $ DYLD_LIBRARY_PATH=../../dist/lib ./accept + PASS + $ + $ # to run all the NSPR tests... + $ + $ DYLD_LIBRARY_PATH=../../dist/lib ../../../nspr/pr/tests/runtests.sh ../.. diff --git a/docs/nspr/nspr_contributor_guide.rst b/docs/nspr/nspr_contributor_guide.rst new file mode 100644 index 0000000000..08a0ac2f99 --- /dev/null +++ b/docs/nspr/nspr_contributor_guide.rst @@ -0,0 +1,182 @@ +NSPR contributor guide +====================== + +**Abstract:** + + NSPR accepts contributions in the form of bugfixes, new features, + libraries, platform ports, documentation, test cases and other items + from many sources. We (the NSPR module owners) sometimes disappoint + our contributors when we must reject their contributions. We reject + contributions for a variety of reasons. Some of these reasons are not + obvious to an outside observer. NSPR wishes to document some + guidelines for those who would contribute to NSPR. These guidelines + should help the contributor in crafting his contribution, increasing + its likelihood for acceptance. + +General Guidelines +~~~~~~~~~~~~~~~~~~ + +*Downward Compatibility* +^^^^^^^^^^^^^^^^^^^^^^^^ + +Because many different applications, besides the mozilla client, use the +NSPR API, the API must remain downward compatible across even major +releases. This means that the behavior of an existing public API item in +NSPR cannot change. Should you need to have a similar API, with some +slightly different behavior or different function prototype, then +suggest a new API with a different name. + +*C Language API* +^^^^^^^^^^^^^^^^ + +The NSPR API is a C Language API. Please do not contribute Java, C or +other language wrappers. + +*Coding Style* +^^^^^^^^^^^^^^ + +NSPR does not have a documented coding style guide. Look at the extant +code. Make yours look like that. Some guidelines concerning naming +conventions can be found in :ref:`NSPR_Naming_Conventions`. +in the :ref:`NSPR API Reference`. + +*Ownership of your contribution* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When you contribute something to NSPR, you must have intellectual +property rights to that contribution. This means that you cannot give us +something you snatched from somewhere else;. it must be your own +invention, free and clear of encumberment of anyone or anything else; +pay close attention to the rights of your "Day-Job" employer. If you +snatched it from somewhere else, tell us where; show us where the right +to incorporate it into NSPR exists. + +*License under MPL or GPL* +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When you contribute material to NSPR, you agree to allow your +contribution to be licensed under the MPL or GPL. + +BugFixes +~~~~~~~~ + +Use `Bugzilla <https://bugzilla.mozilla.org/>`__ to track bugs. Document +the bug or use an existing report. Be verbose in describing what you are +doing and why. + +Include your changes as diffs in an attachment to the BugZilla report. + +Use a coding style consistent with the source file you are changing. + +New Features +~~~~~~~~~~~~ + +For purposes of this paper, a "new feature" is defined as some API +addition that goes into the core NSPR library, for example: +``libnspr4.dll`` + +NSPR is mostly complete. New APIs are driven mostly by the OS vendors as +they add new features. Should you decide that there's something that +NSPR does not cover that should be covered, let's talk. Your proposed +API should encapsulate a relatively low level capability as would be +found in a system call or libc. + +Your new feature must be implemented on all platforms supported by NSPR. +When you consider a new API for NSPR ask yourself if your proposed +feature can implement it across all platforms supported by NSPR. If +several platforms cannot be made to implement your API, then it is not a +good candidate for inclusion in NSPR. + +Before you begin what may be a substantial effort in making a candidate +feature for NSPR, talk to us. We may tell you that you have a good idea; +we may say that it really is not a good candidate for inclusion in NSPR; +we may give you suggestions on what would make it more generalized, +hence a good candidate for inclusion in NSPR. + +Use `Bugzilla <https://bugzilla.mozilla.org>`__ to track your work. Be +verbose. + +NSPR wants you to document your work. If we accept it, we are going to +have to answer questions about it and/or maintain it. These are some +guidelines for new APIs that you may add to NSPR. + +**Header File Descriptions**. Provide header file descriptions that +fully document your public typedefs, enums, macros and functions. + +See: +`prshm.h <http://lxr.mozilla.org/nspr/source/nsprpub/pr/include/prshm.h>`__ +as an example of how your header file(s) should be documented. + +*Source File Descriptions*o. Provide descriptive documentation in your +source (*.c) files. Alas, we have no source files documented as we think +they should be. + +The following are some general guidelines to use when implementing new +features: + +- Don't export global variables +- Your code must be thread safe +- You must provide test cases that test all APIs you are adding. See: + [#TestCases Test Cases] + +New Libraries +~~~~~~~~~~~~~ + +All the guidelines applicable to [#NewFeatures New Features] applies to +new libraries. + +For purposes of this paper, a "new library" is defined as a library under +the ``mozilla/nsprpub/lib`` directory tree and built as a separate +library. These libraries exist, for the most part, as "legacy" code from +NSPR 1.0. [Note that the current NSPR module owners do not now nor never +have been involved with NSPR 1.0.]. Such is life. That said: There are +some libraries that implement functions intended for use with +applications using NSPR, such as ``...nsprpub/lib/libc/plgetopt.*.`` + +- generally useful +- platform abstractions +- you agree to sustain, bug fix +- May rely on the NSPR API +- May NOT rely on any other library API + +New Platform Ports +~~~~~~~~~~~~~~~~~~ + +- all NSPR API items must be implemented +- platform specific headers in ``pr/include/md/_platformname.[h!cfg]`` +- platform specific code in ``pr/src/md/platform/*.c`` +- make rules in ``config/_platform.mk`` + +Documentation +~~~~~~~~~~~~~ + +The files for NSPR's documentation are maintained using a proprietary +word processing system [don't ask]. Document your work as described in +[#NewFeatures New Features]. Use the style of other NSPR documentation. +We will see that your documentation is transcribed into the appropriate +word processor and the derived HTML shows up on mozilla.org + +Test Cases +~~~~~~~~~~ + +You should provide test cases for all new features and new libraries. + +Give consideration to providing a test case when fixing a bug if an +existing test case did not catch a bug it should have caught. + +The new test cases should be implemented in the style of other NSPR test +cases. + +Test cases should prove that the added API items work as advertised. + +Test cases should serve as an example of how to use the API items. + +Test cases should provoke failure of every API item and report its +failure. + +Frequently Asked Questions (FAQ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Q:** Why was my contribution rejected? + +**A:** Check the Bugzilla report covering your contribution. diff --git a/docs/nspr/nspr_poll_method.rst b/docs/nspr/nspr_poll_method.rst new file mode 100644 index 0000000000..6c15861562 --- /dev/null +++ b/docs/nspr/nspr_poll_method.rst @@ -0,0 +1,134 @@ +NSPR pool method +================ + +This technical note documents the poll method of PRFileDesc. The poll +method is not to be confused with the PR_Poll function. The poll method +operates on a single NetScape Portable Runtime (NSPR) file descriptor, +whereas PR_Poll operates on a collection of NSPR file descriptors. +PR_Poll uses the poll method behind the scene, but it is also possible +to use the poll method directly. + +We consider a stack of *NSPR I/O layers* on top of the *network +transport*. Each I/O layer is represented by a PRFileDesc structure and +the protocol of that layer is implemented by a PRIOMethods table. The +bottom layer is a wrapper for the underlying network transport. The NSPR +library provides a reference implementation of the bottom layer using +the sockets API, but you can provide your own implementation of the +bottom layer using another network transport API. The poll method is one +of the functions in the PRIOMethods table. The prototype of the poll +method is + +.. code:: + + PRInt16 poll_method(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags); + +The purpose of the poll method is to allow a layer to modify that flags +that will ultimately be used in the call to the underlying network +transport's select (or equivalent) function, and to indicate that a +layer is already able to make progress in the manner suggested by the +polling flags. The arguments and return value of the poll method are +described below. + +.. _in_flags_input_argument: + +in_flags [input argument] +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The in_flags argument specifies the events at the **top layer** of the +I/O layer stack that the caller is interested in. + +- For PR_Recv, you should pass PR_POLL_READ as the in_flags argument to + the poll method +- For PR_Send, you should pass PR_POLL_WRITE as the in_flags argument + to the poll method + +.. _out_flags_output_argument: + +out_flags [output argument] +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If an I/O layer is ready to satisfy the I/O request defined by in_flags +without involving the underlying network transport, its poll method sets +the corresponding event in \*out_flags on return. + +For example, consider an I/O layer that buffers input data. If the +caller wishes to test for read ready (that is, PR_POLL_READ is set in +in_flags) and the layer has input data buffered, the poll method would +set the PR_POLL_READ event in \*out_flags. It can determine that without +asking the underlying network transport. + +The current implementation of PR_Poll (the primary user of the poll +method) requires that the events in \*out_flags reflect the caller's +view. This requirement may be relaxed in a future NSPR release. To +remain compatible with this potential semantic change, NSPR clients +should only use \*out_flags as described in the *How to use the poll +method* section below. + +.. _Return_value: + +Return value +~~~~~~~~~~~~ + +If the poll method stores a nonzero value in \*out_flags, the return +value will be the value of in_flags. (Note: this may change in a future +NSPR release if we make the semantic change to \*out_flags mentioned +above. Therefore, NSPR clients should only use the return value as +described in *How to use the poll method* section below.) If the poll +method stores zero in \*out_flags, the return value will be the bottom +layer's desires with respect to the in_flags. Those are the events that +the caller should poll the underlying network transport for. These +events may be different from the events in in_flags (which reflect the +caller's view) for some protocols. + +.. _How_to_use_the_poll_method: + +How to use the poll method +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The poll method should only be used with a NSPR file descriptor in +**non-blocking** mode. Most NSPR clients call PR_Poll and do not call +the poll method directly. However, PR_Poll can only used with a stack +whose bottom layer is NSPR's reference implementation. If you are using +your own implementation of the bottom layer, you must call the poll +method as follows. + +Declare two PRInt16 variables to receive the return value and the +out_flags output argument of the poll method. + +.. code:: + + PRInt16 new_flags, out_flags; + +If you are going to call PR_Recv, pass PR_POLL_READ as the in_flags +argument. + +.. code:: + + new_flags = fd->methods->poll(fd, PR_POLL_READ, &out_flags); + +If you are going to call PR_Send, pass PR_POLL_WRITE as the in_flags +argument. + +.. code:: + + new_flags = fd->methods->poll(fd, PR_POLL_WRITE, &out_flags); + +If you are interested in calling both PR_Recv and PR_Send on the same +file descriptor, make two separate calls to the poll method, one with +PR_POLL_READ as in_flags and the other with PR_POLL_WRITE as in_flags, +so that you know what events at the network transport layer PR_POLL_READ +and PR_POLL_WRITE are mapped to, respectively. + +On return, if (new_flags & out_flags) is nonzero, you can try PR_Recv or +PR_Send immediately. + +Otherwise ((new_flags & out_flags) is 0), you should do the following. + +- If new_flags contains PR_POLL_READ, you should try PR_Recv or PR_Send + when the underlying network transport is readable +- If new_flags contains PR_POLL_WRITE, you should try PR_Recv or + PR_Send when the underlying network transport is writable + +**Important** do not use out_flags in any way other than testing if +(new_flags & out_flags) is 0. This is how PR_Poll (the primary user and +hence the de facto specification of the poll method) uses out_flags. diff --git a/docs/nspr/nspr_release_procedure.rst b/docs/nspr/nspr_release_procedure.rst new file mode 100644 index 0000000000..c482c882d9 --- /dev/null +++ b/docs/nspr/nspr_release_procedure.rst @@ -0,0 +1,50 @@ +NSPR release procedure +====================== + +Release checklist +~~~~~~~~~~~~~~~~~ + +#. Change the NSPR version in ``mozilla/nsprpub/pr/include/prinit.h``. +#. Change the NSPR version in + ``mozilla/nsprpub/{configure.in,configure}``. +#. Change the NSPR version in ``mozilla/nsprpub/pr/tests/vercheck.c``. +#. Change the NSPR version in ``mozilla/nsprpub/admin/repackage.sh``. + +.. _Source_tarball: + +Source tarball +~~~~~~~~~~~~~~ + +.. _Binary_distributions: + +Binary distributions +~~~~~~~~~~~~~~~~~~~~ + +Right now I use the ``mozilla/nsprpub/admin/repackage.sh`` script to +generate the binary distributions published on ftp.mozilla.org. As the +name of the shell script implies, ``repackage.sh`` merely repackages +binary distributions in a different format. + +Before you run ``repackage.sh``, you need to have built the binary +distributions using the "gmake release" makefile target. These binary +distributions are jar files, which are really zip files, and they are +published in the directory ``/share/builds/components``. This design +comes from the Netscape days. + +The ``repackage.sh`` script repackages the jar files into the form most +commonly used on that platform. So on Unix it repackages the jar files +into gzipped tar files, and on Windows it repackages the jar files into +zip files. + +Edit the ``repackage.sh`` script to customize it for your environment. + +After you have run ``repackage.sh``, follow the +`instructions <http://www.mozilla.org/build/ftp-stage.html>`__ in to +upload the files to ftp.mozilla.org's staging server, so that they +eventually show up on ftp.mozilla.org. The host ftp.mozilla.org can be +accessed via the ftp, http, and https protocols. We recommend using +https://ftp.mozilla.org/. + +**Note:** For NSS, the script equivalent to NSPR's ``repackage.sh`` is +``/u/robobld/bin/sbsinit/nss/push/buildbindist.sh`` in the "SVBuild" +source tree. diff --git a/docs/nspr/nspr_s_position_on_abrupt_thread_termination.rst b/docs/nspr/nspr_s_position_on_abrupt_thread_termination.rst new file mode 100644 index 0000000000..7cbda0c2c6 --- /dev/null +++ b/docs/nspr/nspr_s_position_on_abrupt_thread_termination.rst @@ -0,0 +1,88 @@ +NSPR's position on abrupt thread termination +============================================ + +This memo describes my position on a facility that is currently under +discussion for inclusion in the NetScape Portable Runtime (NSPR); the +ability of a thread to abruptly exit. I resist including this function +in NSPR because it results in bad programming practice and unsupportable +programs. + + *Threads are not processes.* + +Abrupt termination has been available in the UNIX/C environment for some +time (``exit()``), and I assume that the basic semantics defined there +are applicable here. In that environment, ``exit()`` may be called and +any time, and results in the calling thread's immediate termination. In +the situation where it was defined (UNIX), which has only a single +thread of execution, that is equivalent to terminating the process. The +process abstraction is then responsible for closing all open files and +reclaiming all storage that may have been allocated during the process' +lifetime. + +This practice does not extend to threads. Threads run within the +confines of a process (or similar abstractions in other environments). +Threads are lightweight because they do not maintain the full protection +domain provided by a process. So in a threaded environment, what is the +parallel to UNIX' ``exit()``? + +NSPR has defined a function, callable by any thread within a process at +any time, called ``PR_ProcessExit()``. This is identical to UNIX +``exit()`` and was so named in an effort to make the obvious even more +so. When called, the process exits, closing files and reclaiming the +process' storage. + +Certain people have been disappointed when NSPR did not provide a +functional equivalent to exit just a particular thread. Apparently they +have failed to consider the ramifications. If a thread was to abruptly +terminate, there is no recording of what resources it owns and should +therefore be reclaimed. Those resources are in fact, owned by the +process and shared by all the threads within the process. + +In the general course of events when programming with threads, it is +very advantageous for a thread to have resources that it and only it +knows about. In the natural course of events, these resources will be +allocated by a thread, used for some period of time, and then freed as +the stack unwinds. In these cases, the presence of the data is recorded +only on the stack, known only to the single thread (normally referred to +as *encapsulated*). + +The problem with abrupt termination is that it can happen at any time, +to a thread that is coded correctly to handle both normal and +exceptional situations, but will be unable to do so since it will be +denied the opportunity to complete execution. It can happen because it +called out of its own scope into some lazily implemented library. + +NSPR's answer to this is that there is no abrupt thread termination. All +threads must unwind and return from their root function. If they cannot, +because of some state corruption, then they must assume that the +corruption, like the state, is shared, and their only resource is for +the process to terminate. + +To make this solution work requires that a function that encounters an +error be designed such that it first repairs its immediate state, and +then reports that error to its caller. If the caller cannot deal with +the failure, it must do the same. This process continues until the +thread either recovers from the malady or returns from the root +function. This is not all that difficult (though having done it a number +of times to already existing code, I will admit it isn't much fun +either). + +The implementation of either strategy within the NSPR runtime is not +difficult. That is not what this memo is about. This is about providing +an API that coaxes people to do the right thing in as many ways as +possible. The existence of ``exit()`` in the UNIX/C environment is a +perfect example of how programmers will employ the most expediant +solution available. The definition of the language C is such that +returning from ``main()`` is a perfectly fine thing to do. But what +percentage of C programs actually bother? In UNIX, with its complex +definition of a protection domain, it happens to work (one might even +say it's more efficient) to exit from anywhere. But threads are not +processes. If threads have to maintain the same type of resource +knowledge as a process, they loose all of their benefit. + +Threads are an implementation strategy to provide the illusion of +concurrency within a process. They are alternatives to large state +machines with mostly non-blocking library functions. When the latter is +used to provide concurrency, calling ``exit()`` will terminate the +entire process. Why would anyone expect a thread to behave differently? +Threads are not processes. diff --git a/docs/nspr/optimizing_applications_for_nspr.rst b/docs/nspr/optimizing_applications_for_nspr.rst new file mode 100644 index 0000000000..1bced161a8 --- /dev/null +++ b/docs/nspr/optimizing_applications_for_nspr.rst @@ -0,0 +1,45 @@ +Optimizing applications for NSPR +================================ + +NetScape Portable Runtime (NSPR) tries to provide a consistent level of +service across the platforms it supports. This has proven to be quite +challenging, a challenge that was met to a large degree, but there is +always room for improvement. The casual client may not encounter a need +to know the details of the shortcomings to the level described here, but +if and when clients become more sophisticated, these issues will +certainly surface. + + *This memo is by no way complete.* + +Multiplatform +------------- + +- Do not call any blocking system call from a local thread. The only + exception to this rule is the <tt>select()</tt> and <tt>poll()</tt> + system calls on Unix, both of which NSPR has overridden to make sure + they are aware of the NSPR local threads. +- In the combined (MxN) model, which includes NT, IRIX (sprocs), and + pthreads-user, the primordial thread is always a local thread. + Therefore, if you call a blocking system call from the primordial + thread, it is going to block more than just the primordial thread and + the system may not function correctly. On NT, this problem is + especially obvious because the idle thread, which is in charge of + driving the asynch io completion port, is also blocked. Do not call + blocking system calls from the primordial thread. Create a global + thread and call the system call in that thread, and have the + primordial thread join that thread. +- NSPR uses timer signals to implement thread preemption for local + threads on some platforms. If all the software linked into the + application is not ported to the NSPR API, the application may fail + because of threads being preempted during critical sections. To + disable thread preemption call + <tt>PR_DisableClockInterrupts()</tt>during initialization. +- Interrupting threads (via <tt>PR_Interrupt()</tt>) on threads blocked + in I/O functions is implemented to various degrees on different + platforms. The UNIX based platforms all implement the function though + there may be up to a 5 second delay in processing the request. +- The mechanism used to implement <tt>PR_Interrupt()</tt> on the + *pthreads* versions of NSPR is flawed. No failure attributable to the + flaw has shown up in any tests or products - yet. The specific area + surrounding pthread's *continuation thread* has been both observed + and empirically proven faulty, and a correction identified. diff --git a/docs/nspr/platforms.rst b/docs/nspr/platforms.rst new file mode 100644 index 0000000000..6e251a4d71 --- /dev/null +++ b/docs/nspr/platforms.rst @@ -0,0 +1,145 @@ +NSPR platforms +============== + +Build System and Supported Platforms +------------------------------------ + +NSPR has been implemented on over 20 platforms. A platform may have +more than one implementation strategy of its multi threading and I/O +facilities. This article explains the NSPR build system and how to +specify a particular implementation strategy, compiler or compiler +switches, or the target OS for your build on each platform. + +Implementation Strategies +------------------------- + +Threads are at the core of NSPR, and the I/O functions are tied to the +multi threading facilities because many I/O functions may block the +calling threads. NSPR has multiple implementation strategies of its +multi threading and I/O functions. The various implementation strategies +can be organized into the hierarchy below: + +- **Classic NSPR** (This is our first code base, hence the term + "classic NSPR"): + +**Local threads only**: All threads are user-level threads implemented +by NSPR. +**Global threads only**: All threads are native threads supplied by the +OS vendor. For example, Solaris UI (Unix International) threads and +Win32 threads. +**Combined**: NSPR multiplexes user-level threads on top of native, +kernel-level threads. This is also called the MxN model. At present, +there are three implementations of the combined model. + +- IRIX: sprocs + NSPR user-level threads +- Windows NT: Win32 threads + NT fibers +- **Pthreads-user**: kernel-level pthreads + NSPR user-level threads + +**Pthreads**: All threads are pthreads. The relevant code is in +``mozilla/nsprpub/pr/src/pthreads`` (threads and I/O). +Classic NSPR and pthreads have relatively disjoint code bases in the +threads and I/O areas: + +- Classic NSPR: ``mozilla/nsprpub/pr/src/threads/combined`` (threads), + ``mozilla/nsprpub/pr/src/io`` (I/O) +- Pthreads: ``mozilla/nsprpub/pr/src/pthreads`` (threads and I/O) + +Note that some files under ``mozilla/nsprpub/pr/src/io`` are shared by +both classic NSPR and pthreads. Consult +``mozilla/nsprpub/pr/src/Makefile`` for the definitive list of files +used by each implementation strategy (see the definition of the makefile +variable ``OBJS``). + +Compilers +--------- + +For ease of integration with third-party libraries, which may use native +threads, NSPR uses the native threads whenever possible. As a result, +native compilers are used to build NSPR on most platforms because they +have better debugging support for native threads. The only exception is +Solaris, where both cc and gcc are used. + +NSPR Build System +----------------- + +NSPR build system is based on GNU make. +We use GNU make 3.74 on Unix, but our makefiles should +work fine under newer versions of GNU make. + +Every directory in NSPR has a makefile named ``Makefile``, which +includes the makefile fragments in ``mozilla/nsprpub/config``. NSPR +makefiles implement the common Makefile targets such as +``export``, ``libs``, and ``install``. However, some makefiles targets +are no-op in NSPR because they are not necessary for NSPR. + +To build NSPR, change directory to the root of our source tree +``cd mozilla/nsprpub`` +and then issue the command +``gmake`` +Make will recursively go into all the subdirectories and the right +things will happen. + +The table below lists the common NSPR makefile targets. + ++-----------------------------------+-----------------------------------+ +| ``all`` | The default target. Same as | +| | ``export`` ``libs`` ``install``. | ++-----------------------------------+-----------------------------------+ +| ``export`` | Do a complete build. | ++-----------------------------------+-----------------------------------+ +| ``libs`` | No-op. | ++-----------------------------------+-----------------------------------+ +| ``install`` | No-op. | ++-----------------------------------+-----------------------------------+ +| ``depend`` | No-op. **This means that NSPR | +| | makefiles do not have header file | +| | dependencies.** | ++-----------------------------------+-----------------------------------+ +| ``clean`` | Remove ``.o`` files. | ++-----------------------------------+-----------------------------------+ +| ``clobber`` | Remove ``.o`` files, libraries, | +| | and executable programs. | ++-----------------------------------+-----------------------------------+ +| ``realclean`` | Remove all generated files and | +| | directories. | ++-----------------------------------+-----------------------------------+ +| ``clobber_all`` | Same as ``realclean``. | ++-----------------------------------+-----------------------------------+ + +The table below lists common makefile variables that one can specify +on the command line to customize a build.. + ++-----------------------------------+-----------------------------------+ +| ``BUILD_OPT`` | Optimized build (default: debug | +| | build). | ++-----------------------------------+-----------------------------------+ +| ``OS_TARGET`` | Set to the target OS (``WIN95`` | +| | or ``WIN16``) when doing | +| | cross-compilation on NT (default: | +| | same as the host OS). | ++-----------------------------------+-----------------------------------+ +| ``NS_USE_GCC`` | Use gcc and g++ (default: native | +| | compilers). | ++-----------------------------------+-----------------------------------+ +| ``USE_PTHREADS`` | Build pthreads version. | ++-----------------------------------+-----------------------------------+ +| ``CLASSIC_NSPR`` | Build classic NSPR version | +| | (usually local threads only). | ++-----------------------------------+-----------------------------------+ +| ``PTHREADS_USER`` | Build pthreads-user version. | ++-----------------------------------+-----------------------------------+ +| ``LOCAL_THREADS_ONLY`` | Build local threads only version. | ++-----------------------------------+-----------------------------------+ +| ``USE_DEBUG_RTL`` | On Win32, compile with ``/MDd`` | +| | in the debug build (default: | +| | ``/MD``). Optimized build always | +| | uses ``/MD``. | ++-----------------------------------+-----------------------------------+ +| ``USE_N32`` | On IRIX, compile with ``-n32`` | +| | (default: ``-32``). | ++-----------------------------------+-----------------------------------+ +| ``USE_IPV6`` | Enable IPv6. | ++-----------------------------------+-----------------------------------+ +| ``MOZILLA_CLIENT`` | Adjust NSPR build system for | +| | Netscape Client (mozilla). | ++-----------------------------------+-----------------------------------+ diff --git a/docs/nspr/process_forking_in_nspr.rst b/docs/nspr/process_forking_in_nspr.rst new file mode 100644 index 0000000000..d73291edf0 --- /dev/null +++ b/docs/nspr/process_forking_in_nspr.rst @@ -0,0 +1,23 @@ +Process forking in NSPR +======================= + +The threads provided in NetScape Portable Runtime (NSPR) are implemented +using different mechanisms on the various platforms. On some platforms, +NSPR threads directly map one-to-one to the threads provided by the +platform vendor, on other platforms NSPR threads are basically +user-level threads within a single process (with no kernel threads) and +on still others NSPR threads are user-level threads implemented on top +of one or more kernel threads within single address space. + +NSPR does not override the fork function and so, when fork is called +from the NSPR thread the results are different on the various platforms. +All the threads present in the parent process may be replicated in the +child process, only the calling thread may be replicated in the child +process or only the calling kernel thread may be replicated. + +So, to be consistent across all platforms, it is suggested that when +using fork in a NSPR thread; + +#. The exec function should be called in the child process. +#. No NSPR functions should be called in the child process before the + exec call is made. diff --git a/docs/nspr/reference/anonymous_shared_memory.rst b/docs/nspr/reference/anonymous_shared_memory.rst new file mode 100644 index 0000000000..3daea2cbb0 --- /dev/null +++ b/docs/nspr/reference/anonymous_shared_memory.rst @@ -0,0 +1,118 @@ +Anonymous Shared Memory +======================= + +This chapter describes the NSPR API for anonymous shared memory. + +- `Anonymous Memory Protocol <#Anonymous_Memory_Protocol>`__ +- `Anonymous Shared Memory + Functions <#Anonymous_Shared_Memory_Functions>`__ + +.. _Anonymous_Memory_Protocol: + +Anonymous Memory Protocol +------------------------- + +NSPR provides an anonymous shared memory based on NSPR's :ref:`PRFileMap` +type. The anonymous file-mapped shared memory provides an inheritable +shared memory, as in: the child process inherits the shared memory. +Compare the file-mapped anonymous shared memory to to a named shared +memory described in prshm.h. The intent is to provide a shared memory +that is accessible only by parent and child processes. ... It's a +security thing. + +Depending on the underlying platform, the file-mapped shared memory may +be backed by a file. ... surprise! ... On some platforms, no real file +backs the shared memory. On platforms where the shared memory is backed +by a file, the file's name in the filesystem is visible to other +processes for only the duration of the creation of the file, hopefully a +very short time. This restricts processes that do not inherit the shared +memory from opening the file and reading or writing its contents. +Further, when all processes using an anonymous shared memory terminate, +the backing file is deleted. ... If you are not paranoid, you're not +paying attention. + +The file-mapped shared memory requires a protocol for the parent process +and child process to share the memory. NSPR provides two protocols. Use +one or the other; don't mix and match. + +In the first protocol, the job of passing the inheritable shared memory +is done via helper-functions with PR_CreateProcess. In the second +protocol, the parent process is responsible for creating the child +process; the parent and child are mutually responsible for passing a +``FileMap`` string. NSPR provides helper functions for extracting data +from the :ref:`PRFileMap` object. ... See the examples below. + +Both sides should adhere strictly to the protocol for proper operation. +The pseudo-code below shows the use of a file-mapped shared memory by a +parent and child processes. In the examples, the server creates the +file-mapped shared memory, the client attaches to it. + +.. _First_protocol: + +First protocol +~~~~~~~~~~~~~~ + +**Server:** + +.. code:: + + fm = PR_OpenAnonFileMap(dirName, size, FilemapProt); + addr = PR_MemMap(fm); + attr = PR_NewProcessAttr(); + PR_ProcessAttrSetInheritableFileMap( attr, fm, shmname ); + PR_CreateProcess(Client); + PR_DestroyProcessAttr(attr); + ... yadda ... + PR_MemUnmap( addr ); + PR_CloseFileMap(fm); + +**Client:** + +.. code:: + + ... started by server via PR_CreateProcess() + fm = PR_GetInheritedFileMap( shmname ); + addr = PR_MemMap(fm); + ... yadda ... + PR_MemUnmap(addr); + PR_CloseFileMap(fm); + +.. _Second_protocol: + +Second protocol +~~~~~~~~~~~~~~~ + +**Server:** + +.. code:: + + fm = PR_OpenAnonFileMap(dirName, size, FilemapProt); + fmstring = PR_ExportFileMapAsString( fm ); + addr = PR_MemMap(fm); + ... application specific technique to pass fmstring to child + ... yadda ... Server uses his own magic to create child + PR_MemUnmap( addr ); + PR_CloseFileMap(fm); + +**Client:** + +.. code:: + + ... started by server via his own magic + ... application specific technique to find fmstring from parent + fm = PR_ImportFileMapFromString( fmstring ) + addr = PR_MemMap(fm); + ... yadda ... + PR_MemUnmap(addr); + PR_CloseFileMap(fm); + +.. _Anonymous_Shared_Memory_Functions: + +Anonymous Shared Memory Functions +--------------------------------- + +- :ref:`PR_OpenAnonFileMap` +- :ref:`PR_ProcessAttrSetInheritableFileMap` +- :ref:`PR_GetInheritedFileMap` +- :ref:`PR_ExportFileMapAsString` +- :ref:`PR_ImportFileMapFromString` diff --git a/docs/nspr/reference/atomic_operations.rst b/docs/nspr/reference/atomic_operations.rst new file mode 100644 index 0000000000..1599d39ce8 --- /dev/null +++ b/docs/nspr/reference/atomic_operations.rst @@ -0,0 +1,32 @@ +This chapter describes the global functions you use to perform atomic +operations. The functions define a portable API that may be reliably +used in any environment. Since not all operating environments provide +access to such functions, their performance may vary considerably. + +.. _Atomic_Operations_Functions: + +Atomic Operations Functions +--------------------------- + +The API defined for the atomic functions is consistent across all +supported platforms. However, the implementation may vary greatly, and +hence the performance. On systems that do not provide direct access to +atomic operators, NSPR emulates the capabilities by using its own +locking mechanisms. For such systems, NSPR performs atomic operations +just as efficiently as the client could. Therefore, to preserve +portability, it is recommended that clients use the NSPR API for atomic +operations. + +These functions operate on 32-bit integers: + +- :ref:`PR_AtomicIncrement` +- :ref:`PR_AtomicDecrement` +- :ref:`PR_AtomicSet` +- :ref:`PR_AtomicAdd` + +These functions implement a simple stack data structure: + +- :ref:`PR_CreateStack` +- :ref:`PR_StackPush` +- :ref:`PR_StackPop` +- :ref:`PR_DestroyStack` diff --git a/docs/nspr/reference/cached_monitors.rst b/docs/nspr/reference/cached_monitors.rst new file mode 100644 index 0000000000..647bdb1b54 --- /dev/null +++ b/docs/nspr/reference/cached_monitors.rst @@ -0,0 +1,37 @@ +This chapter describes the functions you use when you work with cached +monitors. Unlike a plain monitor, a cached monitor is associated with +the address of a protected object, and the association is maintained +only while the protection is needed. This arrangement allows a cached +monitor to be associated with another object without preallocating a +monitor for all objects. A hash table is used to quickly map addresses +to their respective monitors. The system automatically enlarges the hash +table as needed. + +Important +--------- + +Cached monitors are slower to use than their uncached counterparts. + +See `Monitors <Monitors>`__ for information about uncached monitors. + +.. _Cached_Monitors_Functions: + +Cached Monitors Functions +------------------------- + +Cached monitors allow the client to associate monitoring protection and +state change synchronization in a lazy fashion. The monitoring +capability is associated with the protected object only during the time +it is required, allowing the monitor object to be reused. This +additional flexibility comes at the cost of a small loss in performance. + + - :ref:`PR_CEnterMonitor` enters the lock associated with a cached + monitor. + - :ref:`PR_CExitMonitor` decrements the entry count associated with a + cached monitor. + - :ref:`PR_CWait` waits for a notification that a monitor's state has + changed. + - :ref:`PR_CNotify` notifies a thread waiting for a change in the state of + monitored data. + - :ref:`PR_CNotifyAll` notifies all the threads waiting for a change in + the state of monitored data. diff --git a/docs/nspr/reference/condition_variables.rst b/docs/nspr/reference/condition_variables.rst new file mode 100644 index 0000000000..b5a1b5abcb --- /dev/null +++ b/docs/nspr/reference/condition_variables.rst @@ -0,0 +1,50 @@ +This chapter describes the API for creating and destroying condition +variables, notifying condition variables of changes in monitored data, +and making a thread wait on such notification. + +- `Condition Variable Type <#Condition_Variable_Type>`__ +- `Condition Variable Functions <#Condition_Variable_Functions>`__ + +Conditions are closely associated with a single monitor, which typically +consists of a mutex, one or more condition variables, and the monitored +data. The association between a condition and a monitor is established +when a condition variable is created, and the association persists for +its life. In addition, a static association exists between the condition +and some data within the monitor. This data is what will be manipulated +by the program under the protection of the monitor. + +A call to :ref:`PR_WaitCondVar` causes a thread to block until a specified +condition variable receives notification of a change of state in its +associated monitored data. Other threads may notify the condition +variable when changes occur. + +For an introduction to NSPR thread synchronization, including locks and +condition variables, see `Introduction to +NSPR <Introduction_to_NSPR>`__. + +For reference information on NSPR locks, see +`Locks <NSPR_API_Reference/Locks>`__. + +NSPR provides a special type, :ref:`PRMonitor`, for use with Java. Unlike a +mutex of type :ref:`PRLock`, which can have multiple associated condition +variables of type :ref:`PRCondVar`, a mutex of type :ref:`PRMonitor` has a +single, implicitly associated condition variable. For information about +:ref:`PRMonitor`, see `Monitors <Monitors>`__. + +.. _Condition_Variable_Type: + +Condition Variable Type +----------------------- + + - :ref:`PRCondVar` + +.. _Condition_Variable_Functions: + +Condition Variable Functions +---------------------------- + + - :ref:`PR_NewCondVar` + - :ref:`PR_DestroyCondVar` + - :ref:`PR_WaitCondVar` + - :ref:`PR_NotifyCondVar` + - :ref:`PR_NotifyAllCondVar` diff --git a/docs/nspr/reference/date_and_time.rst b/docs/nspr/reference/date_and_time.rst new file mode 100644 index 0000000000..b86929b44e --- /dev/null +++ b/docs/nspr/reference/date_and_time.rst @@ -0,0 +1,83 @@ +This chapter describes the date and time functions in NSPR. + +NSPR represents time in two ways, absolute time and clock/calendar time. +NSPR provides types and constants for both representations, and +functions to convert time values between the two. + +- Absolute time representation treats time instants as points along the + time line. A time instant is represented by its position on the time + line relative to the origin, called the epoch. NSPR defines the epoch + to be midnight (00:00:00) 1 January 1970 UTC (Coordinated Universal + Time). In this form, time is just a point on the time line. There is + no notion of time zone. + +- Clock/calendar time, used for human interfaces, represents time in + the familiar year, month, day, hour, minute, second components. In + this form, the time zone information is important. For example, + without specifying the time zone, the time 8:00AM 1 May 1998 is + ambiguous. The NSPR data type for clock/calendar time, called an + exploded time, has the time zone information in it, so that its + corresponding point in absolute time is uniquely specified. + +Note that absolute and clock times are not normally used in timing +operations. For functions that deal with the measurement of elapsed time +and with timeouts, see `Interval Timing <Interval_Timing>`__. + +- `Macros for Time Unit + Conversion <#Macros_for_Time_Unit_Conversion>`__ +- `Types and Constants <#Types_and_Constants>`__ +- `Time Parameter Callback + Functions <#Time_Parameter_Callback_Functions>`__ +- `Functions <#Functions>`__ + +.. _Macros_for_Time_Unit_Conversion: + +Macros for Time Unit Conversion +------------------------------- + +Macros for converting between seconds, milliseconds, microseconds, and +nanoseconds. + +- :ref:`PR_MSEC_PER_SEC` +- :ref:`PR_USEC_PER_SEC` +- :ref:`PR_NSEC_PER_SEC` +- :ref:`PR_USEC_PER_MSEC` +- :ref:`PR_NSEC_PER_MSEC` + +.. _Types_and_Constants: + +Types and Constants +------------------- + +Types and constants defined for NSPR dates and times are: + +- :ref:`PRTime` +- :ref:`PRTimeParameters` +- :ref:`PRExplodedTime` + +.. _Time_Parameter_Callback_Functions: + +Time Parameter Callback Functions +--------------------------------- + +In some geographic locations, use of Daylight Saving Time (DST) and the +rule for determining the dates on which DST starts and ends have changed +a few times. Therefore, a callback function is used to determine time +zone information. + +You can define your own time parameter callback functions, which must +conform to the definition :ref:`PRTimeParamFn`. Two often-used callback +functions of this type are provided by NSPR: + +- :ref:`PRTimeParamFn` +- :ref:`PR_LocalTimeParameters` and :ref:`PR_GMTParameters` + +Functions +--------- + +The functions that create and manipulate time and date values are: + +- :ref:`PR_Now` +- :ref:`PR_ExplodeTime` +- :ref:`PR_ImplodeTime` +- :ref:`PR_NormalizeTime` diff --git a/docs/nspr/reference/dynamic_library_linking.rst b/docs/nspr/reference/dynamic_library_linking.rst new file mode 100644 index 0000000000..6ab8d33840 --- /dev/null +++ b/docs/nspr/reference/dynamic_library_linking.rst @@ -0,0 +1,114 @@ +Dynamic Library Search +====================== + +This section describes NSPR's programming interface to load, unload and +resolve symbols in dynamic libraries. It also provides a method by which +to condition symbols of statically linked code so that to other clients +it appears as though they are dynamically loaded. + +.. _Library_Linking_Types: + +Library Linking Types +--------------------- + +These data types are defined for dynamic library linking: + + - :ref:`PRLibrary` + - :ref:`PRStaticLinkTable` + +.. _Library_Linking_Functions: + +Library Linking Functions +------------------------- + +The library linking functions are: + + - :ref:`PR_SetLibraryPath` + - :ref:`PR_GetLibraryPath` + - :ref:`PR_GetLibraryName` + - :ref:`PR_FreeLibraryName` + - :ref:`PR_LoadLibrary` + - :ref:`PR_UnloadLibrary` + - :ref:`PR_FindSymbol` + - :ref:`PR_FindSymbolAndLibrary` + +.. _Finding_Symbols_Defined_in_the_Main_Executable_Program: + +Finding Symbols Defined in the Main Executable Program +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:ref:`PR_LoadLibrary` cannot open a handle that references the main +executable program. (This is admittedly an omission that should be +fixed.) However, it is possible to look up symbols defined in the main +executable program as follows. + +.. code:: + + PRLibrary *lib; + void *funcPtr; + + funcPtr = PR_FindSymbolAndLibrary("FunctionName", &lib); + +When :ref:`PR_FindSymbolAndLibrary` returns, ``funcPtr`` is the value of +the function pointer you want to look up, and the variable lib +references the main executable program. You can then call +:ref:`PR_FindSymbol` on lib to look up other symbols defined in the main +program. Remember to call ``PR_UnloadLibrary(lib)`` to close the library +handle when you are done. + +.. _Platform_Notes: + +Platform Notes +-------------- + +To use the dynamic library loading functions on some platforms, certain +environment variables must be set at run time, and you may need to link +your executable programs using special linker options. + +This section summarizes these platform idiosyncrasies. For more +information, consult the man pages for ``ld`` and ``dlopen`` (or +``shl_load`` on HP-UX) for Unix, and the ``LoadLibrary`` documentation +for Win32. + +- `Dynamic Library Search Path <#Dynamic_Library_Search_Path>`__ +- `Exporting Symbols from the Main Executable + Program <#Exporting_Symbols_from_the_Main_Executable_Program>`__ + +Dynamic Library Search Path +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The dynamic library search path is the list of directories in which to +look for a dynamic library. Each platform has its own standard +directories in which to look for dynamic libraries, plus a customizable +list of directories specified by an environment variable. + +- On most Unix systems, this environment variable is + ``LD_LIBRARY_PATH``. These systems typically use ``dlopen`` to load a + dynamic library. +- HP-UX uses ``shl_load`` to load dynamic libraries, and the + environment variable specifying the dynamic library search path is + ``SHLIB_PATH``. Moreover, the executable program must be linked with + the +s option so that it will search for shared libraries in the + directories specified by ``SHLIB_PATH`` at run time. Alternatively, + you can enable the +s option as a postprocessing step using the + ``chatr`` tool. For example, link your executable program a.out + without the +s option, then execute the following: + +.. code:: + + chatr +s enable a.out + +- On Rhapsody, the environment variable is ``DYLD_LIBRARY_PATH``. +- On Win32, the environment variable is ``PATH``. The same search path + is used to search for executable programs and DLLs. + +.. _Exporting_Symbols_from_the_Main_Executable_Program: + +Exporting Symbols from the Main Executable Program +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On some systems, symbols defined in the main executable program are not +exported by default. On HP-UX, you must link the executable program with +the -E linker option in order to export all symbols in the main program +to shared libraries. If you use the GNU compilers (on any platform), you +must also link the executable program with the -E option. diff --git a/docs/nspr/reference/floating_point_number_to_string_conversion.rst b/docs/nspr/reference/floating_point_number_to_string_conversion.rst new file mode 100644 index 0000000000..6c9b36003f --- /dev/null +++ b/docs/nspr/reference/floating_point_number_to_string_conversion.rst @@ -0,0 +1,24 @@ +NSPR provides functions that convert double-precision floating point +numbers to and from their character string representations. + +These conversion functions were originally written by David M. Gay of +AT&T. They use IEEE double-precision (not IEEE double-extended) +arithmetic. + +The header file ``prdtoa.h`` declares these functions. The functions +are: + + - :ref:`PR_strtod` + - :ref:`PR_dtoa` + - :ref:`PR_cnvtf` + +References +---------- + +Gay's implementation is inspired by these two papers. + +[1] William D. Clinger, "How to Read Floating Point Numbers Accurately," +Proc. ACM SIGPLAN '90, pp. 92-101. + +[2] Guy L. Steele, Jr. and Jon L. White, "How to Print Floating-Point +Numbers Accurately," Proc. ACM SIGPLAN '90, pp. 112-126. diff --git a/docs/nspr/reference/hash_tables.rst b/docs/nspr/reference/hash_tables.rst new file mode 100644 index 0000000000..bafef49c4b --- /dev/null +++ b/docs/nspr/reference/hash_tables.rst @@ -0,0 +1,42 @@ +This chapter describes the hash table functions in the plds (portable +library — data structures) library of NSPR. The hash table library +functions are declared in the header file ``plhash.h.`` + +.. warning:: + + **Warning**: The NSPR hash table library functions are not thread + safe. + +A hash table lookup may change the internal organization of the hash +table (to speed up future lookups). + +- `Hash Table Types and Constants <#Hash_Table_Types_and_Constants>`__ +- `Hash Table Functions <#Hash_Table_Functions>`__ + +.. _Hash_Table_Types_and_Constants: + +Hash Table Types and Constants +------------------------------ + + - :ref:`PLHashEntry` + - :ref:`PLHashTable` + - :ref:`PLHashNumber` + - :ref:`PLHashFunction` + - :ref:`PLHashComparator` + - :ref:`PLHashEnumerator` + - :ref:`PLHashAllocOps` + +.. _Hash_Table_Functions: + +Hash Table Functions +-------------------- + + - :ref:`PL_NewHashTable` + - :ref:`PL_HashTableDestroy` + - :ref:`PL_HashTableAdd` + - :ref:`PL_HashTableRemove` + - :ref:`PL_HashTableLookup` + - :ref:`PL_HashTableEnumerateEntries` + - :ref:`PL_HashString` + - :ref:`PL_CompareStrings` + - :ref:`PL_CompareValues` diff --git a/docs/nspr/reference/i_o_functions.rst b/docs/nspr/reference/i_o_functions.rst new file mode 100644 index 0000000000..a13d0b3b74 --- /dev/null +++ b/docs/nspr/reference/i_o_functions.rst @@ -0,0 +1,240 @@ +I/O functions +============= + +This chapter describes the NSPR functions used to perform operations +such as system access, normal file I/O, and socket (network) I/O. + +For sample code that illustrates basic I/O operations, see :ref:`Introduction_to_NSPR>`. +For information about the types most +commonly used with the functions described in this chapter, see `I/O +Types <I%2fO_Types>`__. + +- `Functions that Operate on + Pathnames <#Functions_that_Operate_on_Pathnames>`__ +- `Functions that Act on File + Descriptors <#Functions_that_Act_on_File_Descriptors>`__ +- `Directory I/O Functions <#Directory_I/O_Functions>`__ +- `Socket Manipulation Functions <#Socket_Manipulation_Functions>`__ +- `Converting Between Host and Network + Addresses <#Converting_Between_Host_and_Network_Addresses>`__ +- `Memory-Mapped I/O Functions <#Memory-Mapped_I/O_Functions>`__ +- `Anonymous Pipe Function <#Anonymous_Pipe_Function>`__ +- `Polling Functions <#Polling_Functions>`__ +- `Pollable Events <#Pollable_Events>`__ +- `Manipulating Layers <#Manipulating_Layers>`__ + +.. _Functions_that_Operate_on_Pathnames: + +Functions that Operate on Pathnames +----------------------------------- + +A file or directory in a file system is specified by its pathname. NSPR +uses Unix-style pathnames, which are null-terminated character strings. +Only the ASCII character set is supported. The forward slash (/) +separates the directories in a pathname. NSPR converts the slashes in a +pathname to the directory separator of the native OS--for example, +backslash (\) on Windows and colon (:) on Mac OS--before passing it to +the native system calls. + +Some file systems also differentiate drives or volumes. + +- :ref:`PR_Open` +- :ref:`PR_Delete` +- :ref:`PR_GetFileInfo` +- :ref:`PR_GetFileInfo64` +- :ref:`PR_Rename` +- :ref:`PR_Access` + + - type :ref:`PRAccessHow` + +.. _Functions_that_Act_on_File_Descriptors: + +Functions that Act on File Descriptors +-------------------------------------- + +- :ref:`PR_Close` +- :ref:`PR_Read` +- :ref:`PR_Write` +- :ref:`PR_Writev` +- :ref:`PR_GetOpenFileInfo` +- :ref:`PR_GetOpenFileInfo64` +- :ref:`PR_Seek` +- :ref:`PR_Seek64` +- :ref:`PR_Available` +- :ref:`PR_Available64` +- :ref:`PR_Sync` +- :ref:`PR_GetDescType` +- :ref:`PR_GetSpecialFD` +- :ref:`PR_CreatePipe` + +.. _Directory_I.2FO_Functions: + +Directory I/O Functions +----------------------- + +- :ref:`PR_OpenDir` +- :ref:`PR_ReadDir` +- :ref:`PR_CloseDir` +- :ref:`PR_MkDir` +- :ref:`PR_RmDir` + +.. _Socket_Manipulation_Functions: + +Socket Manipulation Functions +----------------------------- + +The network programming interface presented here is a socket API modeled +after the popular Berkeley sockets. Differences include the following: + +- The blocking socket functions in NSPR take a timeout parameter. +- Two new functions, :ref:`PR_TransmitFile` and :ref:`PR_AcceptRead`, can + exploit the new system calls of some operating systems for higher + performance. + +List of functions: + +- :ref:`PR_OpenUDPSocket` +- :ref:`PR_NewUDPSocket` +- :ref:`PR_OpenTCPSocket` +- :ref:`PR_NewTCPSocket` +- :ref:`PR_ImportTCPSocket` +- :ref:`PR_Connect` +- :ref:`PR_ConnectContinue` +- :ref:`PR_Accept` +- :ref:`PR_Bind` +- :ref:`PR_Listen` +- :ref:`PR_Shutdown` +- :ref:`PR_Recv` +- :ref:`PR_Send` +- :ref:`PR_RecvFrom` +- :ref:`PR_SendTo` +- :ref:`PR_TransmitFile` +- :ref:`PR_AcceptRead` +- :ref:`PR_GetSockName` +- :ref:`PR_GetPeerName` +- :ref:`PR_GetSocketOption` +- :ref:`PR_SetSocketOption` + +.. _Converting_Between_Host_and_Network_Addresses: + +Converting Between Host and Network Addresses +--------------------------------------------- + +- :ref:`PR_ntohs` +- :ref:`PR_ntohl` +- :ref:`PR_htons` +- :ref:`PR_htonl` +- :ref:`PR_FamilyInet` + +.. _Memory-Mapped_I.2FO_Functions: + +Memory-Mapped I/O Functions +--------------------------- + +The memory-mapped I/O functions allow sections of a file to be mapped to +memory regions, allowing read-write accesses to the file to be +accomplished by normal memory accesses. + +Memory-mapped I/O functions are currently implemented for Unix, Linux, +Mac OS X, and Win32 only. + +- :ref:`PR_CreateFileMap` +- :ref:`PR_MemMap` +- :ref:`PR_MemUnmap` +- :ref:`PR_CloseFileMap` + +.. _Anonymous_Pipe_Function: + +Anonymous Pipe Function +----------------------- + +- :ref:`PR_CreatePipe` + +.. _Polling_Functions: + +Polling Functions +----------------- + +This section describes two of the most important polling functions +provided by NSPR: + +- :ref:`PR_Poll` +- :ref:`PR_GetConnectStatus` + +.. _Pollable_Events: + +Pollable Events +--------------- + +A pollable event is a special kind of file descriptor. The only I/O +operation you can perform on a pollable event is to poll it with the +:ref:`PR_POLL_READ` flag. You cannot read from or write to a pollable +event. + +The purpose of a pollable event is to combine event waiting with I/O +waiting in a single :ref:`PR_Poll` call. Pollable events are implemented +using a pipe or a pair of TCP sockets connected via the loopback +address, therefore setting and/or waiting for pollable events are +expensive operating system calls. Do not use pollable events for general +thread synchronization; use condition variables instead. + +A pollable event has two states: set and unset. Events are not queued, +so there is no notion of an event count. A pollable event is either set +or unset. + +- :ref:`PR_NewPollableEvent` +- :ref:`PR_DestroyPollableEvent` +- :ref:`PR_SetPollableEvent` +- :ref:`PR_WaitForPollableEvent` + +One can call :ref:`PR_Poll` with the :ref:`PR_POLL_READ` flag on a pollable +event. When the pollable event is set, :ref:`PR_Poll` returns the the +:ref:`PR_POLL_READ` flag set in the out_flags. + +.. _Manipulating_Layers: + +Manipulating Layers +------------------- + +File descriptors may be layered. For example, SSL is a layer on top of a +reliable bytestream layer such as TCP. + +Each type of layer has a unique identity, which is allocated by the +runtime. The layer implementor should associate the identity with all +layers of that type. It is then possible to scan the chain of layers and +find a layer that one recognizes and therefore predict that it will +implement a desired protocol. + +A layer can be pushed onto or popped from an existing stack of layers. +The file descriptor of the top layer can be passed to NSPR I/O +functions, which invoke the appropriate version of the I/O methods +polymorphically. + +NSPR defines three identities: + +.. code:: + + #define PR_INVALID_IO_LAYER (PRDescIdentity)-1 + #define PR_TOP_IO_LAYER (PRDescIdentity)-2 + #define PR_NSPR_IO_LAYER (PRDescIdentity)0 + +- :ref:`PR_INVALID_IO_LAYER`: An invalid layer identify (for error + return). +- :ref:`PR_TOP_IO_LAYER`: The identity of the top of the stack. +- :ref:`PR_NSPR_IO_LAYER`: The identity for the layer implemented by NSPR. + +:ref:`PR_TOP_IO_LAYER` may be used as a shorthand for identifying the +topmost layer of an existing stack. For example, the following lines of +code are equivalent: + +| ``rv = PR_PushIOLayer(stack, PR_TOP_IO_LAYER, my_layer);`` +| ``rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), my_layer);`` + +- :ref:`PR_GetUniqueIdentity` +- :ref:`PR_GetNameForIdentity` +- :ref:`PR_GetLayersIdentity` +- :ref:`PR_GetIdentitiesLayer` +- :ref:`PR_GetDefaultIOMethods` +- :ref:`PR_CreateIOLayerStub` +- :ref:`PR_PushIOLayer` +- :ref:`PR_PopIOLayer` diff --git a/docs/nspr/reference/i_o_types.rst b/docs/nspr/reference/i_o_types.rst new file mode 100644 index 0000000000..16ec1bd705 --- /dev/null +++ b/docs/nspr/reference/i_o_types.rst @@ -0,0 +1,105 @@ +This chapter describes the most common NSPR types, enumerations, and +structures used with the functions described in `I/O +Functions <I%2f%2fO_Functions>`__ and `Network +Addresses <Network_Addresses>`__. These include the types used for +system access, normal file I/O, and socket (network) I/O. + +Types unique to a particular function are described with the function +itself. + +For sample code that illustrates basic I/O operations, see `Introduction +to NSPR <Introduction_to_NSPR>`__. + +- `Directory Type <#Directory_Type>`__ +- `File Descriptor Types <#File_Descriptor_Types>`__ +- `File Info Types <#File_Info_Types>`__ +- `Network Address Types <#Network_Address_Types>`__ +- `Types Used with Socket Options + Functions <#Types_Used_with_Socket_Options_Functions>`__ +- `Type Used with Memory-Mapped + I/O <#Type_Used_with_Memory-Mapped_I/O>`__ +- `Offset Interpretation for Seek + Functions <#Offset_Interpretation_for_Seek_Functions>`__ + +.. _Directory_Type: + +Directory Type +-------------- + + - :ref:`PRDir` + +.. _File_Descriptor_Types: + +File Descriptor Types +--------------------- + +NSPR represents I/O objects, such as open files and sockets, by file +descriptors of type :ref:`PRFileDesc`. This section introduces +:ref:`PRFileDesc` and related types. + + - :ref:`PRFileDesc` + - :ref:`PRIOMethods` + - :ref:`PRFilePrivate` + - :ref:`PRDescIdentity` + +Note that the NSPR documentation follows the Unix convention of using +the term\ *files* to refer to many kinds of I/O objects. To refer +specifically to the files in a file system (that is, disk files), this +documentation uses the term\ *normal files*. + +:ref:`PRFileDesc` has an object-oriented flavor. An I/O function on a +:ref:`PRFileDesc` structure is carried out by invoking the corresponding +"method" in the I/O methods table (a structure of type :ref:`PRIOMethods`) +of the :ref:`PRFileDesc` structure (the "object"). Different kinds of I/O +objects (such as files and sockets) have different I/O methods tables, +thus implementing different behavior in response to the same I/O +function call. + +NSPR supports the implementation of layered I/O. Each layer is +represented by a :ref:`PRFileDesc` structure, and the :ref:`PRFileDesc` +structures for the layers are chained together. Each :ref:`PRFileDesc` +structure has a field (of type :ref:`PRDescIdentity`) to identify itself in +the layers. For example, the Netscape implementation of the Secure +Sockets Layer (SSL) protocol is implemented as an I/O layer on top of +NSPR's socket layer. + +.. _File_Info_Types: + +File Info Types +--------------- + + - :ref:`PRFileInfo` + - :ref:`PRFileInfo64` + - :ref:`PRFileType` + +.. _Network_Address_Types: + +Network Address Types +--------------------- + + - :ref:`PRNetAddr` + - :ref:`PRIPv6Addr` + +.. _Types_Used_with_Socket_Options_Functions: + +Types Used with Socket Options Functions +---------------------------------------- + + - :ref:`PRSocketOptionData` + - :ref:`PRSockOption` + - :ref:`PRLinger` + - :ref:`PRMcastRequest` + +.. _Type_Used_with_Memory-Mapped_I.2FO: + +Type Used with Memory-Mapped I/O +-------------------------------- + + - :ref:`PRFileMap` + +.. _Offset_Interpretation_for_Seek_Functions: + +Offset Interpretation for Seek Functions +---------------------------------------- + + - :ref:`PRSeekWhence` diff --git a/docs/nspr/reference/index.rst b/docs/nspr/reference/index.rst new file mode 100644 index 0000000000..8502db1e33 --- /dev/null +++ b/docs/nspr/reference/index.rst @@ -0,0 +1,289 @@ +NSPR API Reference +================== + +.. toctree:: + :maxdepth: 2 + +Introduction to NSPR +-------------------- + +- :ref:`NSPR_Naming_Conventions` +- :ref:`NSPR_Threads` + + - :ref:`Thread_Scheduling` + + - :ref:`Setting_Thread_Priorities` + - :ref:`Preempting_Threads` + - :ref:`Interrupting_Threads` + +- :ref:`NSPR_Thread_Synchronization` + + - :ref:`Locks_and_Monitors` + - :ref:`Condition_Variables` + +- :ref:`NSPR_Sample_Code` + +NSPR Types +---------- + +- :ref:`Calling_Convention_Types` +- :ref:`Algebraic_Types` + + - :ref:`8-.2C_16-.2C_and_32-bit_Integer_Types` + + - :ref:`Signed_Integers` + - :ref:`Unsigned_Integers` + + - :ref:`64-bit_Integer_Types` + - :ref:`Floating-Point_Number_Type` + - :ref:`Native_OS_Integer_Types` + +- :ref:`Miscellaneous_Types` + + - :ref:`Size_Type` + - :ref:`Pointer_Difference_Types` + - :ref:`Boolean_Types` + - :ref:`Status_Type_for_Return_Values` + +Threads +------- + +- :ref:`Threading_Types_and_Constants` +- :ref:`Threading_Functions` + + - :ref:`Creating.2C_Joining.2C_and_Identifying_Threads` + - :ref:`Controlling_Thread_Priorities` + - :ref:`Controlling_Per-Thread_Private_Data` + - :ref:`Interrupting_and_Yielding` + - :ref:`Setting_Global_Thread_Concurrency` + - :ref:`Getting_a_Thread.27s_Scope` + +Process Initialization +---------------------- + +- :ref:`Identity_and_Versioning` + + - :ref:`Name_and_Version_Constants` + +- :ref:`Initialization_and_Cleanup` +- :ref:`Module_Initialization` + +Locks +----- + +- :ref:`Lock_Type` +- :ref:`Lock_Functions` + +Condition_Variables +------------------- + +- :ref:`Condition_Variable_Type` +- :ref:`Condition_Variable_Functions` + +Monitors +-------- + +- :ref:`Monitor_Type` +- :ref:`Monitor_Functions` + +Cached Monitors +--------------- + +- :ref:`Cached_Monitors_Functions` + +I/O Types +--------- + +- :ref:`Directory_Type` +- :ref:`File_Descriptor_Types` +- :ref:`File_Info_Types` +- :ref:`Network_Address_Types` +- :ref:`Types_Used_with_Socket_Options_Functions` +- :ref:`Type_Used_with_Memory-Mapped_I.2FO` +- :ref:`Offset_Interpretation_for_Seek_Functions` + +I/O Functions +------------- + +- :ref:`Functions_that_Operate_on_Pathnames` +- :ref:`Functions_that_Act_on_File_Descriptors` +- :ref:`Directory_I.2FO_Functions` +- :ref:`Socket_Manipulation_Functions` +- :ref:`Converting_Between_Host_and_Network_Addresses` +- :ref:`Memory-Mapped_I.2FO_Functions` +- :ref:`Anonymous_Pipe_Function` +- :ref:`Polling_Functions` +- :ref:`Pollable_Events` +- :ref:`Manipulating_Layers` + +Network Addresses +----------------- + +- :ref:`Network_Address_Types_and_Constants` +- :ref:`Network_Address_Functions` + +Atomic Operations +----------------- + +- :ref:`PR_AtomicIncrement` +- :ref:`PR_AtomicDecrement` +- :ref:`PR_AtomicSet` + +Interval Timing +--------------- + +- :ref:`Interval_Time_Type_and_Constants` +- :ref:`Interval_Functions` + +Date and Time +------------- + +- :ref:`Types_and_Constants` +- :ref:`Time_Parameter_Callback_Functions` +- :ref:`Functions` + +Memory_Management Operations +---------------------------- + +- :ref:`Memory_Allocation_Functions` +- :ref:`Memory_Allocation_Macros` + +String Operations +----------------- + +- :ref:`PL_strlen` +- :ref:`PL_strcpy` +- :ref:`PL_strdup` +- :ref:`PL_strfree` + +Floating Point Number to String Conversion +------------------------------------------ + +- :ref:`PR_strtod` +- :ref:`PR_dtoa` +- :ref:`PR_cnvtf` + +Linked Lists +------------ + +- :ref:`Linked_List_Types` + + - :ref:`PRCList` + +- :ref:`Linked_List_Macros` + + - :ref:`PR_INIT_CLIST` + - :ref:`PR_INIT_STATIC_CLIST` + - :ref:`PR_APPEND_LINK` + - :ref:`PR_INSERT_LINK` + - :ref:`PR_NEXT_LINK` + - :ref:`PR_PREV_LINK` + - :ref:`PR_REMOVE_LINK` + - :ref:`PR_REMOVE_AND_INIT_LINK` + - :ref:`PR_INSERT_BEFORE` + - :ref:`PR_INSERT_AFTER` + +Dynamic Library Linking +----------------------- + +- :ref:`Library_Linking_Types` + + - :ref:`PRLibrary` + - :ref:`PRStaticLinkTable` + +- :ref:`Library_Linking_Functions` + + - :ref:`PR_SetLibraryPath` + - :ref:`PR_GetLibraryPath` + - :ref:`PR_GetLibraryName` + - :ref:`PR_FreeLibraryName` + - :ref:`PR_LoadLibrary` + - :ref:`PR_UnloadLibrary` + - :ref:`PR_FindSymbol` + - :ref:`PR_FindSymbolAndLibrary` + - :ref:`Finding_Symbols_Defined_in_the_Main_Executable_Program` + +- :ref:`Platform_Notes` + + - :ref:`Dynamic_Library_Search_Path` + - :ref:`Exporting_Symbols_from_the_Main_Executable_Program` + +Process Management and Interprocess Communication +------------------------------------------------- + +- :ref:`Process_Management_Types_and_Constants` + + - :ref:`PRProcess` + - :ref:`PRProcessAttr` + +- :ref:`Process_Management_Functions` + + - :ref:`Setting_the_Attributes_of_a_New_Process` + - :ref:`Creating_and_Managing_Processes` + +Logging +------- + +- :ref:`Conditional_Compilation_and_Execution` +- :ref:`Log_Types_and_Variables` + + - :ref:`PRLogModuleInfo` + - :ref:`PRLogModuleLevel` + - :ref:`NSPR_LOG_MODULES` + - :ref:`NSPR_LOG_FILE` + +- :ref:`Logging_Functions_and_Macros` + + - :ref:`PR_NewLogModule` + - :ref:`PR_SetLogFile` + - :ref:`PR_SetLogBuffering` + - :ref:`PR_LogPrint` + - :ref:`PR_LogFlush` + - :ref:`PR_LOG_TEST` + - :ref:`PR_LOG` + - :ref:`PR_Assert` + - :ref:`PR_ASSERT` + - :ref:`PR_NOT_REACHED` + +- :ref:`Use_Example` + +Named Shared Memory +------------------- + +- :ref:`Shared_Memory_Protocol` +- :ref:`Named_Shared_Memory_Functions` + +Anonymous Shared_Memory +----------------------- + +- :ref:`Anonymous_Memory_Protocol` +- :ref:`Anonymous_Shared_Memory_Functions` + +IPC Semaphores +-------------- + +- :ref:`IPC_Semaphore_Functions` + +Thread Pools +------------ + +- :ref:`Thread_Pool_Types` +- :ref:`Thread_Pool_Functions` + +Random Number Generator +----------------------- + +- :ref:`Random_Number_Generator_Function` + +Hash Tables +----------- + +- :ref:`Hash_Table_Types_and_Constants` +- :ref:`Hash_Table_Functions` + +NSPR Error Handling +------------------- + +- :ref:`Error_Type` +- :ref:`Error_Functions` +- :ref:`Error_Codes` diff --git a/docs/nspr/reference/interval_timing.rst b/docs/nspr/reference/interval_timing.rst new file mode 100644 index 0000000000..2d19d6004b --- /dev/null +++ b/docs/nspr/reference/interval_timing.rst @@ -0,0 +1,72 @@ +NSPR defines a platform-dependent type, :ref:`PRIntervalTime`, for timing +intervals of fewer than approximately 6 hours. This chapter describes +:ref:`PRIntervalTime` and the functions that allow you to use it for timing +purposes: + +- `Interval Time Type and + Constants <#Interval_Time_Type_and_Constants>`__ +- `Interval Functions <#Interval_Functions>`__ + +.. _Interval_Time_Type_and_Constants: + +Interval Time Type and Constants +-------------------------------- + +All timed functions in NSPR require a parameter that depicts the amount +of time allowed to elapse before the operation is declared failed. The +type of such arguments is :ref:`PRIntervalTime`. Such parameters are common +in NSPR functions such as those used for I/O operations and operations +on condition variables. + +NSPR 2.0 provides interval times that are efficient in terms of +performance and storage requirements. Conceptually, they are based on +free-running counters that increment at a fixed rate without possibility +of outside influence (as might be observed if one was using a +time-of-day clock that gets reset due to some administrative action). +The counters have no fixed epoch and have a finite period. To make use +of these counters, the application must declare a point in time, the +epoch, and an amount of time elapsed since that **epoch**, the +**interval**. In almost all cases the epoch is defined as the value of +the interval timer at the time it was sampled. + + - :ref:`PRIntervalTime` + +.. _Interval_Functions: + +Interval Functions +------------------ + +Interval timing functions are divided into three groups: + +- `Getting the Current Interval and Ticks Per + Second <#Getting_the_Current_Interval_and_Ticks_Per_Second>`__ +- `Converting Standard Clock Units to Platform-Dependent + Intervals <#Converting_Standard_Clock_Units_to_Platform-Dependent_Intervals>`__ +- `Converting Platform-Dependent Intervals to Standard Clock + Units <#Converting_Platform-Dependent_Intervals_to_Standard_Clock_Units>`__ + +.. _Getting_the_Current_Interval_and_Ticks_Per_Second: + +Getting the Current Interval and Ticks Per Second +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_IntervalNow` + - :ref:`PR_TicksPerSecond` + +.. _Converting_Standard_Clock_Units_to_Platform-Dependent_Intervals: + +Converting Standard Clock Units to Platform-Dependent Intervals +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_SecondsToInterval` + - :ref:`PR_MillisecondsToInterval` + - :ref:`PR_MicrosecondsToInterval` + +.. _Converting_Platform-Dependent_Intervals_to_Standard_Clock_Units: + +Converting Platform-Dependent Intervals to Standard Clock Units +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_IntervalToSeconds` + - :ref:`PR_IntervalToMilliseconds` + - :ref:`PR_IntervalToMicroseconds` diff --git a/docs/nspr/reference/introduction_to_nspr.rst b/docs/nspr/reference/introduction_to_nspr.rst new file mode 100644 index 0000000000..f1187d4ebe --- /dev/null +++ b/docs/nspr/reference/introduction_to_nspr.rst @@ -0,0 +1,408 @@ +Introduction to NSPR +==================== + +The Netscape Portable Runtime (NSPR) API allows compliant applications +to use system facilities such as threads, thread synchronization, I/O, +interval timing, atomic operations, and several other low-level services +in a platform-independent manner. This chapter introduces key NSPR +programming concepts and illustrates them with sample code. + +NSPR does not provide a platform for porting existing code. It must be +used from the beginning of a software project. + +.. _NSPR_Naming_Conventions: + +NSPR Naming Conventions +----------------------- + +Naming of NSPR types, functions, and macros follows the following +conventions: + +- Types exported by NSPR begin with ``PR`` and are followed by + intercap-style declarations, like this: :ref:`PRInt`, :ref:`PRFileDesc` +- Function definitions begin with ``PR_`` and are followed by + intercap-style declarations, like this: :ref:`PR_Read``, + :ref:`PR_JoinThread`` +- Preprocessor macros begin with the letters ``PR`` and are followed by + all uppercase characters separated with the underscore character + (``_``), like this: :ref:`PR_BYTES_PER_SHORT`, :ref:`PR_EXTERN` + +.. _NSPR_Threads: + +NSPR Threads +------------ + +NSPR provides an execution environment that promotes the use of +lightweight threads. Each thread is an execution entity that is +scheduled independently from other threads in the same process. A thread +has a limited number of resources that it truly owns. These resources +include the thread stack and the CPU register set (including PC). + +To an NSPR client, a thread is represented by a pointer to an opaque +structure of type :ref:`PRThread``. A thread is created by an explicit +client request and remains a valid, independent execution entity until +it returns from its root function or the process abnormally terminates. +(:ref:`PRThread` and functions for creating and manipulating threads are +described in detail in `Threads <Threads>`__.) + +NSPR threads are lightweight in the sense that they are cheaper than +full-blown processes, but they are not free. They achieve the cost +reduction by relying on their containing process to manage most of the +resources that they access. This, and the fact that threads share an +address space with other threads in the same process, makes it important +to remember that *threads are not processes* . + +NSPR threads are scheduled in two separate domains: + +- **Local threads** are scheduled within a process only and are handled + entirely by NSPR, either by completely emulating threads on each host + operating system (OS) that doesn't support threads, or by using the + threading facilities of each host OS that does support threads to + emulate a relatively large number of local threads by using a + relatively small number of native threads. + +- **Global threads** are scheduled by the host OS--not by NSPR--either + within a process or across processes on the entire host. Global + threads correspond to native threads on the host OS. + +NSPR threads can also be either user threads or system threads. NSPR +provides a function, :ref:`PR_Cleanup`, that synchronizes process +termination. :ref:`PR_Cleanup` waits for the last user thread to exit +before returning, whereas it ignores system threads when determining +when a process should exit. This arrangement implies that a system +thread should not have volatile data that needs to be safely stored +away. + +Priorities for NSPR threads are based loosely on hints provided by the +client and sometimes constrained by the underlying operating system. +Therefore, priorities are not rigidly defined. For more information, see +`Thread Scheduling <#Thread_Scheduling>`__. + +In general, it's preferable to create local user threads with normal +priority and let NSPR take care of the details as appropriate for each +host OS. It's usually not necessary to create a global thread explicitly +unless you are planning to port your code only to platforms that provide +threading services with which you are familiar or unless the thread will +be executing code that might directly call blocking OS functions. + +Threads can also have "per-thread-data" attached to them. Each thread +has a built-in per-thread error number and error string that are updated +when NSPR operations fail. It's also possible for NSPR clients to define +their own per-thread-data. For details, see `Controlling Per-Thread +Private Data <Threads#Controlling_Per-Thread_Private_Data>`__. + +.. _Thread_Scheduling: + +Thread Scheduling +~~~~~~~~~~~~~~~~~ + +NSPR threads are scheduled by priority and can be preempted or +interrupted. The sections that follow briefly introduce the NSPR +approach to these three aspects of thread scheduling. + +- `Setting Thread Priorities <#Setting_Thread_Priorities>`__ +- `Preempting Threads <#Preempting_Threads>`__ +- `Interrupting Threads <#Interrupting_Threads>`__ + +For reference information on the NSPR API used for thread scheduling, +see `Threads <Threads>`__. + +.. _Setting_Thread_Priorities: + +Setting Thread Priorities +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The host operating systems supported by NSPR differ widely in the +mechanisms they use to support thread priorities. In general, an NSPR +thread of higher priority has a statistically better chance of running +relative to threads of lower priority. However, because of the multiple +strategies to provide execution vehicles for threads on various host +platforms, priorities are not a clearly defined abstraction in NSPR. At +best they are intended to specify a preference with respect to the +amount of CPU time that a higher-priority thread might expect relative +to a lower-priority thread. This preference is still subject to resource +availability, and must not be used in place of proper synchronization. +For more information on thread synchronization, see `NSPR Thread +Synchronization <#NSPR_Thread_Synchronization>`__. + +The issue is further muddied by inconsistent offerings from OS vendors +regarding the priority of their kernel-supported threads. NSPR assumes +that the priorities of global threads are not manageable, but that the +host OS will perform some sort of fair scheduling. It's usually +preferable to create local user threads with normal priority and let +NSPR and the host take care of the details. + +In some NSPR configurations, there may be an arbitrary (and perhaps +large) number of local threads being supported by a more limited number +of **virtual processors** (an internal application of global threads). +In such situations, each virtual processor will have some number of +local threads associated with it, though exactly which local threads and +how many may vary over time. NSPR guarantees that for each virtual +processor the highest-priority, schedulable local thread is the one +executing. This thread implementation strategy is referred to as the **M +x N model.** + +.. _Preempting_Threads: + +Preempting Threads +^^^^^^^^^^^^^^^^^^ + +Preemption is the act of taking control away from a ready thread at an +arbitrary point and giving control to another appropriate thread. It +might be viewed as taking the executing thread and adding it to the end +of the ready queue for its appropriate priority, then simply running the +scheduling algorithm to find the most appropriate thread. The chosen +thread may be of higher priority, of the same priority, or even the same +thread. It will not be a thread of lower priority. + +Some operating systems cannot be made preemptible (for example, Mac OS +and Win 16). This puts them at some risk in supporting arbitrary code, +even if the code is interpreted (Java). Other systems are not +thread-aware, and their runtime libraries not thread-safe (most versions +of Unix). These systems can support local level thread abstractions that +can be made preemptible, but run the risk of library corruption +(``libc``). Still other operating systems have a native notion of +threads, and their libraries are thread-aware and support locking. +However, if local threads are also present, and they are preemptible, +they are subject to deadlock. At this time, the only safe solutions are +to turn off preemption (a runtime decision) or to preempt global threads +only. + +.. _Interrupting_Threads: + +Interrupting Threads +^^^^^^^^^^^^^^^^^^^^ + +NSPR threads are interruptible, with some constraints and +inconsistencies. + +To interrupt a thread, the caller of :ref:`PR_Interrupt` must have the NSPR +reference to the target thread (:ref:`PRThread`). When the target is +interrupted, it is rescheduled from the point at which it was blocked, +with a status error indicating that it was interrupted. NSPR recognizes +only two areas where a thread may be interrupted: waiting on a condition +variable and waiting on I/O. In the latter case, interruption does +cancel the I/O operation. In neither case does being interrupted imply +the demise of the thread. + +.. _NSPR_Thread_Synchronization: + +NSPR Thread Synchronization +--------------------------- + +Thread synchronization has two aspects: locking and notification. +Locking prevents access to some resource, such as a piece of shared +data: that is, it enforces mutual exclusion. Notification involves +passing synchronization information among cooperating threads. + +In NSPR, a **mutual exclusion lock** (or **mutex**) of type :ref:`PRLock` +controls locking, and associated **condition variables** of type +:ref:`PRCondVar` communicate changes in state among threads. When a +programmer associates a mutex with an arbitrary collection of data, the +mutex provides a protective **monitor** around the data. + +.. _Locks_and_Monitors: + +Locks and Monitors +~~~~~~~~~~~~~~~~~~ + +In general, a monitor is a conceptual entity composed of a mutex, one or +more condition variables, and the monitored data. Monitors in this +generic sense should not be confused with the monitor type used in Java +programming. In addition to :ref:`PRLock`, NSPR provides another mutex +type, :ref:`PRMonitor`, which is reentrant and can have only one associated +condition variable. :ref:`PRMonitor` is intended for use with Java and +reflects the Java approach to thread synchronization. + +To access the data in the monitor, the thread performing the access must +hold the mutex, also described as being "in the monitor." Mutual +exclusion guarantees that only one thread can be in the monitor at a +time and that no thread may observe or modify the monitored data without +being in the monitor. + +Monitoring is about protecting data, not code. A **monitored invariant** +is a Boolean expression over the monitored data. The expression may be +false only when a thread is in the monitor (holding the monitor's +mutex). This requirement implies that when a thread first enters the +monitor, an evaluation of the invariant expression must yield a +``true``. The thread must also reinstate the monitored invariant before +exiting the monitor. Therefore, evaluation of the expression must also +yield a true at that point in execution. + +A trivial example might be as follows. Suppose an object has three +values, ``v1``, ``v2``, and ``sum``. The invariant is that the third +value is the sum of the other two. Expressed mathematically, the +invariant is ``sum = v1 + v2``. Any modification of ``v1`` or ``v2`` +requires modification of ``sum``. Since that is a complex operation, it +must be monitored. Furthermore, any type of access to ``sum`` must also +be monitored to ensure that neither ``v1`` nor ``v2`` are in flux. + +.. note:: + + **Note**: Evaluation of the invariant expression is a conceptual + requirement and is rarely done in practice. It is valuable to + formally define the expression during design, write it down, and + adhere to it. It is also useful to implement the expression during + development and test it where appropriate. The thread makes an + absolute assertion of the expression's evaluation both on entering + and on exiting the monitor. + +Acquiring a lock is a synchronous operation. Once the lock primitive is +called, the thread returns only when it has acquired the lock. Should +another thread (or the same thread) already have the lock held, the +calling thread blocks, waiting for the situation to improve. That +blocked state is not interruptible, nor is it timed. + +.. _Condition_Variables: + +Condition Variables +~~~~~~~~~~~~~~~~~~~ + +Condition variables facilitate communication between threads. The +communication available is a semantic-free notification whose context +must be supplied by the programmer. Conditions are closely associated +with a single monitor. + +The association between a condition and a monitor is established when a +condition variable is created, and the association persists for the life +of the condition variable. In addition, a static association exists +between the condition and some data within the monitor. This data is +what will be manipulated by the program under the protection of the +monitor. A thread may wait on notification of a condition that signals +changes in the state of the associated data. Other threads may notify +the condition when changes occur. + +Condition variables are always monitored. The relevant operations on +conditions are always performed from within the monitor. They are used +to communicate changes in the state of the monitored data (though still +preserving the monitored invariant). Condition variables allow one or +more threads to wait for a predetermined condition to exist, and they +allow another thread to notify them when the condition occurs. Condition +variables themselves do not carry the semantics of the state change, but +simply provide a mechanism for indicating that something has changed. It +is the programmer's responsibility to associate a condition with the +state of the data. + +A thread may be designed to wait for a particular situation to exist in +some monitored data. Since the nature of the situation is not an +attribute of the condition, the program must test that itself. Since +this testing involves the monitored data, it must be done from within +the monitor. The wait operation atomically exits the monitor and blocks +the calling thread in a waiting condition state. When the thread is +resumed after the wait, it will have reentered the monitor, making +operations on the data safe. + +There is a subtle interaction between the thread(s) waiting on a +condition and those notifying it. The notification must take place +within a monitor--the same monitor that protects the data being +manipulated by the notifier. In pseudocode, the sequence looks like +this: + +.. code:: + + enter(monitor); + ... manipulate the monitored data + notify(condition); + exit(monitor); + +Notifications to a condition do not accumulate. Nor is it required that +any thread be waiting on a condition when the notification occurs. The +design of the code that waits on a condition must take these facts into +account. Therefore, the pseudocode for the waiting thread might look +like this: + +.. code:: + + enter(monitor) + while (!expression) wait(condition); + ... manipulate monitored data + exit(monitor); + +The need to evaluate the Boolean expression again after rescheduling +from a wait may appear unnecessary, but it is vital to the correct +execution of the program. The notification promotes a thread waiting on +a condition to a ready state. When that thread actually gets scheduled +is determined by the thread scheduler and cannot be predicted. If +multiple threads are actually processing the notifications, one or more +of them could be scheduled ahead of the one explicitly promoted by the +notification. One such thread could enter the monitor and perform the +work indicated by the notification, and exit. In this case the thread +would resume from the wait only to find that there's nothing to do. + +For example, suppose the defined rule of a function is that it should +wait until there is an object available and that it should return a +reference to that object. Writing the code as follows could potentially +return a null reference, violating the invariant of the function: + +.. code:: + + void *dequeue() + { + void *db; + enter(monitor); + if ((db = delink()) == null) + { + wait(condition); + db = delink(); + } + exit(monitor); + return db; + } + +The same function would be more appropriately written as follows: + +.. code:: + + void *dequeue() + { + void *db; + enter(monitor); + while ((db = delink()) == null) + wait(condition); + exit(monitor); + return db; + } + +.. note:: + + **Caution**: The semantics of :ref:`PR_WaitCondVar` assume that the + monitor is about to be exited. This assumption implies that the + monitored invariant must be reinstated before calling + :ref:`PR_WaitCondVar`. Failure to do this will cause subtle but painful + bugs. + +To modify monitored data safely, a thread must be in the monitor. Since +no other thread may modify or (in most cases) even observe the protected +data from outside the monitor, the thread can safely make any +modifications needed. When the changes have been completed, the thread +notifies the condition associated with the data and exits the monitor +using :ref:`PR_NotifyCondVar`. Logically, each such notification promotes +one thread that was waiting on the condition to a ready state. An +alternate form of notification (:ref:`PR_NotifyAllCondVar`) promotes all +threads waiting on a condition to the ready state. If no threads were +waiting, the notification is a no-op. + +Waiting on a condition variable is an interruptible operation. Another +thread could target the waiting thread and issue a :ref:`PR_Interrupt`, +causing a waiting thread to resume. In such cases the return from the +wait operation indicates a failure and definitively indicates that the +cause of the failure is an interrupt. + +A call to :ref:`PR_WaitCondVar` may also resume because the interval +specified on the wait call has expired. However, this fact cannot be +unambiguously delivered, so no attempt is made to do so. If the logic of +a program allows for timing of waits on conditions, then the clock must +be treated as part of the monitored data and the amount of time elapsed +re-asserted when the call returns. Philosophically, timeouts should be +treated as explicit notifications, and therefore require the testing of +the monitored data upon resumption. + +.. _NSPR_Sample_Code: + +NSPR Sample Code +---------------- + +The documents linked here present two sample programs, including +detailed annotations: ``layer.html`` and ``switch.html``. In addition to +these annotated HTML versions, the same samples are available in pure +source form. diff --git a/docs/nspr/reference/ipc_semaphores.rst b/docs/nspr/reference/ipc_semaphores.rst new file mode 100644 index 0000000000..2391346c9c --- /dev/null +++ b/docs/nspr/reference/ipc_semaphores.rst @@ -0,0 +1,23 @@ +This chapter describes the NSPR API for using interprocess communication +semaphores. + +NSPR provides an interprocess communication mechanism using a counting +semaphore model similar to that which is provided in Unix and Windows +platforms. + +.. note:: + + **Note:** See also `Named Shared Memory <Named_Shared_Memory>`__ + +- `IPC Semaphore Functions <#IPC_Semaphore_Functions>`__ + +.. _IPC_Semaphore_Functions: + +IPC Semaphore Functions +----------------------- + + - :ref:`PR_OpenSemaphore` + - :ref:`PR_WaitSemaphore` + - :ref:`PR_PostSemaphore` + - :ref:`PR_CloseSemaphore` + - :ref:`PR_DeleteSemaphore` diff --git a/docs/nspr/reference/linked_lists.rst b/docs/nspr/reference/linked_lists.rst new file mode 100644 index 0000000000..696d112cd7 --- /dev/null +++ b/docs/nspr/reference/linked_lists.rst @@ -0,0 +1,36 @@ +This chapter describes the NSPR API for managing linked lists. The API +is a set of macros for initializing a circular (doubly linked) list, +inserting and removing elements from the list. The macros are not thread +safe. The caller must provide for mutually-exclusive access to the list, +and for the nodes being added and removed from the list. + +- `Linked List Types <#Linked_List_Types>`__ +- `Linked List Macros <#Linked_List_Macros>`__ + +.. _Linked_List_Types: + +Linked List Types +----------------- + +The :ref:`PRCList` type represents a circular linked list. + +.. _Linked_List_Macros: + +Linked List Macros +------------------ + +Macros that create and operate on linked lists are: + + - :ref:`PR_INIT_CLIST` + - :ref:`PR_INIT_STATIC_CLIST` + - :ref:`PR_APPEND_LINK` + - :ref:`PR_INSERT_LINK` + - :ref:`PR_NEXT_LINK` + - :ref:`PR_PREV_LINK` + - :ref:`PR_REMOVE_LINK` + - :ref:`PR_REMOVE_AND_INIT_LINK` + - :ref:`PR_INSERT_BEFORE` + - :ref:`PR_INSERT_AFTER` + - :ref:`PR_CLIST_IS_EMPTY` + - :ref:`PR_LIST_HEAD` + - :ref:`PR_LIST_TAIL` diff --git a/docs/nspr/reference/locks.rst b/docs/nspr/reference/locks.rst new file mode 100644 index 0000000000..5ab57102c1 --- /dev/null +++ b/docs/nspr/reference/locks.rst @@ -0,0 +1,42 @@ +This chapter describes the NSPR API for creation and manipulation of a +mutex of type :ref:`PRLock`. + +- `Lock Type <#Lock_Type>`__ +- `Lock Functions <#Lock_Functions>`__ + +In NSPR, a mutex of type :ref:`PRLock` controls locking, and associated +condition variables communicate changes in state among threads. When a +programmer associates a mutex with an arbitrary collection of data, the +mutex provides a protective monitor around the data. + +In general, a monitor is a conceptual entity composed of a mutex, one or +more condition variables, and the monitored data. Monitors in this +generic sense should not be confused with monitors used in Java +programming. In addition to :ref:`PRLock`, NSPR provides another mutex +type, :ref:`PRMonitor`, which is reentrant and can have only one associated +condition variable. :ref:`PRMonitor` is intended for use with Java and +reflects the Java approach to thread synchronization. + +For an introduction to NSPR thread synchronization, including locks and +condition variables, see `Introduction to +NSPR <Introduction_to_NSPR>`__. + +For reference information on NSPR condition variables, see `Condition +Variables <Condition_Variables>`__. + +.. _Lock_Type: + +Lock Type +--------- + + - :ref:`PRLock` + +.. _Lock_Functions: + +Lock Functions +-------------- + + - :ref:`PR_NewLock` creates a new lock object. + - :ref:`PR_DestroyLock` destroys a specified lock object. + - :ref:`PR_Lock` locks a specified lock object. + - :ref:`PR_Unlock` unlocks a specified lock object. diff --git a/docs/nspr/reference/logging.rst b/docs/nspr/reference/logging.rst new file mode 100644 index 0000000000..ba91ad39a6 --- /dev/null +++ b/docs/nspr/reference/logging.rst @@ -0,0 +1,116 @@ +NSPR Logging +============ + +This chapter describes the global functions you use to perform logging. +NSPR provides a set of logging functions that conditionally write +``printf()`` style strings to the console or to a log file. NSPR uses +this facility itself for its own development debugging purposes. + +You can select events to be logged by module or level. A module is a +user-defined class of log events. A level is a numeric value that +indicates the seriousness of the event to be logged. You can combine +module and level criteria to get highly selective logging. + +NSPR also provides "assert"-style macros and functions to aid in +application debugging. + +- `Conditional Compilation and + Execution <#Conditional_Compilation_and_Execution>`__ +- `Log Types and Variables <#Log_Types_and_Variables>`__ +- `Logging Functions and Macros <#Logging_Functions_and_Macros>`__ +- `Use Example <#Use_Example>`__ + +.. _Conditional_Compilation_and_Execution: + +Conditional Compilation and Execution +------------------------------------- + +NSPR's logging facility is conditionally compiled in and enabled for +applications using it. These controls are platform dependent. Logging is +not compiled in for the Win16 platform. Logging is compiled into the +NSPR debug builds; logging is not compiled into the NSPR optimized +builds. The compile time ``#define`` values ``DEBUG`` or +``FORCE_PR_LOG`` enable NSPR logging for application programs. + +To enable NSPR logging and/or the debugging aids in your application, +compile using the NSPR debug build headers and runtime. Set one of the +compile-time defines when you build your application. + +Execution-time control of NSPR's logging uses two environment variables. +These variables control which modules and levels are logged as well as +the file name of the log file. By default, no logging is enabled at +execution time. + +.. _Log_Types_and_Variables: + +Log Types and Variables +----------------------- + +Two types supporting NSPR logging are exposed in the API: + + - :ref:`PRLogModuleInfo` + - :ref:`PRLogModuleLevel` + +Two environment variables control the behavior of logging at execution +time: + + - :ref:`NSPR_LOG_MODULES` + - :ref:`NSPR_LOG_FILE` + +.. _Logging_Functions_and_Macros: + +Logging Functions and Macros +---------------------------- + +The functions and macros for logging are: + + - :ref:`PR_NewLogModule` + - :ref:`PR_SetLogFile` + - :ref:`PR_SetLogBuffering` + - :ref:`PR_LogPrint` + - :ref:`PR_LogFlush` + - :ref:`PR_LOG_TEST` + - :ref:`PR_LOG` + - :ref:`PR_Assert` + - :ref:`PR_STATIC_ASSERT` (new in NSPR 4.6.6XXX this hasn't been released + yet; the number is a logical guess) + - :ref:`PR_NOT_REACHED` + +.. note:: + + The above documentation has not been ported to MDN yet, see + http://www-archive.mozilla.org/projects/nspr/reference/html/prlog.html#25338. + +.. _Use_Example: + +Use Example +----------- + +The following sample code fragment demonstrates use of the logging and +debugging aids. + +- Compile the program with DEBUG defined. +- Before running the compiled program, set the environment variable + NSPR_LOG_MODULES to userStuff:5 + +.. code:: + + static void UserLogStuff( void ) + { + PRLogModuleInfo *myLM; + PRIntn i; + + PR_STATIC_ASSERT(5 > 4); /* NSPR 4.6.6 or newer */ + + myLM = PR_NewLogModule( "userStuff" ); + PR_ASSERT( myLM ); + + PR_LOG( myLM, PR_LOG_NOTICE, ("Log a Notice %d\n", 999 )); + for (i = 0; i < 10 ; i++ ) + { + PR_LOG( myLM, PR_LOG_DEBUG, ("Log Debug number: %d\n", i)); + PR_Sleep( 500 ); + } + PR_LOG( myLM, PR_LOG_NOTICE, "That's all folks\n"); + + } /* end UserLogStuff() */ diff --git a/docs/nspr/reference/long_long_(64-bit)_integers.rst b/docs/nspr/reference/long_long_(64-bit)_integers.rst new file mode 100644 index 0000000000..d0a747e7ed --- /dev/null +++ b/docs/nspr/reference/long_long_(64-bit)_integers.rst @@ -0,0 +1,32 @@ +Long Long integers +================== + +This chapter describes the global functions you use to perform 64-bit +integer operations. The functions define a portable API that can be used +reliably in any environment. Where 64-bit integers are desired, use of +NSPR's implementation is recommended to ensure cross-platform +compatibility. + +Most of the 64-bit integer operations are implemented as macros. The +specific implementation of each macro depends on whether the compiler +for the target platform supports 64-bit integers. For a specific target +platform, if 64-bit integers are supported for that platform, define +``HAVE_LONG_LONG`` at compile time. + +.. _64-Bit_Integer_Types: + +64-Bit Integer Types +~~~~~~~~~~~~~~~~~~~~ + +NSPR provides two types to represent 64-bit integers: + +- :ref:`PRInt64` +- :ref:`PRUint64` + +.. _64-Bit_Integer_Functions: + +64-Bit Integer Functions +~~~~~~~~~~~~~~~~~~~~~~~~ + +The API defined for the 64-bit integer functions is consistent across +all supported platforms. diff --git a/docs/nspr/reference/memory_management_operations.rst b/docs/nspr/reference/memory_management_operations.rst new file mode 100644 index 0000000000..1f61020685 --- /dev/null +++ b/docs/nspr/reference/memory_management_operations.rst @@ -0,0 +1,49 @@ +This chapter describes the global functions and macros you use to +perform memory management. NSPR provides heap-based memory management +functions that map to the familiar ``malloc()``, ``calloc()``, +``realloc()``, and ``free()``. + +- `Memory Allocation Functions <#Memory_Allocation_Functions>`__ +- `Memory Allocation Macros <#Memory_Allocation_Macros>`__ + +.. _Memory_Allocation_Functions: + +Memory Allocation Functions +--------------------------- + +NSPR has its own heap, and these functions act on that heap. Libraries +built on top of NSPR, such as the Netscape security libraries, use these +functions to allocate and free memory. If you are allocating memory for +use by such libraries or freeing memory that was allocated by such +libraries, you must use these NSPR functions rather than the libc +equivalents. + +Memory allocation functions are: + + - :ref:`PR_Malloc` + - :ref:`PR_Calloc` + - :ref:`PR_Realloc` + - :ref:`PR_Free` + +``PR_Malloc()``, ``PR_Calloc()``, ``PR_Realloc()``, and ``PR_Free()`` +have the same signatures as their libc equivalents ``malloc()``, +``calloc()``, ``realloc()``, and ``free()``, and have the same +semantics. (Note that the argument type ``size_t`` is replaced by +:ref:`PRUint32`.) Memory allocated by ``PR_Malloc()``, ``PR_Calloc()``, or +``PR_Realloc()`` must be freed by ``PR_Free()``. + +.. _Memory_Allocation_Macros: + +Memory Allocation Macros +------------------------ + +Macro versions of the memory allocation functions are available, as well +as additional macros that provide programming convenience: + + - :ref:`PR_MALLOC` + - :ref:`PR_NEW` + - :ref:`PR_REALLOC` + - :ref:`PR_CALLOC` + - :ref:`PR_NEWZAP` + - :ref:`PR_DELETE` + - :ref:`PR_FREEIF` diff --git a/docs/nspr/reference/monitors.rst b/docs/nspr/reference/monitors.rst new file mode 100644 index 0000000000..63d43d595b --- /dev/null +++ b/docs/nspr/reference/monitors.rst @@ -0,0 +1,63 @@ +In addition to the mutex type :ref:`PRLock`, NSPR provides a special type, +:ref:`PRMonitor`, for use in Java programming. This chapter describes the +NSPR API for creation and manipulation of a mutex of type :ref:`PRMonitor`. + +- `Monitor Type <#Monitor_Type>`__ +- `Monitor Functions <#Monitor_Functions>`__ + +With a mutex of type :ref:`PRLock`, a single thread may enter the monitor +only once before it exits, and the mutex can have multiple associated +condition variables. + +With a mutex of type :ref:`PRMonitor`, a single thread may re-enter a +monitor as many times as it sees fit. The first time the thread enters a +monitor, it acquires the monitor's lock and the thread's entry count is +incremented to 1. Each subsequent time the thread successfully enters +the same monitor, the thread's entry count is incremented again, and +each time the thread exits the monitor, the thread's entry count is +decremented. When the entry count for a thread reaches zero, the thread +releases the monitor's lock, and other threads that were blocked while +trying to enter the monitor will be rescheduled. + +A call to :ref:`PR_Wait` temporarily returns the entry count to zero. When +the calling thread resumes, it has the same entry count it had before +the wait operation. + +Unlike a mutex of type :ref:`PRLock`, a mutex of type :ref:`PRMonitor` has a +single, implicitly associated condition variable that may be used to +facilitate synchronization of threads with the change in state of +monitored data. + +For an introduction to NSPR thread synchronization, including locks and +condition variables, see `Introduction to +NSPR <Introduction_to_NSPR>`__. + +.. _Monitor_Type: + +Monitor Type +------------ + +With the exception of :ref:`PR_NewMonitor`, which creates a new monitor +object, all monitor functions require a pointer to an opaque object of +type :ref:`PRMonitor`. + +.. _Monitor_Functions: + +Monitor Functions +----------------- + +All monitor functions are thread-safe. However, this safety does not +extend to protecting the monitor object from deletion. + + - :ref:`PR_NewMonitor` creates a new monitor. + - :ref:`PR_DestroyMonitor` destroys a monitor object. + - :ref:`PR_EnterMonitor` enters the lock associated with a specified + monitor. + - :ref:`PR_ExitMonitor` decrements the entry count associated with a + specified monitor. + - :ref:`PR_Wait` waits for a notify on a specified monitor's condition + variable. + - :ref:`PR_Notify` notifies a thread waiting on a specified monitor's + condition variable. + - :ref:`PR_NotifyAll` notifies all threads waiting on a specified + monitor's condition variable. diff --git a/docs/nspr/reference/named_shared_memory.rst b/docs/nspr/reference/named_shared_memory.rst new file mode 100644 index 0000000000..dff1275cc4 --- /dev/null +++ b/docs/nspr/reference/named_shared_memory.rst @@ -0,0 +1,95 @@ +The chapter describes the NSPR API for named shared memory. Shared +memory allows multiple processes to access one or more common shared +memory regions, using it as an interprocess communication channel. The +NSPR shared memory API provides a cross-platform named shared-memory +interface that is modeled on similar constructs in the Unix and Windows +operating systems. + +- `Shared Memory Protocol <#Shared_Memory_Protocol>`__ +- `Named Shared Memory Functions <#Named_Shared_Memory_Functions>`__ + +.. _Shared_Memory_Protocol: + +Shared Memory Protocol +---------------------- + +.. _Using_Named_Shared_Memory_Functions: + +Using Named Shared Memory Functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:ref:`PR_OpenSharedMemory` creates the shared memory segment, if it does +not already exist, or opens a connection with the existing shared memory +segment if it already exists. + +:ref:`PR_AttachSharedMemory` should be called following +:ref:`PR_OpenSharedMemory` to map the memory segment to an address in the +application's address space. :ref:`PR_AttachSharedMemory` may also be +called to remap a shared memory segment after detaching the same +``PRSharedMemory`` object. Be sure to detach it when you're finished. + +:ref:`PR_DetachSharedMemory` should be called to unmap the shared memory +segment from the application's address space. + +:ref:`PR_CloseSharedMemory` should be called when no further use of the +``PRSharedMemory`` object is required within a process. Following a call +to :ref:`PR_CloseSharedMemory`, the ``PRSharedMemory`` object is invalid +and cannot be reused. + +:ref:`PR_DeleteSharedMemory` should be called before process termination. +After you call :ref:`PR_DeleteSharedMemory`, any further use of the shared +memory associated with the name may cause unpredictable results. + +Filenames +~~~~~~~~~ + +The name passed to :ref:`PR_OpenSharedMemory` should be a valid filename +for a Unix platform. :ref:`PR_OpenSharedMemory` creates file using the name +passed in. Some platforms may mangle the name before creating the file +and the shared memory. The Unix implementation may use SysV IPC shared +memory, Posix shared memory, or memory mapped files; the filename may be +used to define the namespace. On Windows, the name is significant, but +there is no file associated with the name. + +No assumptions about the persistence of data in the named file should be +made. Depending on platform, the shared memory may be mapped onto system +paging space and be discarded at process termination. + +All names provided to :ref:`PR_OpenSharedMemory` should be valid filename +syntax or name syntax for shared memory for the target platform. +Referenced directories should have permissions appropriate for writing. + +.. _Limits_on_Shared_Memory_Resources: + +Limits on Shared Memory Resources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Different platforms have limits on both the number and size of shared +memory resources. The default system limits on some platforms may be +smaller than your requirements. These limits may be adjusted on some +platforms either via boot-time options or by setting the size of the +system paging space to accommodate more and/or larger shared memory +segment(s). + +.. _Security_Considerations: + +Security Considerations +~~~~~~~~~~~~~~~~~~~~~~~ + +On Unix platforms, depending on implementation, contents of the backing +store for the shared memory can be exposed via the file system. Set +permissions and or access controls at create and attach time to ensure +you get the desired security. + +On Windows platforms, no special security measures are provided. + +.. _Named_Shared_Memory_Functions: + +Named Shared Memory Functions +----------------------------- + + - :ref:`PR_OpenSharedMemory` + - :ref:`PR_AttachSharedMemory` + - :ref:`PR_DetachSharedMemory` + - :ref:`PR_CloseSharedMemory` + - :ref:`PR_DeleteSharedMemory` diff --git a/docs/nspr/reference/network_addresses.rst b/docs/nspr/reference/network_addresses.rst new file mode 100644 index 0000000000..c6845e6efc --- /dev/null +++ b/docs/nspr/reference/network_addresses.rst @@ -0,0 +1,82 @@ +This chapter describes the NSPR types and functions used to manipulate +network addresses. + +- `Network Address Types and + Constants <#Network_Address_Types_and_Constants>`__ +- `Network Address Functions <#Network_Address_Functions>`__ + +The API described in this chapter recognizes the emergence of Internet +Protocol Version 6 (IPv6). To facilitate the transition to IPv6, it is +recommended that clients treat all structures containing network +addresses as transparent objects and use the functions documented here +to manipulate the information. + +If used consistently, this API also eliminates the need to deal with the +byte ordering of network addresses. Typically, the only numeric +declarations required are the well-known port numbers that are part of +the :ref:`PRNetAddr` structure. + +.. _Network_Address_Types_and_Constants: + +Network Address Types and Constants +----------------------------------- + + - :ref:`PRHostEnt` + - :ref:`PRProtoEnt` + - :ref:`PR_NETDB_BUF_SIZE` + +.. _Network_Address_Functions: + +Network address functions +------------------------- + +.. _Initializing_a_Network_Address: + +Initializing a network address +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:ref:`PR_InitializeNetAddr` facilitates the use of :ref:`PRNetAddr`, the basic +network address structure, in a polymorphic manner. By using these +functions with other network address functions, clients can support +either version 4 or version 6 of the Internet Protocol transparently. + +All NSPR functions that require `PRNetAddr <PRNetAddr>`__ as an argument +accept either an IPv4 or IPv6 version of the address. + + - :ref:`PR_InitializeNetAddr` + +.. _Converting_Between_a_String_and_a_Network_Address: + +Converting between a string and a network address +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_StringToNetAddr` + - :ref:`PR_NetAddrToString` + +.. _Converting_address_formats: + +Converting address formats +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_ConvertIPv4AddrToIPv6` + +.. _Getting_Host_Names_and_Addresses: + +Getting host names and addresses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_GetHostByName` + - :ref:`PR_GetHostByAddr` + - :ref:`PR_EnumerateHostEnt` + - :ref:`PR_GetAddrInfoByName` + - :ref:`PR_EnumerateAddrInfo` + - :ref:`PR_GetCanonNameFromAddrInfo` + - :ref:`PR_FreeAddrInfo` + +.. _Getting_Protocol_Entries: + +Getting protocol entries +~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_GetProtoByName` + - :ref:`PR_GetProtoByNumber` diff --git a/docs/nspr/reference/nspr_error_handling.rst b/docs/nspr/reference/nspr_error_handling.rst new file mode 100644 index 0000000000..df40678607 --- /dev/null +++ b/docs/nspr/reference/nspr_error_handling.rst @@ -0,0 +1,206 @@ +This chapter describes the functions for retrieving and setting errors +and the error codes set by NSPR. + +- `Error Type <#Error_Type>`__ +- `Error Functions <#Error_Functions>`__ +- `Error Codes <#Error_Codes>`__ + +For information on naming conventions for NSPR types, functions, and +macros, see `NSPR Naming +Conventions <Introduction_to_NSPR#NSPR_Naming_Conventions>`__. + +.. _Error_Type: + +Error Type +---------- + + - :ref:`PRErrorCode` + +.. _Error_Functions: + +Error Functions +--------------- + + - :ref:`PR_SetError` + - :ref:`PR_SetErrorText` + - :ref:`PR_GetError` + - :ref:`PR_GetOSError` + - :ref:`PR_GetErrorTextLength` + - :ref:`PR_GetErrorText` + +.. _Error_Codes: + +Error Codes +----------- + +Error codes defined in ``prerror.h``: + +``PR_OUT_OF_MEMORY_ERROR`` + Insufficient memory to perform request. +``PR_BAD_DESCRIPTOR_ERROR`` + The file descriptor used as an argument in the preceding function is + invalid. +``PR_WOULD_BLOCK_ERROR`` + The operation would have blocked, which conflicts with the semantics + that have been established. +``PR_ACCESS_FAULT_ERROR`` + One of the arguments of the preceding function specified an invalid + memory address. +``PR_INVALID_METHOD_ERROR`` + The preceding function is invalid for the type of file descriptor + used. +``PR_ILLEGAL_ACCESS_ERROR`` + One of the arguments of the preceding function specified an invalid + memory address. +``PR_UNKNOWN_ERROR`` + Some unknown error has occurred. +``PR_PENDING_INTERRUPT_ERROR`` + The operation terminated because another thread has interrupted it + with :ref:`PR_Interrupt`. +``PR_NOT_IMPLEMENTED_ERROR`` + The preceding function has not been implemented. +``PR_IO_ERROR`` + The preceding I/O function encountered some sort of an error, perhaps + an invalid device. +``PR_IO_TIMEOUT_ERROR`` + The I/O operation has not completed in the time specified for the + preceding function. +``PR_IO_PENDING_ERROR`` + An I/O operation has been attempted on a file descriptor that is + currently busy with another operation. +``PR_DIRECTORY_OPEN_ERROR`` + The directory could not be opened. +``PR_INVALID_ARGUMENT_ERROR`` + One or more of the arguments to the function is invalid. +``PR_ADDRESS_NOT_AVAILABLE_ERROR`` + The network address (:ref:`PRNetAddr`) is not available (probably in + use). +``PR_ADDRESS_NOT_SUPPORTED_ERROR`` + The type of network address specified is not supported. +``PR_IS_CONNECTED_ERROR`` + An attempt to connect on an already connected network file + descriptor. +``PR_BAD_ADDRESS_ERROR`` + The network address specified is invalid (as reported by the + network). +``PR_ADDRESS_IN_USE_ERROR`` + Network address specified (:ref:`PRNetAddr`) is in use. +``PR_CONNECT_REFUSED_ERROR`` + The peer has refused to allow the connection to be established. +``PR_NETWORK_UNREACHABLE_ERROR`` + The network address specifies a host that is unreachable (perhaps + temporary). +``PR_CONNECT_TIMEOUT_ERROR`` + The connection attempt did not complete in a reasonable period of + time. +``PR_NOT_CONNECTED_ERROR`` + The preceding function attempted to use connected semantics on a + network file descriptor that was not connected. +``PR_LOAD_LIBRARY_ERROR`` + Failure to load a dynamic library. +``PR_UNLOAD_LIBRARY_ERROR`` + Failure to unload a dynamic library. +``PR_FIND_SYMBOL_ERROR`` + Symbol could not be found in the specified library. +``PR_INSUFFICIENT_RESOURCES_ERROR`` + There are insufficient system resources to process the request. +``PR_DIRECTORY_LOOKUP_ERROR`` + A directory lookup on a network address has failed. +``PR_TPD_RANGE_ERROR`` + Attempt to access a thread-private data index that is out of range of + any index that has been allocated to the process. +``PR_PROC_DESC_TABLE_FULL_ERROR`` + The process' table for holding open file descriptors is full. +``PR_SYS_DESC_TABLE_FULL_ERROR`` + The system's table for holding open file descriptors has been + exceeded. +``PR_NOT_SOCKET_ERROR`` + An attempt to use a non-network file descriptor on a network-only + operation. +``PR_NOT_TCP_SOCKET_ERROR`` + Attempt to perform a TCP specific function on a non-TCP file + descriptor. +``PR_SOCKET_ADDRESS_IS_BOUND_ERRO`` + Attempt to bind an address to a TCP file descriptor that is already + bound. +``PR_NO_ACCESS_RIGHTS_ERROR`` + Calling thread does not have privilege to perform the operation + requested. +``PR_OPERATION_NOT_SUPPORTED_ERRO`` + The requested operation is not supported by the platform. +``PR_PROTOCOL_NOT_SUPPORTED_ERROR`` + The host operating system does not support the protocol requested. +``PR_REMOTE_FILE_ERROR`` + Access to the remote file has been severed. +``PR_BUFFER_OVERFLOW_ERROR`` + The value retrieved is too large to be stored in the buffer provided. +``PR_CONNECT_RESET_ERROR`` + The (TCP) connection has been reset by the peer. +``PR_RANGE_ERROR`` + Unused. +``PR_DEADLOCK_ERROR`` + Performing the requested operation would have caused a deadlock. The + deadlock was avoided. +``PR_FILE_IS_LOCKED_ERROR`` + An attempt to acquire a lock on a file has failed because the file is + already locked. +``PR_FILE_TOO_BIG_ERROR`` + Completing the write or seek operation would have resulted in a file + larger than the system could handle. +``PR_NO_DEVICE_SPACE_ERROR`` + The device for storing the file is full. +``PR_PIPE_ERROR`` + Unused. +``PR_NO_SEEK_DEVICE_ERROR`` + Unused. +``PR_IS_DIRECTORY_ERROR`` + Attempt to perform a normal file operation on a directory. +``PR_LOOP_ERROR`` + Symbolic link loop. +``PR_NAME_TOO_LONG_ERROR`` + Filename is longer than allowed by the host operating system. +``PR_FILE_NOT_FOUND_ERROR`` + The requested file was not found. +``PR_NOT_DIRECTORY_ERROR`` + Attempt to perform directory specific operations on a normal file. +``PR_READ_ONLY_FILESYSTEM_ERROR`` + Attempt to write to a read-only file system. +``PR_DIRECTORY_NOT_EMPTY_ERROR`` + Attempt to delete a directory that is not empty. +``PR_FILESYSTEM_MOUNTED_ERROR`` + Attempt to delete or rename a file object while the file system is + busy. +``PR_NOT_SAME_DEVICE_ERROR`` + Request to rename a file to a file system on another device. +``PR_DIRECTORY_CORRUPTED_ERROR`` + The directory object in the file system is corrupted. +``PR_FILE_EXISTS_ERROR`` + Attempt to create or rename a file when the new name is already being + used. +``PR_MAX_DIRECTORY_ENTRIES_ERROR`` + Attempt to add new filename to directory would exceed the limit + allowed. +``PR_INVALID_DEVICE_STATE_ERROR`` + The device was in an invalid state to complete the desired operation. +``PR_DEVICE_IS_LOCKED_ERROR`` + The device needed to perform the desired request is locked. +``PR_NO_MORE_FILES_ERROR`` + There are no more entries in the directory. +``PR_END_OF_FILE_ERROR`` + Unexpectedly encountered end of file (Mac OS only). +``PR_FILE_SEEK_ERROR`` + An unexpected seek error (Mac OS only). +``PR_FILE_IS_BUSY_ERROR`` + The file is busy and the operation cannot be performed. +``PR_IN_PROGRESS_ERROR`` + The operation is still in progress (probably a nonblocking connect). +``PR_ALREADY_INITIATED_ERROR`` + The (retried) operation has already been initiated (probably a + nonblocking connect). +``PR_GROUP_EMPTY_ERROR`` + The wait group is empty. +``PR_INVALID_STATE_ERROR`` + The attempted operation is on an object that was in an improper state + to perform the request. +``PR_MAX_ERROR`` + Placeholder for the end of the list. diff --git a/docs/nspr/reference/nspr_log_file.rst b/docs/nspr/reference/nspr_log_file.rst new file mode 100644 index 0000000000..0208d4bac4 --- /dev/null +++ b/docs/nspr/reference/nspr_log_file.rst @@ -0,0 +1,31 @@ +NSPR_LOG_FILE +============= + +This environment variable specifies the file to which log messages are +directed. + + +Syntax +------ + +:: + + filespec + +*filespec* is a filename. The exact syntax is platform specific. + + +Description +----------- + +Use this environment variable to specify a log file other than the +default. If :ref:`NSPR_LOG_FILE` is not in the environment, then log output +is written to ``stdout`` or ``stderr``, depending on the platform. Set +:ref:`NSPR_LOG_FILE` to the name of the log file you want to use. NSPR +logging, when enabled, writes to the file named in this environment +variable. + +For MS Windows systems, you can set :ref:`NSPR_LOG_FILE` to the special +(case-sensitive) value ``WinDebug``. This value causes logging output to +be written using the Windows function ``OutputDebugString()``, which +writes to the debugger window. diff --git a/docs/nspr/reference/nspr_log_modules.rst b/docs/nspr/reference/nspr_log_modules.rst new file mode 100644 index 0000000000..9f2986607f --- /dev/null +++ b/docs/nspr/reference/nspr_log_modules.rst @@ -0,0 +1,88 @@ +NSPR_LOG_MODULES +================ + +This environment variable specifies which log modules have logging +enabled. + + +Syntax +------ + +:: + + moduleName:level[, moduleName:level]* + +*moduleName* is the name specified in a +`:ref:`PR_NewLogModule` <http://www-archive.mozilla.org/projects/nspr/reference/html/prlog.html#25372>`__ +call or one of the handy magic names listed below. + +*level* is a numeric value between 0 and 5, with the values having the +following meanings: + +- 0 = PR_LOG_NONE: nothing should be logged +- 1 = PR_LOG_ALWAYS: important; intended to always be logged +- 2 = PR_LOG_ERROR: errors +- 3 = PR_LOG_WARNING: warnings +- 4 = PR_LOG_DEBUG: debug messages, notices +- 5: everything! + + +Description +----------- + +Specify a ``moduleName`` that is associated with the ``name`` argument +in a call to +`:ref:`PR_NewLogModule` <http://www-archive.mozilla.org/projects/nspr/reference/html/prlog.html#25372>`__ +and a non-zero ``level`` value to enable logging for the named +``moduleName``. + +Special log module names are provided for controlling NSPR's log service +at execution time. These controls should be set in the +:ref:`NSPR_LOG_MODULES` environment variable at execution time to affect +NSPR's log service for your application. + +- **all** The name ``all`` enables all log modules. To enable all log + module calls to + ```PR_LOG`` <http://www-archive.mozilla.org/projects/nspr/reference/html/prlog.html#25497>`__, + set the variable as follows: + + :: + + set NSPR_LOG_MODULES=all:5 + +- **timestamp** Including ``timestamp`` results in a timestamp of the + form "2015-01-15 21:24:26.049906 UTC - " prefixing every logged line. + +- **append** Including ``append`` results in log entries being appended + to the existing contents of the file referenced by NSPR_LOG_FILE. If + not specified, the existing contents of NSPR_LOG_FILE will be lost as + a new file is created with the same filename. + +- **sync** The name ``sync`` enables unbuffered logging. This ensures + that all log messages are flushed to the operating system as they are + written, but may slow the program down. + +- **bufsize:size** The name ``bufsize:``\ *size* sets the log buffer to + *size*. + +Examples +-------- + +Log everything from the Toolkit::Storage component that happens, +prefixing each line with the timestamp when it was logged to the file +/tmp/foo.log (which will be replaced each time the executable is run). + +:: + + set NSPR_LOG_MODULES=timestamp,mozStorage:5 + set NSPR_LOG_FILE=/tmp/foo.log + +.. _Logging_with_Try_Server: + +Logging with Try Server +----------------------- + +- For **mochitest**, edit variable :ref:`NSPR_LOG_MODULES` in + ``testing/mochitest/runtests.py`` before pushing to try. You would be + able to download the log file as an artifact from the Log viewer. +- (other tests?) diff --git a/docs/nspr/reference/nspr_types.rst b/docs/nspr/reference/nspr_types.rst new file mode 100644 index 0000000000..6e304f4eb5 --- /dev/null +++ b/docs/nspr/reference/nspr_types.rst @@ -0,0 +1,180 @@ +This chapter describes the most common NSPR types. Other chapters +describe more specialized types when describing the functions that use +them. + +- `Calling Convention Types <#Calling_Convention_Types>`__ are used for + externally visible functions and globals. +- `Algebraic Types <#Algebraic_Types>`__ of various lengths are used + for integer algebra. +- `Miscellaneous Types <#Miscellaneous_Types>`__ are used for + representing size, pointer difference, Boolean values, and return + values. + +For information on naming conventions for NSPR types, functions, and +macros, see `NSPR Naming +Conventions <Introduction_to_NSPR#NSPR_Naming_Conventions>`__. + +.. _Calling_Convention_Types: + +Calling Convention Types +------------------------ + +These types are used to support cross-platform declarations of +prototypes and implementations: + + - :ref:`PR_EXTERN` is used for declarations of external functions or + variables. + - :ref:`PR_IMPLEMENT` is used for definitions of external functions or + variables. + - :ref:`PR_CALLBACK` is used for definitions and declarations of functions + that are called via function pointers. A typical example is a + function implemented in an application but called from a shared + library. + +Here are some simple examples of the use of these types: + +.. container:: highlight + + In dowhim.h: + + .. code:: + + PR_EXTERN( void ) DoWhatIMean( void ); + + static void PR_CALLBACK RootFunction(void *arg); + +.. container:: highlight + + In dowhim.c: + + .. code:: + + PR_IMPLEMENT( void ) DoWhatIMean( void ) { return; }; + + PRThread *thread = PR_CreateThread(..., RootFunction, ...); + +.. _Algebraic_Types: + +Algebraic Types +--------------- + +NSPR provides the following type definitions with unambiguous bit widths +for algebraic operations: + +- `8-, 16-, and 32-bit Integer + Types <#8-,_16-,_and_32-bit_Integer_Types>`__ +- `64-bit Integer Types <#64-bit_Integer_Types>`__ +- `Floating-Point Number Type <#Floating-Point_Number_Type>`__ + +For convenience, NSPR also provides type definitions with +platform-dependent bit widths: + +- `Native OS Integer Types <#Native_OS_Integer_Types>`__ + +.. _8-.2C_16-.2C_and_32-bit_Integer_Types: + +8-, 16-, and 32-bit Integer Types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _Signed_Integers: + +Signed Integers +^^^^^^^^^^^^^^^ + + - :ref:`PRInt8` + - :ref:`PRInt16` + - :ref:`PRInt32` + +.. _Unsigned_Integers: + +Unsigned Integers +^^^^^^^^^^^^^^^^^ + + - :ref:`PRUint8` + - :ref:`PRUint16` + - :ref:`PRUint32` + +.. _64-bit_Integer_Types: + +64-bit Integer Types +~~~~~~~~~~~~~~~~~~~~ + +Different platforms treat 64-bit numeric fields in different ways. Some +systems require emulation of 64-bit fields by using two 32-bit numeric +fields bound in a structure. Since the types (``long long`` versus +``struct LONGLONG``) are not type compatible, NSPR defines macros to +manipulate 64-bit numeric fields. These macros are defined in +``prlong.h``. Conscientious use of these macros ensures portability of +code to all the platforms supported by NSPR and still provides optimal +behavior on those systems that treat long long values directly. + + - :ref:`PRInt64` + - :ref:`PRUint64` + +.. _Floating-Point_Number_Type: + +Floating-Point Number Type +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The NSPR floating-point type is always 64 bits. + + - :ref:`PRFloat64` + +.. _Native_OS_Integer_Types: + +Native OS Integer Types +~~~~~~~~~~~~~~~~~~~~~~~ + +These types are most appropriate for automatic variables. They are +guaranteed to be at least 16 bits, though various architectures may +define them to be wider (for example, 32 or even 64 bits). These types +are never valid for fields of a structure. + + - :ref:`PRIntn` + - :ref:`PRUintn` + +.. _Miscellaneous_Types: + +Miscellaneous Types +------------------- + +- `Size Type <#Size_Type>`__ +- `Pointer Difference Types <#Pointer_Difference_Types>`__ +- `Boolean Types <#Boolean_Types>`__ +- `Status Type for Return Values <#Status_Type_for_Return_Values>`__ + +.. _Size_Type: + +Size Type +~~~~~~~~~ + + - :ref:`PRSize` + +.. _Pointer_Difference_Types: + +Pointer Difference Types +~~~~~~~~~~~~~~~~~~~~~~~~ + +Types for pointer difference. Variables of these types are suitable for +storing a pointer or pointer subtraction. These are the same as the +corresponding types in ``libc``. + + - :ref:`PRPtrdiff` + - :ref:`PRUptrdiff` + +.. _Boolean_Types: + +Boolean Types +~~~~~~~~~~~~~ + +Type and constants for Boolean values. + + - :ref:`PRBool` + - :ref:`PRPackedBool` + +.. _Status_Type_for_Return_Values: + +Status Type for Return Values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PRStatus` diff --git a/docs/nspr/reference/pl_comparestrings.rst b/docs/nspr/reference/pl_comparestrings.rst new file mode 100644 index 0000000000..46050c74b2 --- /dev/null +++ b/docs/nspr/reference/pl_comparestrings.rst @@ -0,0 +1,27 @@ +PL_CompareStrings +================= + +Compares two character strings. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PRIntn PL_CompareStrings( + const void *v1, + const void *v2); + + +Description +----------- + +:ref:`PL_CompareStrings` compares ``v1`` and ``v2`` as character strings +using ``strcmp``. If the two strings are equal, it returns 1. If the two +strings are not equal, it returns 0. + +:ref:`PL_CompareStrings` can be used as the comparator function for +string-valued key or entry value. diff --git a/docs/nspr/reference/pl_comparevalues.rst b/docs/nspr/reference/pl_comparevalues.rst new file mode 100644 index 0000000000..9fef0b63f3 --- /dev/null +++ b/docs/nspr/reference/pl_comparevalues.rst @@ -0,0 +1,27 @@ +PL_CompareValues +================ + +Compares two ``void *`` values numerically. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PRIntn PL_CompareValues(const + void *v1, + const void *v2); + + +Description +----------- + +:ref:`PL_CompareValues` compares the two ``void *`` values ``v1`` and +``v2`` numerically, i.e., it returns the value of the expression ``v1`` +== ``v2``. + +:ref:`PL_CompareValues` can be used as the comparator function for integer +or pointer-valued key or entry value. diff --git a/docs/nspr/reference/pl_hashstring.rst b/docs/nspr/reference/pl_hashstring.rst new file mode 100644 index 0000000000..3c6b8cde5f --- /dev/null +++ b/docs/nspr/reference/pl_hashstring.rst @@ -0,0 +1,36 @@ +PL_HashString +============= + +A general-purpose hash function for character strings. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PLHashNumber PL_HashString(const void *key); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``key`` + A pointer to a character string. + + +Returns +~~~~~~~ + +The hash number for the specified key. + + +Description +----------- + +:ref:`PL_HashString` can be used as the key hash function for a hash table +if the key is a character string. diff --git a/docs/nspr/reference/pl_hashtableadd.rst b/docs/nspr/reference/pl_hashtableadd.rst new file mode 100644 index 0000000000..a4827d5c05 --- /dev/null +++ b/docs/nspr/reference/pl_hashtableadd.rst @@ -0,0 +1,52 @@ +PL_HashTableAdd +=============== + +Add a new entry with the specified key and value to the hash table. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PLHashEntry *PL_HashTableAdd( + PLHashTable *ht, + const void *key, + void *value); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``ht`` + A pointer to the the hash table to which to add the entry. +``key`` + A pointer to the key for the entry to be added. +``value`` + A pointer to the value for the entry to be added. + + +Returns +~~~~~~~ + +A pointer to the new entry. + + +Description +----------- + +Add a new entry with the specified key and value to the hash table. + +If an entry with the same key already exists in the table, the +``freeEntry`` function is invoked with the ``HT_FREE_VALUE`` flag. You +can write your ``freeEntry`` function to free the value of the specified +entry if the old value should be freed. The default ``freeEntry`` +function does not free the value of the entry. + +:ref:`PL_HashTableAdd` returns ``NULL`` if there is not enough memory to +create a new entry. It doubles the number of buckets if the table is +overloaded. diff --git a/docs/nspr/reference/pl_hashtabledestroy.rst b/docs/nspr/reference/pl_hashtabledestroy.rst new file mode 100644 index 0000000000..9b45e5a609 --- /dev/null +++ b/docs/nspr/reference/pl_hashtabledestroy.rst @@ -0,0 +1,32 @@ +PL_HashTableDestroy +=================== + +Frees the table and all the entries. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + void PL_HashTableDestroy(PLHashTable *ht); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``ht`` + A pointer to the hash table to be destroyed. + + +Description +----------- + +:ref:`PL_HashTableDestroy` frees all the entries in the table and the table +itself. The entries are freed by the ``freeEntry`` function (with the +``HT_FREE_ENTRY`` flag) in the ``allocOps`` structure supplied when the +table was created. diff --git a/docs/nspr/reference/pl_hashtableenumerateentries.rst b/docs/nspr/reference/pl_hashtableenumerateentries.rst new file mode 100644 index 0000000000..ce77c8aad7 --- /dev/null +++ b/docs/nspr/reference/pl_hashtableenumerateentries.rst @@ -0,0 +1,46 @@ +PL_HashTableEnumerateEntries +============================ + +Enumerates all the entries in the hash table, invoking a specified +function on each entry. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PRIntn PL_HashTableEnumerateEntries( + PLHashTable *ht, + PLHashEnumerator f, + void *arg); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``ht`` + A pointer to the hash table whose entries are to be enumerated. +``f`` + Function to be applied to each entry. +``arg`` + Argument for function ``f``. + + +Returns +~~~~~~~ + +The number of entries enumerated. + + +Description +----------- + +The entries are enumerated in an unspecified order. For each entry, the +enumerator function is invoked with the entry, the index (in the +sequence of enumeration, starting from 0) of the entry, and arg as +arguments. diff --git a/docs/nspr/reference/pl_hashtablelookup.rst b/docs/nspr/reference/pl_hashtablelookup.rst new file mode 100644 index 0000000000..236c08a874 --- /dev/null +++ b/docs/nspr/reference/pl_hashtablelookup.rst @@ -0,0 +1,45 @@ +PL_HashTableLookup +================== + +Looks up the entry with the specified key and return its value. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + void *PL_HashTableLookup( + PLHashTable *ht, + const void *key); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``ht`` + A pointer to the hash table in which to look up the entry specified + by ``key``. +``key`` + A pointer to the key for the entry to look up. + + +Returns +~~~~~~~ + +The value of the entry with the specified key, or ``NULL`` if there is +no such entry. + + +Description +----------- + +If there is no entry with the specified key, :ref:`PL_HashTableLookup` +returns ``NULL``. This means that one cannot tell whether a ``NULL`` +return value means the entry does not exist or the value of the entry is +``NULL``. Keep this ambiguity in mind if you want to store ``NULL`` +values in a hash table. diff --git a/docs/nspr/reference/pl_hashtableremove.rst b/docs/nspr/reference/pl_hashtableremove.rst new file mode 100644 index 0000000000..32c3662f63 --- /dev/null +++ b/docs/nspr/reference/pl_hashtableremove.rst @@ -0,0 +1,46 @@ +PL_HashTableRemove +================== + +Removes the entry with the specified key from the hash table. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PRBool PL_HashTableRemove( + PLHashTable *ht, + const void *key); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``ht`` + A pointer to the hash table from which to remove the entry. +``key`` + A pointer to the key for the entry to be removed. + + +Description +----------- + +If there is no entry in the table with the specified key, +:ref:`PL_HashTableRemove` returns ``PR_FALSE``. If the entry exists, +:ref:`PL_HashTableRemove` removes the entry from the table, invokes +``freeEntry`` with the ``HT_FREE_ENTRY`` flag to frees the entry, and +returns ``PR_TRUE``. + +If the table is underloaded, :ref:`PL_HashTableRemove` also shrinks the +number of buckets by half. + + +Remark +------ + +This function should return :ref:`PRStatus`. diff --git a/docs/nspr/reference/pl_newhashtable.rst b/docs/nspr/reference/pl_newhashtable.rst new file mode 100644 index 0000000000..d4479284c5 --- /dev/null +++ b/docs/nspr/reference/pl_newhashtable.rst @@ -0,0 +1,67 @@ +PL_NewHashTable +=============== + +Create a new hash table. + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + PLHashTable *PL_NewHashTable( + PRUint32 numBuckets, + PLHashFunction keyHash, + PLHashComparator keyCompare, + PLHashComparator valueCompare, + const PLHashAllocOps *allocOps, + void *allocPriv + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``numBuckets`` + The number of buckets in the hash table. +``keyHash`` + Hash function. +``keyCompare`` + Function used to compare keys of entries. +``valueCompare`` + Function used to compare keys of entries. +``allocOps`` + A pointer to a ``PLHashAllocOps`` structure that must exist + throughout the lifetime of the new hash table. +``allocPriv`` + Passed as the first argument (pool). + + +Returns +~~~~~~~ + +The new hash table. + + +Description +----------- + +:ref:`PL_NewHashTable` creates a new hash table. The table has at least 16 +buckets. You can pass a value of 0 as ``numBuckets`` to create the +default number of buckets in the new table. The arguments ``keyCompare`` +and ``valueCompare`` are functions of type :ref:`PLHashComparator` that the +hash table library functions use to compare the keys and the values of +entries. + +The argument ``allocOps`` points to a ``PLHashAllocOps`` structure that +must exist throughout the lifetime of the new hash table. The hash table +library functions do not make a copy of this structure. When the +allocation functions in ``allocOps`` are invoked, the allocation private +data allocPriv is passed as the first argument (pool). You can specify a +``NULL`` value for ``allocOps`` to use the default allocation functions. +If ``allocOps`` is ``NULL``, ``allocPriv`` is ignored. Note that the +default ``freeEntry`` function does not free the value of the entry. diff --git a/docs/nspr/reference/pl_strcpy.rst b/docs/nspr/reference/pl_strcpy.rst new file mode 100644 index 0000000000..addd05b824 --- /dev/null +++ b/docs/nspr/reference/pl_strcpy.rst @@ -0,0 +1,40 @@ +PL_strcpy +========= + + +Copies a string, up to and including the trailing ``'\0'``, into a +destination buffer. + + +Syntax +~~~~~~ + +.. code:: + + char * PL_strcpy(char *dest, const char *src); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``dest`` + Pointer to a buffer. On output, the buffer contains a copy of the + string passed in src. +``src`` + Pointer to the string to be copied. + + +Returns +~~~~~~~ + +The function returns a pointer to the buffer specified by the ``dest`` +parameter. + + +Description +~~~~~~~~~~~ + +If the string specified by ``src`` is longer than the buffer specified +by ``dest``, the buffer will not be null-terminated. diff --git a/docs/nspr/reference/pl_strdup.rst b/docs/nspr/reference/pl_strdup.rst new file mode 100644 index 0000000000..fcced90ec4 --- /dev/null +++ b/docs/nspr/reference/pl_strdup.rst @@ -0,0 +1,48 @@ +PL_strdup +========= + +Returns a pointer to a new memory node in the NSPR heap containing a +copy of a specified string. + + +Syntax +~~~~~~ + +.. code:: + + #include <plstr.h> + + char *PL_strdup(const char *s); + + +Parameter +~~~~~~~~~ + +The function has a single parameter: + +``s`` + The string to copy, may be ``NULL``. + + +Returns +~~~~~~~ + +The function returns one of these values: + +- If successful, a pointer to a copy of the specified string. +- If the memory allocation fails, ``NULL``. + + +Description +~~~~~~~~~~~ + +To accommodate the terminator, the size of the allocated memory is one +greater than the length of the string being copied. A ``NULL`` argument, +like a zero-length argument, results in a pointer to a one-byte block of +memory containing the null value. + +Notes +~~~~~ + +The memory allocated by :ref:`PL_strdup` should be freed with +`PL_strfree </en/PL_strfree>`__. diff --git a/docs/nspr/reference/pl_strfree.rst b/docs/nspr/reference/pl_strfree.rst new file mode 100644 index 0000000000..e17c0c34cf --- /dev/null +++ b/docs/nspr/reference/pl_strfree.rst @@ -0,0 +1,21 @@ +PL_strfree +========== + +Frees memory allocated by :ref:`PL_strdup` + + +Syntax +~~~~~~ + +.. code:: + + void PL_strfree(char *s); + + +Parameter +~~~~~~~~~ + +The function has these parameter: + +``s`` + Pointer to the string to be freed. diff --git a/docs/nspr/reference/pl_strlen.rst b/docs/nspr/reference/pl_strlen.rst new file mode 100644 index 0000000000..edd1ecd129 --- /dev/null +++ b/docs/nspr/reference/pl_strlen.rst @@ -0,0 +1,28 @@ +PL_strlen +========= + +Returns the length of a specified string (not including the trailing +``'\0'``) + + +Syntax +~~~~~~ + +.. code:: + + PRUint32 PL_strlen(const char *str); + + +Parameter +~~~~~~~~~ + +The function has these parameter: + +``str`` + Size in bytes of item to be allocated. + + +Returns +~~~~~~~ + +If successful, the function returns length of the specified string. diff --git a/docs/nspr/reference/plhashallocops.rst b/docs/nspr/reference/plhashallocops.rst new file mode 100644 index 0000000000..02cceb9c2b --- /dev/null +++ b/docs/nspr/reference/plhashallocops.rst @@ -0,0 +1,40 @@ + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef struct PLHashAllocOps { + void *(PR_CALLBACK *allocTable)(void *pool, PRSize size); + void (PR_CALLBACK *freeTable)(void *pool, void *item); + PLHashEntry *(PR_CALLBACK *allocEntry)(void *pool, const void *key); + void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag); + } PLHashAllocOps; + + #define HT_FREE_VALUE 0 /* just free the entry's value */ + #define HT_FREE_ENTRY 1 /* free value and entire entry */ + + +Description +----------- + +Users of the hash table functions can provide their own memory +allocation functions. A pair of functions is used to allocate and tree +the table, and another pair of functions is used to allocate and free +the table entries. + +The first argument, pool, for all four functions is a void \* pointer +that is a piece of data for the memory allocator. Typically pool points +to a memory pool used by the memory allocator. + +The ``freeEntry`` function does not need to free the value of the entry. +If flag is ``HT_FREE_ENTRY``, the function frees the entry. + + +Remark +------ + +The ``key`` argument for the ``allocEntry`` function does not seem to be +useful. It is unused in the default ``allocEntry`` function. diff --git a/docs/nspr/reference/plhashcomparator.rst b/docs/nspr/reference/plhashcomparator.rst new file mode 100644 index 0000000000..1310a6f37d --- /dev/null +++ b/docs/nspr/reference/plhashcomparator.rst @@ -0,0 +1,41 @@ +PLHashComparator +================ + + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef PRIntn (PR_CALLBACK *PLHashComparator)( + const void *v1, + const void *v2); + + +Description +----------- + +:ref:`PLHashComparator` is a function type that compares two values of an +unspecified type. It returns a nonzero value if the two values are +equal, and 0 if the two values are not equal. :ref:`PLHashComparator` +defines the meaning of equality for the unspecified type. + +For convenience, two comparator functions are provided. +:ref:`PL_CompareStrings` compare two character strings using ``strcmp``. +:ref:`PL_CompareValues` compares the values of the arguments v1 and v2 +numerically. + + +Remark +------ + +The return value of :ref:`PLHashComparator` functions should be of type +:ref:`PRBool`. + + +See Also +-------- + +:ref:`PL_CompareStrings`, :ref:`PL_CompareValues` diff --git a/docs/nspr/reference/plhashentry.rst b/docs/nspr/reference/plhashentry.rst new file mode 100644 index 0000000000..ea11ac3439 --- /dev/null +++ b/docs/nspr/reference/plhashentry.rst @@ -0,0 +1,36 @@ + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef struct PLHashEntry PLHashEntry; + + +Description +----------- + +``PLHashEntry`` is a structure that represents an entry in the hash +table. An entry has a key and a value, represented by the following +fields in the ``PLHashEntry`` structure. + +.. code:: + + const void *key; + void *value; + +The key field is a pointer to an opaque key. The value field is a +pointer to an opaque value. If the key of an entry is an integral value +that can fit into a ``void *`` pointer, you can just cast the key itself +to ``void *`` and store it in the key field. Similarly, if the value of +an entry is an integral value that can fit into a ``void *`` pointer, +you can cast the value itself to ``void *`` and store it in the value +field. + +.. warning:: + + **Warning**: There are other fields in the ``PLHashEntry`` structure + besides key and value. These fields are for use by the hash table + library functions and the user should not tamper with them. diff --git a/docs/nspr/reference/plhashenumerator.rst b/docs/nspr/reference/plhashenumerator.rst new file mode 100644 index 0000000000..eba3635c5e --- /dev/null +++ b/docs/nspr/reference/plhashenumerator.rst @@ -0,0 +1,41 @@ + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn index, void *arg); + + /* Return value */ + #define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ + #define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ + #define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ + #define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */ + + +Description +----------- + +``PLHashEnumerator`` is a function type used in the enumerating a hash +table. When all the table entries are enumerated, each entry is passed +to a user-specified function of type ``PLHashEnumerator`` with the hash +table entry, an integer index, and an arbitrary piece of user data as +argument. + + +Remark +------ + +The meaning of ``HT_ENUMERATE_UNHASH`` is not clear. In the current +implementation, it will leave the hash table in an inconsistent state. +The entries are unlinked from the table, they are not freed, but the +entry count (the ``nentries`` field of the ``PLHashTable`` structure) is +not decremented. + + +See Also +-------- + +:ref:`PL_HashTableEnumerateEntries` diff --git a/docs/nspr/reference/plhashfunction.rst b/docs/nspr/reference/plhashfunction.rst new file mode 100644 index 0000000000..e1767e7e94 --- /dev/null +++ b/docs/nspr/reference/plhashfunction.rst @@ -0,0 +1,22 @@ + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key); + + +Description +----------- + +``PLHashNumber`` is a function type that maps the key of a hash table +entry to a hash number. + + +See Also +-------- + +`PL_HashString <PL_HashString>`__ diff --git a/docs/nspr/reference/plhashnumber.rst b/docs/nspr/reference/plhashnumber.rst new file mode 100644 index 0000000000..a84c147aa9 --- /dev/null +++ b/docs/nspr/reference/plhashnumber.rst @@ -0,0 +1,29 @@ + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef PRUint32 PLHashNumber; + + #define PL_HASH_BITS 32 + + +Description +----------- + +``PLHashNumber`` is an unsigned 32-bit integer. ``PLHashNumber`` is the +data type of the return value of a hash function. A hash function maps a +key to a hash number, which is then used to compute the index of the +bucket. + +The macro ``PL_HASH_BITS`` is the size (in bits) of the ``PLHashNumber`` +data type and has the value of 32. + + +See Also +-------- + +``PLHashFunction`` diff --git a/docs/nspr/reference/plhashtable.rst b/docs/nspr/reference/plhashtable.rst new file mode 100644 index 0000000000..70bad3aebe --- /dev/null +++ b/docs/nspr/reference/plhashtable.rst @@ -0,0 +1,21 @@ + +Syntax +------ + +.. code:: + + #include <plhash.h> + + typedef struct PLHashTable PLHashTable; + + +Description +----------- + +The opaque ``PLHashTable`` structure represents a hash table. Entries in +the table have the type ``PLHashEntry`` and are organized into buckets. +The number of buckets in a hash table may be changed by the library +functions during the lifetime of the table to optimize speed and space. + +A new hash table is created by the :ref:`PL_NewHashTable` function, and +destroyed by the :ref:`PL_HashTableDestroy` function. diff --git a/docs/nspr/reference/pr_abort.rst b/docs/nspr/reference/pr_abort.rst new file mode 100644 index 0000000000..5c14ea2e2e --- /dev/null +++ b/docs/nspr/reference/pr_abort.rst @@ -0,0 +1,21 @@ +PR_Abort +======== + +Aborts the process in a nongraceful manner. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_Abort(void); + + +Description +----------- + +:ref:`PR_Abort` results in a core file and a call to the debugger or +equivalent, in addition to causing the entire process to stop. diff --git a/docs/nspr/reference/pr_accept.rst b/docs/nspr/reference/pr_accept.rst new file mode 100644 index 0000000000..eb1b1ad3ed --- /dev/null +++ b/docs/nspr/reference/pr_accept.rst @@ -0,0 +1,65 @@ +PR_Accept +========= + +Accepts a connection on a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_Accept( + PRFileDesc *fd, + PRNetAddr *addr, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing the rendezvous + socket on which the caller is willing to accept new connections. +``addr`` + A pointer to a structure of type :ref:`PRNetAddr`. On output, this + structure contains the address of the connecting entity. +``timeout`` + A value of type :ref:`PRIntervalTime` specifying the time limit for + completion of the accept operation. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful acceptance of a connection, a pointer to a new + :ref:`PRFileDesc` structure representing the newly accepted connection. +- If unsuccessful, ``NULL``. Further information can be obtained by + calling :ref:`PR_GetError`. + + +Description +----------- + +The socket ``fd`` is a rendezvous socket that has been bound to an +address with :ref:`PR_Bind` and is listening for connections after a call +to :ref:`PR_Listen`. :ref:`PR_Accept` accepts the first connection from the +queue of pending connections and creates a new socket for the newly +accepted connection. The rendezvous socket can still be used to accept +more connections. + +If the ``addr`` parameter is not ``NULL``, :ref:`PR_Accept` stores the +address of the connecting entity in the :ref:`PRNetAddr` object pointed to +by ``addr``. + +:ref:`PR_Accept` blocks the calling thread until either a new connection is +successfully accepted or an error occurs. If the timeout parameter is +not ``PR_INTERVAL_NO_TIMEOUT`` and no pending connection can be accepted +before the time limit, :ref:`PR_Accept` returns ``NULL`` with the error +code ``PR_IO_TIMEOUT_ERROR``. diff --git a/docs/nspr/reference/pr_acceptread.rst b/docs/nspr/reference/pr_acceptread.rst new file mode 100644 index 0000000000..d0e8fca61b --- /dev/null +++ b/docs/nspr/reference/pr_acceptread.rst @@ -0,0 +1,73 @@ +PR_AcceptRead +============= + +Accepts a new connection and receives a block of data. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_AcceptRead( + PRFileDesc *listenSock, + PRFileDesc **acceptedSock, + PRNetAddr **peerAddr, + void *buf, + PRInt32 amount, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``listenSock`` + A pointer to a :ref:`PRFileDesc` object representing a socket descriptor + that has been called with the :ref:`PR_Listen` function, also known as + the rendezvous socket. +``acceptedSock`` + A pointer to a pointer to a :ref:`PRFileDesc` object. On return, + ``*acceptedSock`` points to the :ref:`PRFileDesc` object for the newly + connected socket. This parameter is valid only if the function return + does not indicate failure. +``peerAddr`` + A pointer a pointer to a :ref:`PRNetAddr` object. On return, + ``peerAddr`` points to the address of the remote socket. The + :ref:`PRNetAddr` object that ``peerAddr`` points to will be in the + buffer pointed to by ``buf``. This parameter is valid only if the + function return does not indicate failure. +``buf`` + A pointer to a buffer to hold data sent by the peer and the peer's + address. This buffer must be large enough to receive ``amount`` bytes + of data and two :ref:`PRNetAddr` structures (thus allowing the runtime + to align the addresses as needed). +``amount`` + The number of bytes of data to receive. Does not include the size of + the :ref:`PRNetAddr` structures. If 0, no data will be read from the + peer. +``timeout`` + The timeout interval only applies to the read portion of the + operation. :ref:`PR_AcceptRead` blocks indefinitely until the connection + is accepted; the read will time out after the timeout interval + elapses. + + +Returns +~~~~~~~ + +- A positive number indicates the number of bytes read from the peer. +- The value -1 indicates a failure. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_AcceptRead` accepts a new connection and retrieves the newly +created socket's descriptor and the connecting peer's address. Also, as +its name suggests, :ref:`PR_AcceptRead` receives the first block of data +sent by the peer. diff --git a/docs/nspr/reference/pr_access.rst b/docs/nspr/reference/pr_access.rst new file mode 100644 index 0000000000..14fb5018b2 --- /dev/null +++ b/docs/nspr/reference/pr_access.rst @@ -0,0 +1,41 @@ +PR_Access +========= + +Determines the accessibility of a file. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Access( + const char *name, + PRAccessHow how); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``name`` + The pathname of the file whose accessibility is to be determined. +``how`` + Specifies which access permission to check for. Use one of the + following values: + + - :ref:`PR_ACCESS_READ_OK`. Test for read permission. + - :ref:`PR_ACCESS_WRITE_OK`. Test for write permission. + - :ref:`PR_ACCESS_EXISTS`. Check existence of file. + + +Returns +~~~~~~~ + +One of the following values: + +- If the requested access is permitted, ``PR_SUCCESS``. +- If the requested access is not permitted, ``PR_FAILURE``. diff --git a/docs/nspr/reference/pr_append_link.rst b/docs/nspr/reference/pr_append_link.rst new file mode 100644 index 0000000000..7525f348a5 --- /dev/null +++ b/docs/nspr/reference/pr_append_link.rst @@ -0,0 +1,32 @@ +PR_APPEND_LINK +============== + +Appends an element to the end of a list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_APPEND_LINK ( + PRCList *elemp, + PRCList *listp); + + +Parameters +~~~~~~~~~~ + +``elemp`` + A pointer to the element to be inserted. +``listp`` + A pointer to the list. + + +Description +----------- + +PR_APPEND_LINK adds the specified element to the end of the specified +list. diff --git a/docs/nspr/reference/pr_assert.rst b/docs/nspr/reference/pr_assert.rst new file mode 100644 index 0000000000..669c8d346a --- /dev/null +++ b/docs/nspr/reference/pr_assert.rst @@ -0,0 +1,43 @@ +PR_ASSERT +========= + +Terminates execution when a given expression is ``FALSE``. + + +Syntax +------ + +.. code:: + + #include <prlog.h> + + void PR_ASSERT ( expression ); + + +Parameters +~~~~~~~~~~ + +The macro has this parameter: + +expression + Any valid C language expression that evaluates to ``TRUE`` or + ``FALSE``. + + +Returns +~~~~~~~ + +Nothing + + +Description +----------- + +This macro evaluates the specified expression. When the result is zero +(``FALSE``) the application terminates; otherwise the application +continues. The macro converts the expression to a string and passes it +to ``PR_Assert``, using file and line parameters from the compile-time +environment. + +This macro compiles to nothing if compile-time options are not specified +to enable logging. diff --git a/docs/nspr/reference/pr_atomicadd.rst b/docs/nspr/reference/pr_atomicadd.rst new file mode 100644 index 0000000000..3f2afeece0 --- /dev/null +++ b/docs/nspr/reference/pr_atomicadd.rst @@ -0,0 +1,37 @@ +PR_AtomicAdd +============ + + +Syntax +------ + +.. code:: + + #include <pratom.h> + + PRInt32 PR_AtomicAdd( + PRInt32 *ptr, + PRInt32 val); + + +Parameter +~~~~~~~~~ + +The function has the following parameters: + +``ptr`` + A pointer to the value to increment. +``val`` + A value to be added. + + +Returns +~~~~~~~ + +The returned value is the result of the addition. + + +Description +----------- + +Atomically add a 32 bit value. diff --git a/docs/nspr/reference/pr_atomicdecrement.rst b/docs/nspr/reference/pr_atomicdecrement.rst new file mode 100644 index 0000000000..a27b8d8227 --- /dev/null +++ b/docs/nspr/reference/pr_atomicdecrement.rst @@ -0,0 +1,37 @@ +PR_AtomicDecrement +================== + +Atomically decrements a 32-bit value. + + +Syntax +------ + +.. code:: + + #include <pratom.h> + + PRInt32 PR_AtomicDecrement(PRInt32 *val); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``val`` + A pointer to the value to decrement. + + +Returns +~~~~~~~ + +The function returns the decremented value (i.e., the result). + + +Description +----------- + +:ref:`PR_AtomicDecrement` first decrements the referenced variable by one. +The value returned is the referenced variable's final value. The +modification to memory is unconditional. diff --git a/docs/nspr/reference/pr_atomicincrement.rst b/docs/nspr/reference/pr_atomicincrement.rst new file mode 100644 index 0000000000..126ed7989c --- /dev/null +++ b/docs/nspr/reference/pr_atomicincrement.rst @@ -0,0 +1,37 @@ +PR_AtomicIncrement +================== + +Atomically increments a 32-bit value. + + +Syntax +------ + +.. code:: + + #include <pratom.h> + + PRInt32 PR_AtomicIncrement(PRInt32 *val); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``val`` + A pointer to the value to increment. + + +Returns +~~~~~~~ + +The function returns the incremented value (i.e., the result). + + +Description +----------- + +The referenced variable is incremented by one. The result of the +function is the value of the memory after the operation. The writing of +the memory is unconditional. diff --git a/docs/nspr/reference/pr_atomicset.rst b/docs/nspr/reference/pr_atomicset.rst new file mode 100644 index 0000000000..3c9df0b1b9 --- /dev/null +++ b/docs/nspr/reference/pr_atomicset.rst @@ -0,0 +1,42 @@ +PR_AtomicSet +============ + +Atomically sets a 32-bit value and return its previous contents. + + +Syntax +------ + +.. code:: + + #include <pratom.h> + + PRInt32 PR_AtomicSet( + PRInt32 *val, + PRInt32 newval); + + +Parameters +~~~~~~~~~~ + +The function has the following parameter: + +``val`` + A pointer to the value to be set. +``newval`` + The new value to assign to the ``val`` parameter. + + +Returns +~~~~~~~ + +The function returns the prior value of the referenced variable. + + +Description +----------- + +:ref:`PR_AtomicSet` first reads the value of var, then updates it with the +supplied value. The returned value is the value that was read\ *before* +memory was updated. The memory modification is unconditional--that is, +it isn't a test and set operation. diff --git a/docs/nspr/reference/pr_attachsharedmemory.rst b/docs/nspr/reference/pr_attachsharedmemory.rst new file mode 100644 index 0000000000..ed7c38d4a3 --- /dev/null +++ b/docs/nspr/reference/pr_attachsharedmemory.rst @@ -0,0 +1,44 @@ +PR_AttachSharedMemory +===================== + +Attaches a memory segment previously opened with :ref:`PR_OpenSharedMemory` +and maps it into the process memory space. + + +Syntax +------ + +.. code:: + + #include <prshm.h> + +.. code:: + + NSPR_API( void * ) + PR_AttachSharedMemory( + PRSharedMemory *shm, + PRIntn flags + ); + + /* Define values for PR_AttachSharedMemory(...,flags) */ + #define PR_SHM_READONLY 0x01 + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +shm + The handle returned from :ref:`PR_OpenSharedMemory`. +flags + Options for mapping the shared memory. ``PR_SHM_READONLY`` causes the + memory to be attached read-only. + + +Returns +~~~~~~~ + +Address where shared memory is mapped, or ``NULL`` if an error occurs. +Retrieve the reason for the failure by calling :ref:`PR_GetError` and +:ref:`PR_GetOSError`. diff --git a/docs/nspr/reference/pr_attachthread.rst b/docs/nspr/reference/pr_attachthread.rst new file mode 100644 index 0000000000..78edfc19b0 --- /dev/null +++ b/docs/nspr/reference/pr_attachthread.rst @@ -0,0 +1,76 @@ +PR_AttachThread +=============== + +.. container:: blockIndicator obsolete obsoleteHeader + + | **Obsolete** + | This feature is obsolete. Although it may still work in some + browsers, its use is discouraged since it could be removed at any + time. Try to avoid using it. + +Associates a :ref:`PRThread` object with an existing native thread. + + +Syntax +------ + +.. code:: + + #include <pprthread.h> + + PRThread* PR_AttachThread( + PRThreadType type, + PRThreadPriority priority, + PRThreadStack *stack); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_AttachThread` has the following parameters: + +``type`` + Specifies that the thread is either a user thread + (``PR_USER_THREAD``) or a system thread (``PR_SYSTEM_THREAD``). +``priority`` + The priority to assign to the thread being attached. +``stack`` + The stack for the thread being attached. + + +Returns +~~~~~~~ + +The function returns one of these values: + +- If successful, a pointer to a :ref:`PRThread` object. +- If unsuccessful, for example if system resources are not available, + ``NULL``. + + +Description +----------- + +You use :ref:`PR_AttachThread` when you want to use NSS functions on the +native thread that was not created with NSPR. :ref:`PR_AttachThread` +informs NSPR about the new thread by associating a :ref:`PRThread` object +with the native thread. + +The thread object is automatically destroyed when it is no longer +needed. + +You don't need to call :ref:`PR_AttachThread` unless you create your own +native thread. :ref:`PR_Init` calls :ref:`PR_AttachThread` automatically for +the primordial thread. + +.. note:: + + **Note**: As of NSPR release v3.0, :ref:`PR_AttachThread` and + :ref:`PR_DetachThread` are obsolete. A native thread not created by NSPR + is automatically attached the first time it calls an NSPR function, + and automatically detached when it exits. + +In NSPR release 19980529B and earlier, it is necessary for a native +thread not created by NSPR to call :ref:`PR_AttachThread` before it calls +any NSPR functions, and call :ref:`PR_DetachThread` when it is done calling +NSPR functions. diff --git a/docs/nspr/reference/pr_available.rst b/docs/nspr/reference/pr_available.rst new file mode 100644 index 0000000000..8906bcace5 --- /dev/null +++ b/docs/nspr/reference/pr_available.rst @@ -0,0 +1,51 @@ +PR_Available +============ + +Determines the number of bytes (expressed as a 32-bit integer) that are +available for reading beyond the current read-write pointer in a +specified file or socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Available(PRFileDesc *fd); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``fd`` + Pointer to a :ref:`PRFileDesc` object representing a file or socket. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the function completes successfully, it returns the number of + bytes that are available for reading. For a normal file, these are + the bytes beyond the current file pointer. +- If the function fails, it returns the value -1. The error code can + then be retrieved via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_Available` works on normal files and sockets. :ref:`PR_Available` +does not work with pipes on Win32 platforms. + + +See Also +-------- + +If the number of bytes available for reading is out of the range of a +32-bit integer, use :ref:`PR_Available64`. diff --git a/docs/nspr/reference/pr_available64.rst b/docs/nspr/reference/pr_available64.rst new file mode 100644 index 0000000000..7ee2dd07a7 --- /dev/null +++ b/docs/nspr/reference/pr_available64.rst @@ -0,0 +1,51 @@ +PR_Available64 +============== + +Determines the number of bytes (expressed as a 32-bit integer) that are +available for reading beyond the current read-write pointer in a +specified file or socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt64 PR_Available64(PRFileDesc *fd); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``fd`` + Pointer to a :ref:`PRFileDesc` object representing a file or socket. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the function completes successfully, it returns the number of + bytes that are available for reading. For a normal file, these are + the bytes beyond the current file pointer. +- If the function fails, it returns the value -1. The error code can + then be retrieved via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_Available64` works on normal files and sockets. :ref:`PR_Available` +does not work with pipes on Win32 platforms. + + +See Also +-------- + +If the number of bytes available for reading is within the range of a +32-bit integer, use :ref:`PR_Available`. diff --git a/docs/nspr/reference/pr_bind.rst b/docs/nspr/reference/pr_bind.rst new file mode 100644 index 0000000000..25bba0bcd1 --- /dev/null +++ b/docs/nspr/reference/pr_bind.rst @@ -0,0 +1,54 @@ +PR_Bind +======= + +Binds an address to a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Bind( + PRFileDesc *fd, + const PRNetAddr *addr); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``addr`` + A pointer to a :ref:`PRNetAddr` object representing the address to which + the socket will be bound. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful binding of an address to a socket, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. Further information can be obtained + by calling :ref:`PR_GetError`. + + +Description +----------- + +When a new socket is created, it has no address bound to it. :ref:`PR_Bind` +assigns the specified address (also known as name) to the socket. If you +do not care about the exact IP address assigned to the socket, set the +``inet.ip`` field of :ref:`PRNetAddr` to :ref:`PR_htonl`\ (``PR_INADDR_ANY``). +If you do not care about the TCP/UDP port assigned to the socket, set +the ``inet.port`` field of :ref:`PRNetAddr` to 0. + +Note that if :ref:`PR_Connect` is invoked on a socket that is not bound, it +implicitly binds an arbitrary address the socket. + +Call :ref:`PR_GetSockName` to obtain the address (name) bound to a socket. diff --git a/docs/nspr/reference/pr_blockclockinterrupts.rst b/docs/nspr/reference/pr_blockclockinterrupts.rst new file mode 100644 index 0000000000..936dedb877 --- /dev/null +++ b/docs/nspr/reference/pr_blockclockinterrupts.rst @@ -0,0 +1,14 @@ +PR_BlockClockInterrupts +======================= + +Blocks the timer signal used for preemptive scheduling. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_BlockClockInterrupts(void); diff --git a/docs/nspr/reference/pr_callback.rst b/docs/nspr/reference/pr_callback.rst new file mode 100644 index 0000000000..47798a77b5 --- /dev/null +++ b/docs/nspr/reference/pr_callback.rst @@ -0,0 +1,24 @@ +PR_CALLBACKimplementation +========================= + +Used to define pointers to functions that will be implemented by the +client but called from a (different) shared library. + + +Syntax +------ + +.. code:: + + #include <prtypes.h>type PR_CALLBACKimplementation + + +Description +----------- + +Functions that are implemented in an application (or shared library) +that are intended to be called from another shared library (such as +NSPR) must be declared with the ``PR_CALLBACK`` attribute. Normally such +functions are passed by reference (pointer to function). The +``PR_CALLBACK`` attribute is included as part of the function's +definition between its return value type and the function's name. diff --git a/docs/nspr/reference/pr_calloc.rst b/docs/nspr/reference/pr_calloc.rst new file mode 100644 index 0000000000..b36a89d9b4 --- /dev/null +++ b/docs/nspr/reference/pr_calloc.rst @@ -0,0 +1,42 @@ +PR_Calloc +========= + +Allocates zeroed memory from the heap for a number of objects of a given +size. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + void *PR_Calloc ( + PRUint32 nelem, + PRUint32 elsize); + + +Parameters +~~~~~~~~~~ + +``nelem`` + The number of elements of size ``elsize`` to be allocated. +``elsize`` + The size of an individual element. + + +Returns +~~~~~~~ + +An untyped pointer to the allocated memory, or if the allocation attempt +fails, ``NULL``. Call ``PR_GetError()`` to retrieve the error returned +by the libc function ``malloc()``. + + +Description +----------- + +This function allocates memory on the heap for the specified number of +objects of the specified size. All bytes in the allocated memory are +cleared. diff --git a/docs/nspr/reference/pr_callonce.rst b/docs/nspr/reference/pr_callonce.rst new file mode 100644 index 0000000000..912f1a3ac3 --- /dev/null +++ b/docs/nspr/reference/pr_callonce.rst @@ -0,0 +1,35 @@ +PR_CallOnce +=========== + +Ensures that subsystem initialization occurs only once. + + +Syntax +------ + +.. code:: + + PRStatus PR_CallOnce( + PRCallOnceType *once, + PRCallOnceFN func); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_CallOnce` has these parameters: + +``once`` + A pointer to an object of type :ref:`PRCallOnceType`. Initially (before + any threading issues exist), the object must be initialized to all + zeros. From that time on, the client should consider the object + read-only (or even opaque) and allow the runtime to manipulate its + content appropriately. +``func`` + A pointer to the function the calling client has designed to perform + the subsystem initialization. The function will be called once, at + most, for each subsystem to be initialized. It should return a + :ref:`PRStatus` indicating the result of the initialization process. + While the first thread executes this function, other threads + attempting the same initialization will be blocked until it has been + completed. diff --git a/docs/nspr/reference/pr_canceljob.rst b/docs/nspr/reference/pr_canceljob.rst new file mode 100644 index 0000000000..6d49445d75 --- /dev/null +++ b/docs/nspr/reference/pr_canceljob.rst @@ -0,0 +1,30 @@ +PR_CancelJob +============ + +Causes a previously queued job to be canceled. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRStatus) PR_CancelJob(PRJob *job); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``job`` + A pointer to a :ref:`PRJob` structure returned by a :ref:`PR_QueueJob` + function representing the job to be cancelled. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_centermonitor.rst b/docs/nspr/reference/pr_centermonitor.rst new file mode 100644 index 0000000000..8c135f844e --- /dev/null +++ b/docs/nspr/reference/pr_centermonitor.rst @@ -0,0 +1,57 @@ +PR_CEnterMonitor +================ + +Enters the lock associated with a cached monitor. + + +Syntax +------ + +.. code:: + + #include <prcmon.h> + + PRMonitor* PR_CEnterMonitor(void *address); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``address`` + A reference to the data that is to be protected by the monitor. This + reference must remain valid as long as there are monitoring + operations being performed. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, the function returns a pointer to the :ref:`PRMonitor` + associated with the value specified in the ``address`` parameter. +- If unsuccessful (the monitor cache needs to be expanded and the + system is out of memory), the function returns ``NULL``. + + +Description +----------- + +:ref:`PR_CEnterMonitor` uses the value specified in the ``address`` +parameter to find a monitor in the monitor cache, then enters the lock +associated with the monitor. If no match is found, an available monitor +is associated with the address and the monitor's entry count is +incremented (so it has a value of one). If a match is found, then either +the calling thread is already in the monitor (and this is a reentrant +call) or another thread is holding the monitor's mutex. In the former +case, the entry count is simply incremented and the function returns. In +the latter case, the calling thread is likely to find the monitor locked +by another thread and waits for that thread to exit before continuing. + +.. note:: + + **Note**: :ref:`PR_CEnterMonitor` and :ref:`PR_CExitMonitor` must be + paired--that is, there must be an exit for every entry--or the object + will never become available for any other thread. diff --git a/docs/nspr/reference/pr_cexitmonitor.rst b/docs/nspr/reference/pr_cexitmonitor.rst new file mode 100644 index 0000000000..91e95f9bff --- /dev/null +++ b/docs/nspr/reference/pr_cexitmonitor.rst @@ -0,0 +1,44 @@ +PR_CExitMonitor +=============== + +Decrement the entry count associated with a cached monitor. + + +Syntax +------ + +.. code:: + + #include <prcmon.h> + + PRStatus PR_CExitMonitor(void *address); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``address`` + The address of the protected object--the same address previously + passed to :ref:`PR_CEnterMonitor`. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. This may indicate that the address + parameter is invalid or that the calling thread is not in the + monitor. + + +Description +----------- + +Using the value specified in the address parameter to find a monitor in +the monitor cache, :ref:`PR_CExitMonitor` decrements the entry count +associated with the monitor. If the decremented entry count is zero, the +monitor is exited. diff --git a/docs/nspr/reference/pr_cleanup.rst b/docs/nspr/reference/pr_cleanup.rst new file mode 100644 index 0000000000..6f4a93717e --- /dev/null +++ b/docs/nspr/reference/pr_cleanup.rst @@ -0,0 +1,39 @@ +PR_Cleanup +========== + +Coordinates a graceful shutdown of NSPR. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + PRStatus PR_Cleanup(void); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If NSPR has been shut down successfully, ``PR_SUCCESS``. +- If the calling thread of this function is not the primordial thread, + ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_Cleanup` must be called by the primordial thread near the end of +the ``main`` function. + +:ref:`PR_Cleanup` attempts to synchronize the natural termination of the +process. It does so by blocking the caller, if and only if it is the +primordial thread, until all user threads have terminated. When the +primordial thread returns from ``main``, the process immediately and +silently exits. That is, the process (if necessary) forcibly terminates +any existing threads and exits without significant blocking and without +error messages or core files. diff --git a/docs/nspr/reference/pr_clearinterrupt.rst b/docs/nspr/reference/pr_clearinterrupt.rst new file mode 100644 index 0000000000..27900e40d9 --- /dev/null +++ b/docs/nspr/reference/pr_clearinterrupt.rst @@ -0,0 +1,29 @@ +PR_ClearInterrupt +================= + +Clears the interrupt request for the calling thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + void PR_ClearInterrupt(void); + + +Description +----------- + +Interrupting is a cooperative process, so it's possible that the thread +passed to :ref:`PR_Interrupt` may never respond to the interrupt request. +For example, the target thread may reach the agreed-on control point +without providing an opportunity for the runtime to notify the thread of +the interrupt request. In this case, the request for interrupt is still +pending with the thread and must be explicitly canceled. Therefore it is +sometimes necessary to call :ref:`PR_ClearInterrupt` to clear a previous +interrupt request. + +If no interrupt request is pending, :ref:`PR_ClearInterrupt` is a no-op. diff --git a/docs/nspr/reference/pr_clist_is_empty.rst b/docs/nspr/reference/pr_clist_is_empty.rst new file mode 100644 index 0000000000..1794a8b7b4 --- /dev/null +++ b/docs/nspr/reference/pr_clist_is_empty.rst @@ -0,0 +1,28 @@ +PR_CLIST_IS_EMPTY +================= + +Checks for an empty circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PRIntn PR_CLIST_IS_EMPTY (PRCList *listp); + + +Parameter +~~~~~~~~~ + +``listp`` + A pointer to the linked list. + + +Description +----------- + +PR_CLIST_IS_EMPTY returns a non-zero value if the specified list is an +empty list, otherwise returns zero. diff --git a/docs/nspr/reference/pr_close.rst b/docs/nspr/reference/pr_close.rst new file mode 100644 index 0000000000..1bf310c495 --- /dev/null +++ b/docs/nspr/reference/pr_close.rst @@ -0,0 +1,40 @@ +PR_Close +======== + +Closes a file descriptor. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Close(PRFileDesc *fd); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object. + + +Returns +~~~~~~~ + +One of the following values: + +- If file descriptor is closed successfully, ``PR_SUCCESS``. +- If the file descriptor is not closed successfully, ``PR_FAILURE``. + + +Description +----------- + +The file descriptor may represent a normal file, a socket, or an end +point of a pipe. On successful return, :ref:`PR_Close` frees the dynamic +memory and other resources identified by the ``fd`` parameter. diff --git a/docs/nspr/reference/pr_closedir.rst b/docs/nspr/reference/pr_closedir.rst new file mode 100644 index 0000000000..e7a586282f --- /dev/null +++ b/docs/nspr/reference/pr_closedir.rst @@ -0,0 +1,47 @@ +PR_CloseDir +=========== + +Closes the specified directory. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_CloseDir(PRDir *dir); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``dir`` + A pointer to a :ref:`PRDir` structure representing the directory to be + closed. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + retrieved via :ref:`PR_GetError`. + + +Description +----------- + +When a :ref:`PRDir` object is no longer needed, it must be closed and freed +with a call to :ref:`PR_CloseDir` call. Note that after a :ref:`PR_CloseDir` +call, any ``PRDirEntry`` object returned by a previous :ref:`PR_ReadDir` +call on the same :ref:`PRDir` object becomes invalid. + + +See Also +-------- + +:ref:`PR_OpenDir` diff --git a/docs/nspr/reference/pr_closefilemap.rst b/docs/nspr/reference/pr_closefilemap.rst new file mode 100644 index 0000000000..a6a5590729 --- /dev/null +++ b/docs/nspr/reference/pr_closefilemap.rst @@ -0,0 +1,40 @@ +PR_CloseFileMap +=============== + +Closes a file mapping. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_CloseFileMap(PRFileMap *fmap); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``fmap`` + The file mapping to be closed. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the memory region is successfully unmapped, ``PR_SUCCESS``. +- If the memory region is not successfully unmapped, ``PR_FAILURE``. + The error code can be retrieved via :ref:`PR_GetError`. + + +Description +----------- + +When a file mapping created with a call to :ref:`PR_CreateFileMap` is no +longer needed, it should be closed with a call to :ref:`PR_CloseFileMap`. diff --git a/docs/nspr/reference/pr_closesemaphore.rst b/docs/nspr/reference/pr_closesemaphore.rst new file mode 100644 index 0000000000..07d1aca46e --- /dev/null +++ b/docs/nspr/reference/pr_closesemaphore.rst @@ -0,0 +1,30 @@ +PR_CloseSemaphore +================= + +Closes a specified semaphore. + + +Syntax +------ + +.. code:: + + #include <pripcsem.h> + + NSPR_API(PRStatus) PR_CloseSemaphore(PRSem *sem); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``sem`` + A pointer to a ``PRSem`` structure returned from a call to + :ref:`PR_OpenSemaphore`. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_closesharedmemory.rst b/docs/nspr/reference/pr_closesharedmemory.rst new file mode 100644 index 0000000000..221b07f2ba --- /dev/null +++ b/docs/nspr/reference/pr_closesharedmemory.rst @@ -0,0 +1,32 @@ +PR_CloseSharedMemory +==================== + +Closes a shared memory segment identified by name. + + +Syntax +------ + +.. code:: + + #include <prshm.h> + + NSPR_API( PRStatus ) + PR_CloseSharedMemory( + PRSharedMemory *shm + ); + + +Parameter +~~~~~~~~~ + +The function has these parameter: + +shm + The handle returned from :ref:`PR_OpenSharedMemory`. + + +Returns +~~~~~~~ + +:ref:`PRStatus`. diff --git a/docs/nspr/reference/pr_cnotify.rst b/docs/nspr/reference/pr_cnotify.rst new file mode 100644 index 0000000000..d3c5163a81 --- /dev/null +++ b/docs/nspr/reference/pr_cnotify.rst @@ -0,0 +1,43 @@ +PR_CNotify +========== + +Notify a thread waiting on a change in the state of monitored data. + + +Syntax +------ + +.. code:: + + #include <prcmon.h> + + PRStatus PR_CNotify(void *address); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``address`` + The address of the monitored object. The calling thread must be in + the monitor defined by the value of the address. + + +Returns +~~~~~~~ + + - :ref:`PR_SUCCESS` indicates that the calling thread is the holder of the + mutex for the monitor referred to by the address parameter. + - :ref:`PR_FAILURE` indicates that the monitor has not been entered by the + calling thread. + + +Description +----------- + +Using the value specified in the ``address`` parameter to find a monitor +in the monitor cache, :ref:`PR_CNotify` notifies single a thread waiting +for the monitor's state to change. If a thread is waiting on the monitor +(having called :ref:`PR_CWait`), then that thread is made ready. As soon as +the thread is scheduled, it attempts to reenter the monitor. diff --git a/docs/nspr/reference/pr_cnotifyall.rst b/docs/nspr/reference/pr_cnotifyall.rst new file mode 100644 index 0000000000..80a7c2aeb9 --- /dev/null +++ b/docs/nspr/reference/pr_cnotifyall.rst @@ -0,0 +1,43 @@ +PR_CNotifyAll +============= + +Notifies all the threads waiting for a change in the state of monitored +data. + + +Syntax +------ + +.. code:: + + #include <prcmon.h> + + PRStatus PR_CNotifyAll(void *address); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``address`` + The address of the monitored object. The calling thread must be in + the monitor at the time :ref:`PR_CNotifyAll` is called. + + +Returns +~~~~~~~ + + - :ref:`PR_SUCCESS` indicates that the referenced monitor was located and + the calling thread was in the monitor. + - :ref:`PR_FAILURE` indicates that the referenced monitor could not be + located or that the calling thread was not in the monitor + + +Description +----------- + +Using the value specified in the address parameter to find a monitor in +the monitor cache, :ref:`PR_CNotifyAll` notifies all threads waiting for +the monitor's state to change. All of the threads waiting on the state +change are then scheduled to reenter the monitor. diff --git a/docs/nspr/reference/pr_cnvtf.rst b/docs/nspr/reference/pr_cnvtf.rst new file mode 100644 index 0000000000..f2b0fa88b5 --- /dev/null +++ b/docs/nspr/reference/pr_cnvtf.rst @@ -0,0 +1,45 @@ +PR_cnvtf +======== + +Converts a floating point number to a string. + + +Syntax +------ + +.. code:: + + #include <prdtoa.h> + + void PR_cnvtf ( + char *buf, + PRIntn bufsz, + PRIntn prcsn, + PRFloat64 fval); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``buf`` + The address of the buffer in which to store the result. +``bufsz`` + The size of the buffer provided to hold the result. +``prcsn`` + The number of digits of precision to which to generate the floating + point value. +``fval`` + The double-precision floating point number to be converted. + + +Description +----------- + +:ref:`PR_cnvtf` is a simpler interface to convert a floating point number +to a string. It conforms to the ECMA standard of Javascript +(ECMAScript). + +On return, the result is written to the buffer pointed to by ``buf`` of +size ``bufsz``. diff --git a/docs/nspr/reference/pr_connect.rst b/docs/nspr/reference/pr_connect.rst new file mode 100644 index 0000000000..10978df792 --- /dev/null +++ b/docs/nspr/reference/pr_connect.rst @@ -0,0 +1,67 @@ +PR_Connect +========== + +Initiates a connection on a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Connect( + PRFileDesc *fd, + const PRNetAddr *addr, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``addr`` + A pointer to the address of the peer to which the socket is to be + connected. +``timeout`` + A value of type :ref:`PRIntervalTime` specifying the time limit for + completion of the connect operation. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion of connection setup, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. Further information can be obtained + by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_Connect` is usually invoked on a TCP socket, but it may also be +invoked on a UDP socket. Both cases are discussed here. + +If the socket is a TCP socket, :ref:`PR_Connect` establishes a TCP +connection to the peer. If the socket is not bound, it will be bound to +an arbitrary local address. + +:ref:`PR_Connect` blocks until either the connection is successfully +established or an error occurs. The function uses the lesser of the +provided timeout and the OS's connect timeout. In particular, if you +specify ``PR_INTERVAL_NO_TIMEOUT`` as the timeout, the OS's connection +time limit will be used. + +If the socket is a UDP socket, there is no connection setup to speak of, +since UDP is connectionless. If :ref:`PR_Connect` is invoked on a UDP +socket, it has an overloaded meaning: :ref:`PR_Connect` merely saves the +specified address as the default peer address for the socket, so that +subsequently one can send and receive datagrams from the socket using +:ref:`PR_Send` and :ref:`PR_Recv` instead of the usual :ref:`PR_SendTo` and +:ref:`PR_RecvFrom`. diff --git a/docs/nspr/reference/pr_connectcontinue.rst b/docs/nspr/reference/pr_connectcontinue.rst new file mode 100644 index 0000000000..b4ba88bc20 --- /dev/null +++ b/docs/nspr/reference/pr_connectcontinue.rst @@ -0,0 +1,53 @@ +PR_ConnectContinue +================== + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_ConnectContinue( + PRFileDesc *fd, + PRInt16 out_flags); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. + +``out_flags`` + The out_flags field of the poll descriptor returned by + `PR_Poll() <PR_Poll>`__. + + +Returns +~~~~~~~ + +- If the nonblocking connect has successfully completed, + PR_ConnectContinue returns PR_SUCCESS. +- If PR_ConnectContinue() returns PR_FAILURE, call PR_GetError(): +- PR_IN_PROGRESS_ERROR: the nonblocking connect is still in + progress and has not completed yet. The caller should poll the file + descriptor for the in_flags PR_POLL_WRITE|PR_POLL_EXCEPT and retry + PR_ConnectContinue later when PR_Poll() returns. +- Other errors: the nonblocking connect has failed with this + error code. + + +Description +----------- + +Continue a nonblocking connect. After a nonblocking connect is initiated +with PR_Connect() (which fails with PR_IN_PROGRESS_ERROR), one should +call PR_Poll() on the socket, with the in_flags PR_POLL_WRITE \| +PR_POLL_EXCEPT. When PR_Poll() returns, one calls PR_ConnectContinue() +on the socket to determine whether the nonblocking connect has completed +or is still in progress. Repeat the PR_Poll(), PR_ConnectContinue() +sequence until the nonblocking connect has completed. diff --git a/docs/nspr/reference/pr_convertipv4addrtoipv6.rst b/docs/nspr/reference/pr_convertipv4addrtoipv6.rst new file mode 100644 index 0000000000..c19535ccc2 --- /dev/null +++ b/docs/nspr/reference/pr_convertipv4addrtoipv6.rst @@ -0,0 +1,30 @@ +PR_ConvertIPv4AddrToIPv6 +======================== + +Converts an IPv4 address into an (IPv4-mapped) IPv6 address. + + +Syntax +~~~~~~ + +.. code:: + + #include <prnetdb.h> + + void PR_ConvertIPv4AddrToIPv6( + PRUint32 v4addr, + PRIPv6Addr *v6addr + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``v4addr`` + The IPv4 address to convert into an IPv4-mapped IPv6 address. This + must be specified in network byte order. +``v6addr`` + A pointer to a buffer, allocated by the caller, that is filled in + with the IPv6 address on return. diff --git a/docs/nspr/reference/pr_createfilemap.rst b/docs/nspr/reference/pr_createfilemap.rst new file mode 100644 index 0000000000..c347d94e5e --- /dev/null +++ b/docs/nspr/reference/pr_createfilemap.rst @@ -0,0 +1,66 @@ +PR_CreateFileMap +================ + +Creates a file mapping object. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileMap* PR_CreateFileMap( + PRFileDesc *fd, + PRInt64 size, + PRFileMapProtect prot); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing the file that is to + be mapped to memory. +``size`` + Size of the file specified by ``fd``. +``prot`` + Protection option for read and write accesses of a file mapping. This + parameter consists of one of the following options: + + - :ref:`PR_PROT_READONLY`. Read-only access. + - :ref:`PR_PROT_READWRITE`. Readable, and write is shared. + - :ref:`PR_PROT_WRITECOPY`. Readable, and write is private + (copy-on-write). + + +Returns +~~~~~~~ + +- If successful, a file mapping of type :ref:`PRFileMap`. +- If unsuccessful, ``NULL``. + + +Description +----------- + +The ``PRFileMapProtect`` enumeration used in the ``prot`` parameter is +defined as follows: + +.. code:: + + typedef enum PRFileMapProtect { + PR_PROT_READONLY, + PR_PROT_READWRITE, + PR_PROT_WRITECOPY + } PRFileMapProtect; + +:ref:`PR_CreateFileMap` only prepares for the mapping a file to memory. The +returned file-mapping object must be passed to :ref:`PR_MemMap` to actually +map a section of the file to memory. + +The file-mapping object should be closed with a :ref:`PR_CloseFileMap` call +when it is no longer needed. diff --git a/docs/nspr/reference/pr_createiolayerstub.rst b/docs/nspr/reference/pr_createiolayerstub.rst new file mode 100644 index 0000000000..3deb061db2 --- /dev/null +++ b/docs/nspr/reference/pr_createiolayerstub.rst @@ -0,0 +1,46 @@ +PR_CreateIOLayerStub +==================== + +Creates a new layer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_CreateIOLayerStub( + PRDescIdentity ident + PRIOMethods const *methods); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``ident`` + The identity to be associated with the new layer. +``methods`` + A pointer to the :ref:`PRIOMethods` structure specifying the functions + for the new layer. + + +Returns +~~~~~~~ + +A new file descriptor for the specified layer. + + +Description +----------- + +A new layer may be allocated by calling :ref:`PR_CreateIOLayerStub`. The +file descriptor returned contains the pointer to the I/O methods table +provided. The runtime neither modifies the table nor tests its +correctness. + +The caller should override appropriate contents of the file descriptor +returned before pushing it onto the protocol stack. diff --git a/docs/nspr/reference/pr_createpipe.rst b/docs/nspr/reference/pr_createpipe.rst new file mode 100644 index 0000000000..3409cb9912 --- /dev/null +++ b/docs/nspr/reference/pr_createpipe.rst @@ -0,0 +1,53 @@ +PR_CreatePipe +============= + +Creates an anonymous pipe and retrieves file descriptors for the read +and write ends of the pipe. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_CreatePipe( + PRFileDesc **readPipe, + PRFileDesc **writePipe); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``readPipe`` + A pointer to a :ref:`PRFileDesc` pointer. On return, this parameter + contains the file descriptor for the read end of the pipe. +``writePipe`` + A pointer to a :ref:`PRFileDesc` pointer. On return, this parameter + contains the file descriptor for the write end of the pipe. + + +Returns +~~~~~~~ + +The function returns one of these values: + +- If the pipe is successfully created, ``PR_SUCCESS``. +- If the pipe is not successfully created, ``PR_FAILURE``. The error + code can be retrieved via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_CreatePipe` creates an anonymous pipe. Data written into the write +end of the pipe can be read from the read end of the pipe. Pipes are +useful for interprocess communication between a parent and a child +process. When the pipe is no longer needed, both ends should be closed +with calls to :ref:`PR_Close`. + +:ref:`PR_CreatePipe` is currently implemented on Unix, Linux, Mac OS X, and +Win32 only. diff --git a/docs/nspr/reference/pr_createthread.rst b/docs/nspr/reference/pr_createthread.rst new file mode 100644 index 0000000000..cf733e624d --- /dev/null +++ b/docs/nspr/reference/pr_createthread.rst @@ -0,0 +1,79 @@ +PR_CreateThread +=============== + +Creates a new thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRThread* PR_CreateThread( + PRThreadType type, + void (*start)(void *arg), + void *arg, + PRThreadPriority priority, + PRThreadScope scope, + PRThreadState state, + PRUint32 stackSize); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_CreateThread` has the following parameters: + +``type`` + Specifies that the thread is either a user thread + (``PR_USER_THREAD``) or a system thread (``PR_SYSTEM_THREAD``). +``start`` + A pointer to the thread's root function, which is called as the root + of the new thread. Returning from this function is the only way to + terminate a thread. +``arg`` + A pointer to the root function's only parameter. NSPR does not assess + the type or the validity of the value passed in this parameter. +``priority`` + The initial priority of the newly created thread. +``scope`` + Specifies your preference for making the thread local + (``PR_LOCAL_THREAD``), global (``PR_GLOBAL_THREAD``) or global bound + (``PR_GLOBAL_BOUND_THREAD``). However, NSPR may override this + preference if necessary. +``state`` + Specifies whether the thread is joinable (``PR_JOINABLE_THREAD``) or + unjoinable (``PR_UNJOINABLE_THREAD``). +``stackSize`` + Specifies your preference for the size of the stack, in bytes, + associated with the newly created thread. If you pass zero in this + parameter, :ref:`PR_CreateThread` chooses the most favorable + machine-specific stack size. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, a pointer to the new thread. This pointer remains + valid until the thread returns from its root function. +- If unsuccessful, (for example, if system resources are unavailable), + ``NULL``. + + +Description +----------- + +If you want the thread to start up waiting for the creator to do +something, enter a lock before creating the thread and then have the +thread's root function enter and exit the same lock. When you are ready +for the thread to run, exit the lock. For more information on locks and +thread synchronization, see `Introduction to +NSPR <Introduction_to_NSPR>`__. + +If you want to detect the completion of the created thread, make it +joinable. You can then use :ref:`PR_JoinThread` to synchronize the +termination of another thread. diff --git a/docs/nspr/reference/pr_createthreadpool.rst b/docs/nspr/reference/pr_createthreadpool.rst new file mode 100644 index 0000000000..a4e6021991 --- /dev/null +++ b/docs/nspr/reference/pr_createthreadpool.rst @@ -0,0 +1,43 @@ +PR_CreateThreadPool +=================== + +Create a new hash table. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRThreadPool *) + PR_CreateThreadPool( + PRInt32 initial_threads, + PRInt32 max_threads, + PRUint32 stacksize + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``initial_threads`` + The number of threads to be created within this thread pool. +``max_threads`` + The limit on the number of threads that will be created to server the + thread pool. +``stacksize`` + Size of the stack allocated to each thread in the thread. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRThreadPool` structure or ``NULL`` on error. + + +Description +~~~~~~~~~~~ diff --git a/docs/nspr/reference/pr_cwait.rst b/docs/nspr/reference/pr_cwait.rst new file mode 100644 index 0000000000..9af79c42c3 --- /dev/null +++ b/docs/nspr/reference/pr_cwait.rst @@ -0,0 +1,63 @@ +PR_CWait +======== + +Wait for a notification that a monitor's state has changed. + + +Syntax +------ + +.. code:: + + #include <prcmon.h> + + PRStatus PR_CWait( + void *address, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``address`` + The address of the protected object--the same address previously + passed to :ref:`PR_CEnterMonitor`. +``timeout`` + The amount of time (in :ref:`PRIntervalTime` units) that the thread is + willing to wait for an explicit notification before being + rescheduled. If you specify ``PR_INTERVAL_NO_TIMEOUT``, the function + returns if and only if the object is notified. + + +Returns +~~~~~~~ + +The function returns one of the following values: + + - :ref:`PR_SUCCESS` indicates either that the monitored object has been + notified or that the interval specified in the timeout parameter has + been exceeded. + - :ref:`PR_FAILURE` indicates either that the monitor could not be located + in the cache or that the monitor was located and the calling thread + was not the thread that held the monitor's mutex. + + +Description +----------- + +Using the value specified in the ``address`` parameter to find a monitor +in the monitor cache, :ref:`PR_CWait` waits for a notification that the +monitor's state has changed. While the thread is waiting, it exits the +monitor (just as if it had called :ref:`PR_CExitMonitor` as many times as +it had called :ref:`PR_CEnterMonitor`). When the wait has finished, the +thread regains control of the monitor's lock with the same entry count +as before the wait began. + +The thread waiting on the monitor resumes execution when the monitor is +notified (assuming the thread is the next in line to receive the notify) +or when the interval specified in the ``timeout`` parameter has been +exceeded. When the thread resumes execution, it is the caller's +responsibility to test the state of the monitored data to determine the +appropriate action. diff --git a/docs/nspr/reference/pr_delete.rst b/docs/nspr/reference/pr_delete.rst new file mode 100644 index 0000000000..f3d5523836 --- /dev/null +++ b/docs/nspr/reference/pr_delete.rst @@ -0,0 +1,38 @@ +PR_Delete +========= + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Delete(const char *name); + + +Parameters +~~~~~~~~~~ + +The function has the following parameter: + +``name`` + The pathname of the file to be deleted. + + +Returns +~~~~~~~ + +One of the following values: + +- If file is deleted successfully, ``PR_SUCCESS``. +- If the file is not deleted, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_Delete` deletes a file with the specified pathname ``name``. If +the function fails, the error code can then be retrieved via +:ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_delete_.rst b/docs/nspr/reference/pr_delete_.rst new file mode 100644 index 0000000000..c441801d25 --- /dev/null +++ b/docs/nspr/reference/pr_delete_.rst @@ -0,0 +1,37 @@ +PR_DELETE +========= + + +Allocates memory of a specified size from the heap. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + void PR_DELETE(_ptr); + + +Parameter +~~~~~~~~~ + +``_ptr`` + The address of memory to be returned to the heap. Must be an lvalue + (an expression that can appear on the left side of an assignment + statement). + + +Returns +~~~~~~~ + +Nothing. + + +Description +----------- + +This macro returns allocated memory to the heap from the specified +location and sets ``_ptr`` to ``NULL``. diff --git a/docs/nspr/reference/pr_deletesemaphore.rst b/docs/nspr/reference/pr_deletesemaphore.rst new file mode 100644 index 0000000000..bfef8e89eb --- /dev/null +++ b/docs/nspr/reference/pr_deletesemaphore.rst @@ -0,0 +1,30 @@ +PR_DeleteSemaphore +================== + +Removes a semaphore specified by name from the system. + + +Syntax +------ + +.. code:: + + #include <pripcsem.h> + + NSPR_API(PRStatus) PR_DeleteSemaphore(const char *name); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``name`` + The name of a semaphore that was previously created via a call to + :ref:`PR_OpenSemaphore`. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_deletesharedmemory.rst b/docs/nspr/reference/pr_deletesharedmemory.rst new file mode 100644 index 0000000000..3e39bd6e04 --- /dev/null +++ b/docs/nspr/reference/pr_deletesharedmemory.rst @@ -0,0 +1,32 @@ +PR_DeleteSharedMemory +===================== + +Deletes a shared memory segment identified by name. + + +Syntax +------ + +.. code:: + + #include <prshm.h> + + NSPR_API( PRStatus ) + PR_DeleteSharedMemory( + const char *name + ); + + +Parameter +~~~~~~~~~ + +The function has these parameter: + +shm + The handle returned from :ref:`PR_OpenSharedMemory`. + + +Returns +~~~~~~~ + +:ref:`PRStatus`. diff --git a/docs/nspr/reference/pr_destroycondvar.rst b/docs/nspr/reference/pr_destroycondvar.rst new file mode 100644 index 0000000000..2347a2d389 --- /dev/null +++ b/docs/nspr/reference/pr_destroycondvar.rst @@ -0,0 +1,30 @@ +PR_DestroyCondVar +================= + +Destroys a condition variable. + + +Syntax +------ + +.. code:: + + #include <prcvar.h> + + void PR_DestroyCondVar(PRCondVar *cvar); + + +Parameter +~~~~~~~~~ + +:ref:`PR_DestroyCondVar` has one parameter: + +``cvar`` + A pointer to the condition variable object to be destroyed. + + +Description +----------- + +Before calling :ref:`PR_DestroyCondVar`, the caller is responsible for +ensuring that the condition variable is no longer in use. diff --git a/docs/nspr/reference/pr_destroylock.rst b/docs/nspr/reference/pr_destroylock.rst new file mode 100644 index 0000000000..9ed566efc5 --- /dev/null +++ b/docs/nspr/reference/pr_destroylock.rst @@ -0,0 +1,30 @@ +PR_DestroyLock +============== + +Destroys a specified lock object. + + +Syntax +------ + +.. code:: + + #include <prlock.h> + + void PR_DestroyLock(PRLock *lock); + + +Parameter +~~~~~~~~~ + +:ref:`PR_DestroyLock` has one parameter: + +``lock`` + A pointer to a lock object. + +Caution +------- + +The caller must ensure that no thread is currently in a lock-specific +function. Locks do not provide self-referential protection against +deletion. diff --git a/docs/nspr/reference/pr_destroymonitor.rst b/docs/nspr/reference/pr_destroymonitor.rst new file mode 100644 index 0000000000..4d9d9e58ac --- /dev/null +++ b/docs/nspr/reference/pr_destroymonitor.rst @@ -0,0 +1,31 @@ +PR_DestroyMonitor +================= + +Destroys a monitor object. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + void PR_DestroyMonitor(PRMonitor *mon); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``mon`` + A reference to an existing structure of type :ref:`PRMonitor`. + + +Description +----------- + +The caller is responsible for guaranteeing that the monitor is no longer +in use before calling :ref:`PR_DestroyMonitor`. There must be no thread +(including the calling thread) in the monitor or waiting on the monitor. diff --git a/docs/nspr/reference/pr_destroypollableevent.rst b/docs/nspr/reference/pr_destroypollableevent.rst new file mode 100644 index 0000000000..526a90258d --- /dev/null +++ b/docs/nspr/reference/pr_destroypollableevent.rst @@ -0,0 +1,33 @@ +PR_DestroyPollableEvent +======================= + +Close the file descriptor associated with a pollable event and release +related resources. + + +Syntax +------ + +.. code:: + + NSPR_API(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``event`` + Pointer to a :ref:`PRFileDesc` structure previously created via a call + to :ref:`PR_NewPollableEvent`. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + retrieved via :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_detachsharedmemory.rst b/docs/nspr/reference/pr_detachsharedmemory.rst new file mode 100644 index 0000000000..1954762970 --- /dev/null +++ b/docs/nspr/reference/pr_detachsharedmemory.rst @@ -0,0 +1,35 @@ +PR_DetachSharedMemory +===================== + +Unmaps a shared memory segment identified by name. + + +Syntax +------ + +.. code:: + + #include <prshm.h> + + NSPR_API( PRStatus ) + PR_DetachSharedMemory( + PRSharedMemory *shm, + void *addr + ); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +shm + The handle returned from :ref:`PR_OpenSharedMemory`. +addr + The address to which the shared memory segment is mapped. + + +Returns +~~~~~~~ + +:ref:`PRStatus`. diff --git a/docs/nspr/reference/pr_detachthread.rst b/docs/nspr/reference/pr_detachthread.rst new file mode 100644 index 0000000000..c140f60c37 --- /dev/null +++ b/docs/nspr/reference/pr_detachthread.rst @@ -0,0 +1,57 @@ +PR_DetachThread +=============== + +.. container:: blockIndicator obsolete obsoleteHeader + + | **Obsolete** + | This feature is obsolete. Although it may still work in some + browsers, its use is discouraged since it could be removed at any + time. Try to avoid using it. + +Disassociates a PRThread object from a native thread. + + +Syntax +------ + +.. code:: + + #include <pprthread.h> + + void PR_DetachThread(void); + + +Parameters +~~~~~~~~~~ + +PR_DetachThread has no parameters. + + +Returns +~~~~~~~ + +The function returns nothing. + + +Description +----------- + +This function detaches the NSPR thread from the currently executing +native thread. The thread object and all related data attached to it are +destroyed. The exit process is invoked. The call returns after the NSPR +thread object is destroyed. + +This call is needed only if you attached the thread using +:ref:`PR_AttachThread`. + +.. note:: + + **Note**: As of NSPR release v3.0, :ref:`PR_AttachThread` and + :ref:`PR_DetachThread` are obsolete. A native thread not created by NSPR + is automatically attached the first time it calls an NSPR function, + and automatically detached when it exits. + +In NSPR release 19980529B and earlier, it is necessary for a native +thread not created by NSPR to call :ref:`PR_AttachThread` before it calls +any NSPR functions, and call :ref:`PR_DetachThread` when it is done calling +NSPR functions. diff --git a/docs/nspr/reference/pr_disableclockinterrupts.rst b/docs/nspr/reference/pr_disableclockinterrupts.rst new file mode 100644 index 0000000000..9296395873 --- /dev/null +++ b/docs/nspr/reference/pr_disableclockinterrupts.rst @@ -0,0 +1,14 @@ +PR_DisableClockInterrupts +========================= + +Disables timer signals used for preemptive scheduling. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_DisableClockInterrupts(void); diff --git a/docs/nspr/reference/pr_dtoa.rst b/docs/nspr/reference/pr_dtoa.rst new file mode 100644 index 0000000000..d2f5d73bac --- /dev/null +++ b/docs/nspr/reference/pr_dtoa.rst @@ -0,0 +1,93 @@ +PR_dtoa +======= + +Converts a floating point number to a string. + + +Syntax +------ + +.. code:: + + #include <prdtoa.h> + + PRStatus PR_dtoa( + PRFloat64 d, + PRIntn mode, + PRIntn ndigits, + PRIntn *decpt, + PRIntn *sign, + char **rve, + char *buf, + PRSize bufsz); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``d`` + The floating point number to be converted to a string. +``mode`` + The type of conversion to employ. +``ndigits`` + The number of digits desired in the output string. +``decpt`` + A pointer to a memory location where the runtime will store the + offset, relative to the beginning of the output string, of the + conversion's decimal point. +``sign`` + A location where the runtime can store an indication that the + conversion was of a negative value. +``*rve`` + If not ``NULL`` this location is set to the address of the end of the + result. +``buf`` + The address of the buffer in which to store the result. +``bufsz`` + The size of the buffer provided to hold the result. + +Results +~~~~~~~ + +The principle output is the null-terminated string stored in ``buf``. If +``rve`` is not ``NULL``, ``*rve`` is set to point to the end of the +returned value. + + +Description +----------- + +This function converts the specified floating point number to a string, +using the method specified by ``mode``. Possible modes are: + +``0`` + Shortest string that yields ``d`` when read in and rounded to + nearest. +``1`` + Like 0, but with Steele & White stopping rule. For example, with IEEE + 754 arithmetic, mode 0 gives 1e23 whereas mode 1 gives + 9.999999999999999e22. +``2`` + ``max(1, ndigits)`` significant digits. This gives a return value + similar to that of ``ecvt``, except that trailing zeros are + suppressed. +``3`` + Through ``ndigits`` past the decimal point. This gives a return value + similar to that from ``fcvt``, except that trailing zeros are + suppressed, and ``ndigits`` can be negative. +``4,5,8,9`` + Same as modes 2 and 3, but using\ *left to right* digit generation. +``6-9`` + Same as modes 2 and 3, but do not try fast floating-point estimate + (if applicable). +``all others`` + Treated as mode 2. + +Upon return, the buffer specified by ``buf`` and ``bufsz`` contains the +converted string. Trailing zeros are suppressed. Sufficient space is +allocated to the return value to hold the suppressed trailing zeros. + +If the input parameter ``d`` is\ *+Infinity*,\ *-Infinity* or\ *NAN*, +``*decpt`` is set to 9999. diff --git a/docs/nspr/reference/pr_entermonitor.rst b/docs/nspr/reference/pr_entermonitor.rst new file mode 100644 index 0000000000..501104e082 --- /dev/null +++ b/docs/nspr/reference/pr_entermonitor.rst @@ -0,0 +1,41 @@ +PR_EnterMonitor +=============== + +Enters the lock associated with a specified monitor. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + void PR_EnterMonitor(PRMonitor *mon); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``mon`` + A reference to an existing structure of type :ref:`PRMonitor`. + + +Description +----------- + +When the calling thread returns, it will have acquired the monitor's +lock. Attempts to acquire the lock for a monitor that is held by some +other thread will result in the caller blocking. The operation is +neither timed nor interruptible. + +If the monitor's entry count is greater than zero and the calling thread +is recognized as the holder of the lock, :ref:`PR_EnterMonitor` increments +the entry count by one and returns. If the entry count is greater than +zero and the calling thread is not recognized as the holder of the lock, +the thread is blocked until the entry count reaches zero. When the entry +count reaches zero (or if it is already zero), the entry count is +incremented by one and the calling thread is recorded as the lock's +holder. diff --git a/docs/nspr/reference/pr_enumerateaddrinfo.rst b/docs/nspr/reference/pr_enumerateaddrinfo.rst new file mode 100644 index 0000000000..d978766da6 --- /dev/null +++ b/docs/nspr/reference/pr_enumerateaddrinfo.rst @@ -0,0 +1,58 @@ +PR_EnumerateAddrInfo +==================== + + +Enumerates each of the possible network addresses of a ``PRAddrInfo`` +structure, acquired from :ref:`PR_GetAddrInfoByName`. + + +Syntax +~~~~~~ + +.. code:: + + #include <prnetdb.h> + + void *PR_EnumerateAddrInfo( + void *enumPtr, + const PRAddrInfo *addrInfo, + PRUint16 port, + PRNetAddr *result); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``enumPtr`` + The index pointer of the enumeration. To begin an enumeration, this + argument is set to ``NULL``. To continue an enumeration (thereby + getting successive addresses from the ``PRAddrInfo`` structure), the + value should be set to the function's last returned value. The + enumeration is complete when a value of ``NULL`` is returned. +``addrInfo`` + A pointer to a ``PRAddrInfo`` structure returned by + :ref:`PR_GetAddrInfoByName`. +``port`` + The port number to be assigned as part of the :ref:`PRNetAddr` + structure. This parameter is not checked for validity. +``result`` + On input, a pointer to a :ref:`PRNetAddr` structure. On output, this + structure is filled in by the runtime if the result of the call is + not ``NULL``. + + +Returns +~~~~~~~ + +The function returns the value you should specify in the ``enumPtr`` +parameter for the next call of the enumerator. If the function returns +``NULL``, the enumeration is ended. + + +Description +----------- + +:ref:`PR_EnumerateAddrInfo` is a stateless enumerator. The principle input, +the ``PRAddrInfo`` structure, is not modified. diff --git a/docs/nspr/reference/pr_enumeratehostent.rst b/docs/nspr/reference/pr_enumeratehostent.rst new file mode 100644 index 0000000000..a808730330 --- /dev/null +++ b/docs/nspr/reference/pr_enumeratehostent.rst @@ -0,0 +1,61 @@ +PR_EnumerateHostEnt +=================== + +Evaluates each of the possible addresses of a :ref:`PRHostEnt` structure, +acquired from :ref:`PR_GetHostByName` or :ref:`PR_GetHostByAddr`. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRIntn PR_EnumerateHostEnt( + PRIntn enumIndex, + const PRHostEnt *hostEnt, + PRUint16 port, + PRNetAddr *address); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``enumIndex`` + The index of the enumeration. To begin an enumeration, this argument + is set to zero. To continue an enumeration (thereby getting + successive addresses from the host entry structure), the value should + be set to the function's last returned value. The enumeration is + complete when a value of zero is returned. +``hostEnt`` + A pointer to a :ref:`PRHostEnt` structure obtained from + :ref:`PR_GetHostByName` or :ref:`PR_GetHostByAddr`. +``port`` + The port number to be assigned as part of the :ref:`PRNetAddr` + structure. This parameter is not checked for validity. +``address`` + On input, a pointer to a :ref:`PRNetAddr` structure. On output, this + structure is filled in by the runtime if the result of the call is + greater than 0. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, the function returns the value you should specify in + the ``enumIndex`` parameter for the next call of the enumerator. If + the function returns 0, the enumeration is ended. +- If unsuccessful, the function returns -1. You can retrieve the reason + for the failure by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_EnumerateHostEnt` is a stateless enumerator. The principle input, +the :ref:`PRHostEnt` structure, is not modified. diff --git a/docs/nspr/reference/pr_exitmonitor.rst b/docs/nspr/reference/pr_exitmonitor.rst new file mode 100644 index 0000000000..3cb8463e85 --- /dev/null +++ b/docs/nspr/reference/pr_exitmonitor.rst @@ -0,0 +1,44 @@ +PR_ExitMonitor +============== + +Decrements the entry count associated with a specified monitor and, if +the entry count reaches zero, releases the monitor's lock. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + PRStatus PR_ExitMonitor(PRMonitor *mon); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``mon`` + A reference to an existing structure of type :ref:`PRMonitor`. The + monitor object referenced must be one for which the calling thread + currently holds the lock. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful (the calling thread has not entered the monitor), + ``PR_FAILURE``. + + +Description +----------- + +If the decremented entry count is zero, :ref:`PR_ExitMonitor` releases the +monitor's lock. Threads that were blocked trying to enter the monitor +will be rescheduled. diff --git a/docs/nspr/reference/pr_explodetime.rst b/docs/nspr/reference/pr_explodetime.rst new file mode 100644 index 0000000000..066ccfcd01 --- /dev/null +++ b/docs/nspr/reference/pr_explodetime.rst @@ -0,0 +1,46 @@ +PR_ExplodeTime +============== + +Converts an absolute time to a clock/calendar time. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + void PR_ExplodeTime( + PRTime usecs, + PRTimeParamFn params, + PRExplodedTime *exploded); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``usecs`` + An absolute time in the :ref:`PRTime` format. +``params`` + A time parameter callback function. +``exploded`` + A pointer to a location where the converted time can be stored. This + location must be preallocated by the caller. + + +Returns +~~~~~~~ + +Nothing; the buffer pointed to by ``exploded`` is filled with the +exploded time. + + +Description +----------- + +This function converts the specified absolute time to a clock/calendar +time in the specified time zone. Upon return, the location pointed to by +the exploded parameter contains the converted time value. diff --git a/docs/nspr/reference/pr_exportfilemapasstring.rst b/docs/nspr/reference/pr_exportfilemapasstring.rst new file mode 100644 index 0000000000..649a373a34 --- /dev/null +++ b/docs/nspr/reference/pr_exportfilemapasstring.rst @@ -0,0 +1,47 @@ +PR_ExportFileMapAsString +======================== + +Creates a string identifying a :ref:`PRFileMap`. + + +Syntax +------ + +.. code:: + + #include <prshma.h> + + NSPR_API( PRStatus ) + PR_ExportFileMapAsString( + PRFileMap *fm, + PRSize bufsize, + char *buf + ); + +#. define PR_FILEMAP_STRING_BUFSIZE 128 + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fm`` + A pointer to the :ref:`PRFileMap` to be represented as a string. +``bufsize`` + sizeof(buf) +``buf`` + A pointer to abuffer of length ``PR_FILEMAP_STRING_BUFSIZE``. + + +Returns +~~~~~~~ + +:ref:`PRStatus` + + +Description +----------- + +Creates an identifier, as a string, from a :ref:`PRFileMap` object +previously created with :ref:`PR_OpenAnonFileMap`. diff --git a/docs/nspr/reference/pr_extern.rst b/docs/nspr/reference/pr_extern.rst new file mode 100644 index 0000000000..64d38654b6 --- /dev/null +++ b/docs/nspr/reference/pr_extern.rst @@ -0,0 +1,30 @@ +PR_EXTERN +========= + +Used to define the prototypes for functions or variables that are to be +exported from a shared library. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + PR_EXTERN(type)prototype + + +Description +----------- + +:ref:`PR_EXTERN` is used to define externally visible routines and globals. +For syntax details for each platform, see +`prtypes.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtypes.h>`__. +The macro includes the proper specifications to declare the target +``extern`` and set up other required linkages. + +.. warning:: + + **Warning**: Some platforms do not allow the use of the underscore + character (_) as the first character of an exported symbol. diff --git a/docs/nspr/reference/pr_familyinet.rst b/docs/nspr/reference/pr_familyinet.rst new file mode 100644 index 0000000000..251286257f --- /dev/null +++ b/docs/nspr/reference/pr_familyinet.rst @@ -0,0 +1,23 @@ +PR_FamilyInet +============= + +Gets the value of the address family for Internet Protocol. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRUint16 PR_FamilyInet(void); + + +Returns +~~~~~~~ + +The value of the address family for Internet Protocol. This is usually +``PR_AF_INET``, but can also be ``PR_AF_INET6`` if IPv6 is enabled. The +returned value can be assigned to the ``inet.family`` field of a +:ref:`PRNetAddr` object. diff --git a/docs/nspr/reference/pr_findsymbol.rst b/docs/nspr/reference/pr_findsymbol.rst new file mode 100644 index 0000000000..c30ccfabfe --- /dev/null +++ b/docs/nspr/reference/pr_findsymbol.rst @@ -0,0 +1,52 @@ +PR_FindSymbol +============= + +``PR_FindSymbol()`` will return an untyped reference to a symbol in a +particular library given the identity of the library and a textual +representation of the symbol in question. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + void* PR_FindSymbol ( + PRLibrary *lib, + const char *name); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``lib`` + A valid reference to a loaded library, as returned by + :ref:`PR_LoadLibrary`, or ``NULL``. +``name`` + A textual representation of the symbol to resolve. + + +Returns +~~~~~~~ + +An untyped pointer. + + +Description +----------- + +This function finds and returns an untyped reference to the specified +symbol in the specified library. If the lib parameter is ``NULL``, all +libraries known to the runtime and the main program are searched in an +unspecified order. + +Use this function to look up functions or data symbols in a shared +library. Getting a pointer to a symbol in a library does indicate that +the library is available when the search was made. The runtime does +nothing to ensure the continued validity of the symbol. If the library +is unloaded, for instance, the results of any :ref:`PR_FindSymbol` calls +become invalid as well. diff --git a/docs/nspr/reference/pr_findsymbolandlibrary.rst b/docs/nspr/reference/pr_findsymbolandlibrary.rst new file mode 100644 index 0000000000..0df683a76c --- /dev/null +++ b/docs/nspr/reference/pr_findsymbolandlibrary.rst @@ -0,0 +1,59 @@ +PR_FindSymbolAndLibrary +======================= + +Finds a symbol in one of the currently loaded libraries, and returns +both the symbol and the library in which it was found. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + void* PR_FindSymbolAndLibrary ( + const char *name, + PRLibrary **lib); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``name`` + The textual representation of the symbol to locate. +``lib`` + A reference to a location at which the runtime will store the library + in which the symbol was discovered. This location must be + pre-allocated by the caller. + + +Returns +~~~~~~~ + +If successful, returns a non-``NULL`` pointer to the found symbol, and +stores a pointer to the library in which it was found at the location +pointed to by lib. + +If the symbol could not be found, returns ``NULL``. + + +Description +----------- + +This function finds the specified symbol in one of the currently loaded +libraries. It returns the address of the symbol. Upon return, the +location pointed to by the parameter lib contains a pointer to the +library that contains that symbol. The location must be pre-allocated by +the caller. + +The function returns ``NULL`` if no such function can be found. The +order in which the known libraries are searched in not specified. This +function is equivalent to calling first :ref:`PR_LoadLibrary`, then +:ref:`PR_FindSymbol`. + +The identity returned from this function must be the target of a +:ref:`PR_UnloadLibrary` in order to return the runtime to its original +state. diff --git a/docs/nspr/reference/pr_free.rst b/docs/nspr/reference/pr_free.rst new file mode 100644 index 0000000000..577955d205 --- /dev/null +++ b/docs/nspr/reference/pr_free.rst @@ -0,0 +1,33 @@ +PR_Free +======= + +Frees allocated memory in the heap. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + void PR_Free(void *ptr); + + +Parameter +~~~~~~~~~ + +``ptr`` + A pointer to the memory to be freed. + + +Returns +~~~~~~~ + +Nothing. + + +Description +----------- + +This function frees the memory addressed by ``ptr`` in the heap. diff --git a/docs/nspr/reference/pr_freeaddrinfo.rst b/docs/nspr/reference/pr_freeaddrinfo.rst new file mode 100644 index 0000000000..bc004c037e --- /dev/null +++ b/docs/nspr/reference/pr_freeaddrinfo.rst @@ -0,0 +1,32 @@ +PR_FreeAddrInfo +=============== + + +Destroys the ``PRAddrInfo`` structure returned by +:ref:`PR_GetAddrInfoByName`. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + void PR_EnumerateAddrInfo(PRAddrInfo *addrInfo); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``addrInfo`` + A pointer to a ``PRAddrInfo`` structure returned by a successful call + to :ref:`PR_GetAddrInfoByName`. + + +Returns +~~~~~~~ + +The function doesn't return anything. diff --git a/docs/nspr/reference/pr_freeif.rst b/docs/nspr/reference/pr_freeif.rst new file mode 100644 index 0000000000..3d8f9baba5 --- /dev/null +++ b/docs/nspr/reference/pr_freeif.rst @@ -0,0 +1,34 @@ +PR_FREEIF +========= + +Conditionally frees allocated memory. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + void PR_FREEIF(_ptr); + + +Parameter +~~~~~~~~~ + +``_ptr`` + The address of memory to be returned to the heap. + + +Returns +~~~~~~~ + +Nothing. + + +Description +----------- + +This macro returns memory to the heap when ``_ptr`` is not ``NULL``. If +``_ptr`` is ``NULL``, the macro has no effect. diff --git a/docs/nspr/reference/pr_freelibraryname.rst b/docs/nspr/reference/pr_freelibraryname.rst new file mode 100644 index 0000000000..2091277c79 --- /dev/null +++ b/docs/nspr/reference/pr_freelibraryname.rst @@ -0,0 +1,39 @@ +PR_FreeLibraryName +================== + +Frees memory allocated by NSPR for library names and path names. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + void PR_FreeLibraryName(char *mem); + + +Parameters +~~~~~~~~~~ + +The function has this parameter: + +``mem`` + A reference to a character array that was previously allocated by the + dynamic library runtime. + + +Returns +~~~~~~~ + +Nothing. + + +Description +----------- + +This function deletes the storage allocated by the runtime in the +functions described previously. It is important to use this function to +rather than calling directly into ``malloc`` in order to isolate the +runtime's semantics regarding storage management. diff --git a/docs/nspr/reference/pr_getaddrinfobyname.rst b/docs/nspr/reference/pr_getaddrinfobyname.rst new file mode 100644 index 0000000000..fd428124da --- /dev/null +++ b/docs/nspr/reference/pr_getaddrinfobyname.rst @@ -0,0 +1,48 @@ +PR_GetAddrInfoByName +==================== + +Looks up a host by name. Equivalent to ``getaddrinfo(host, NULL, ...)`` +of RFC 3493. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRAddrInfo *PR_GetAddrInfoByName( + const char *hostname, + PRUint16 af, + PRIntn flags); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``hostname`` + The character string defining the host name of interest. +``af`` + The address family. May be ``PR_AF_UNSPEC`` or ``PR_AF_INET``. +``flags`` + May be either ``PR_AI_ADDRCONFIG`` or + ``PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME``. Include + ``PR_AI_NOCANONNAME`` to suppress the determination of the canonical + name corresponding to ``hostname`` + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, a pointer to the opaque ``PRAddrInfo`` structure + containing the results of the host lookup. Use + :ref:`PR_EnumerateAddrInfo` to inspect the :ref:`PRNetAddr` values stored + in this structure. When no longer needed, this pointer must be + destroyed with a call to :ref:`PR_FreeAddrInfo`. +- If unsuccessful, ``NULL``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getcanonnamefromaddrinfo.rst b/docs/nspr/reference/pr_getcanonnamefromaddrinfo.rst new file mode 100644 index 0000000000..b84fe84604 --- /dev/null +++ b/docs/nspr/reference/pr_getcanonnamefromaddrinfo.rst @@ -0,0 +1,33 @@ +PR_GetCanonNameFromAddrInfo +=========================== + +Extracts the canonical name of the hostname passed to +:ref:`PR_GetAddrInfoByName`. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + const char *PR_GetCanonNameFromAddrInfo(const PRAddrInfo *addrInfo); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``addrInfo`` + A pointer to a ``PRAddrInfo`` structure returned by a successful call + to :ref:`PR_GetAddrInfoByName`. + + +Returns +~~~~~~~ + +The function returns a const pointer to the canonical hostname stored in +the given ``PRAddrInfo`` structure. This pointer is invalidated once the +``PRAddrInfo`` structure is destroyed by a call to :ref:`PR_FreeAddrInfo`. diff --git a/docs/nspr/reference/pr_getconnectstatus.rst b/docs/nspr/reference/pr_getconnectstatus.rst new file mode 100644 index 0000000000..a8753e546e --- /dev/null +++ b/docs/nspr/reference/pr_getconnectstatus.rst @@ -0,0 +1,48 @@ +PR_GetConnectStatus +=================== + +Get the completion status of a nonblocking connection. + + +Syntax +------ + +.. code:: + + PRStatus PR_GetConnectStatus(const PRPollDesc *pd); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``pd`` + A pointer to a ``PRPollDesc`` satructure whose ``fd`` field is the + socket and whose ``in_flags`` field must contain ``PR_POLL_WRITE`` + and ``PR_POLL_EXCEPT``. + + +Returns +~~~~~~~ + +The function returns one of these values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + retrieved via :ref:`PR_GetError`. + +If :ref:`PR_GetError` returns ``PR_IN_PROGRESS_ERROR``, the nonblocking +connection is still in progress and has not completed yet.Other errors +indicate that the connection has failed. + + +Description +----------- + +After :ref:`PR_Connect` on a nonblocking socket fails with +``PR_IN_PROGRESS_ERROR``, you may wait for the connection to complete by +calling :ref:`PR_Poll` on the socket with the ``in_flags`` +``PR_POLL_WRITE`` \| ``PR_POLL_EXCEPT``. When :ref:`PR_Poll` returns, call +:ref:`PR_GetConnectStatus` on the socket to determine whether the +nonblocking connect has succeeded or failed. diff --git a/docs/nspr/reference/pr_getcurrentthread.rst b/docs/nspr/reference/pr_getcurrentthread.rst new file mode 100644 index 0000000000..b198ce1a6a --- /dev/null +++ b/docs/nspr/reference/pr_getcurrentthread.rst @@ -0,0 +1,32 @@ +PR_GetCurrentThread +=================== + +Returns the current thread object for the currently running code. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRThread* PR_GetCurrentThread(void); + + +Returns +~~~~~~~ + +Always returns a valid reference to the calling thread--a self-identity. + + +Description +~~~~~~~~~~~ + +The currently running thread may discover its own identity by calling +:ref:`PR_GetCurrentThread`. + +.. note:: + + **Note**: This is the only safe way to establish the identity of a + thread. Creation and enumeration are both subject to race conditions. diff --git a/docs/nspr/reference/pr_getdefaultiomethods.rst b/docs/nspr/reference/pr_getdefaultiomethods.rst new file mode 100644 index 0000000000..674dea0366 --- /dev/null +++ b/docs/nspr/reference/pr_getdefaultiomethods.rst @@ -0,0 +1,31 @@ +PR_GetDefaultIOMethods +====================== + +Gets the default I/O methods table. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + const PRIOMethods* PR_GetDefaultIOMethods(void); + + +Returns +~~~~~~~ + +If successful, the function returns a pointer to a :ref:`PRIOMethods` +structure. + + +Description +----------- + +After using :ref:`PR_GetDefaultIOMethods` to identify the default I/O +methods table, you can select elements from that table with which to +build your own layer's methods table. You may not modify the default I/O +methods table directly. You can pass your own layer's methods table to +:ref:`PR_CreateIOLayerStub` to create your new layer. diff --git a/docs/nspr/reference/pr_getdesctype.rst b/docs/nspr/reference/pr_getdesctype.rst new file mode 100644 index 0000000000..66cbf58397 --- /dev/null +++ b/docs/nspr/reference/pr_getdesctype.rst @@ -0,0 +1,58 @@ +PR_GetDescType +============== + +Describes what type of file is referenced by a specified file +descriptor. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRDescType PR_GetDescType(PRFileDesc *file); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``file`` + A pointer to a :ref:`PRFileDesc` object whose descriptor type is to be + returned. + + +Returns +~~~~~~~ + +The function returns a ``PRDescType`` enumeration constant that +describes the type of file. + + +Description +----------- + +The ``PRDescType`` enumeration is defined as follows: + +.. code:: + + typedef enum PRDescType { + PR_DESC_FILE = 1, + PR_DESC_SOCKET_TCP = 2, + PR_DESC_SOCKET_UDP = 3, + PR_DESC_LAYERED = 4 + } PRDescType; + +The enumeration has the following enumerators: + +``PR_DESC_FILE`` + The :ref:`PRFileDesc` object represents a normal file. +``PR_DESC_SOCKET_TCP`` + The :ref:`PRFileDesc` object represents a TCP socket. +``PR_DESC_SOCKET_UDP`` + The :ref:`PRFileDesc` object represents a UDP socket. +``PR_DESC_LAYERED`` + The :ref:`PRFileDesc` object is a layered file descriptor. diff --git a/docs/nspr/reference/pr_geterror.rst b/docs/nspr/reference/pr_geterror.rst new file mode 100644 index 0000000000..9a50d8aacc --- /dev/null +++ b/docs/nspr/reference/pr_geterror.rst @@ -0,0 +1,23 @@ +PR_GetError +=========== + +Returns the current thread's last set platform-independent error code. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + PRErrorCode PR_GetError(void) + + +Returns +~~~~~~~ + +The value returned is a 32-bit number. NSPR provides no direct +interpretation of the number's value. NSPR does use :ref:`PR_SetError` to +set error numbers defined in `Error +Codes <NSPR_Error_Handling#Error_Code>`__. diff --git a/docs/nspr/reference/pr_geterrortext.rst b/docs/nspr/reference/pr_geterrortext.rst new file mode 100644 index 0000000000..e8a0508b8a --- /dev/null +++ b/docs/nspr/reference/pr_geterrortext.rst @@ -0,0 +1,32 @@ +PR_GetErrorText +=============== + +Copies the current thread's current error text without altering the text +as stored in the thread's context. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + PRInt32 PR_GetErrorText(char *text); + + +Parameters +~~~~~~~~~~ + +The function has one parameter: + +``text`` + On output, the array pointed to contains the thread's current error + text. + + +Returns +------- + +The actual number of bytes copied. If the result is zero, ``text`` is +unaffected. diff --git a/docs/nspr/reference/pr_geterrortextlength.rst b/docs/nspr/reference/pr_geterrortextlength.rst new file mode 100644 index 0000000000..c771e4c1ee --- /dev/null +++ b/docs/nspr/reference/pr_geterrortextlength.rst @@ -0,0 +1,22 @@ +PR_GetErrorTextLength +===================== + +Gets the length of the error text. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + PRInt32 PR_GetErrorTextLength(void) + + +Returns +~~~~~~~ + +If a zero is returned, no error text is currently set. Otherwise, the +value returned is sufficient to contain the error text currently +available. diff --git a/docs/nspr/reference/pr_getfileinfo.rst b/docs/nspr/reference/pr_getfileinfo.rst new file mode 100644 index 0000000000..1d1daf5427 --- /dev/null +++ b/docs/nspr/reference/pr_getfileinfo.rst @@ -0,0 +1,55 @@ +PR_GetFileInfo +============== + +Gets information about a file with a specified pathname. File size is +expressed as a 32-bit integer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetFileInfo( + const char *fn, + PRFileInfo *info); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fn`` + The pathname of the file to get information about. +``info`` + A pointer to a file information object (see :ref:`PRFileInfo`). On + output, :ref:`PR_GetFileInfo` writes information about the given file to + the file information object. + + +Returns +~~~~~~~ + +One of the following values: + +- If the file information is successfully obtained, ``PR_SUCCESS``. +- If the file information is not successfully obtained, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_GetFileInfo` stores information about the file with the specified +pathname in the :ref:`PRFileInfo` structure pointed to by ``info``. The +file size is returned as an unsigned 32-bit integer. + + +See Also +-------- + +For the 64-bit version of this function, see :ref:`PR_GetFileInfo64`. To +get equivalent information on a file that's already open, use +:ref:`PR_GetOpenFileInfo`. diff --git a/docs/nspr/reference/pr_getfileinfo64.rst b/docs/nspr/reference/pr_getfileinfo64.rst new file mode 100644 index 0000000000..f57217103a --- /dev/null +++ b/docs/nspr/reference/pr_getfileinfo64.rst @@ -0,0 +1,55 @@ +PR_GetFileInfo64 +================ + +Gets information about a file with a specified pathname. File size is +expressed as a 64-bit integer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetFileInfo64( + const char *fn, + PRFileInfo64 *info); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fn`` + The pathname of the file to get information about. +``info`` + A pointer to a 64-bit file information object (see :ref:`PRFileInfo64`). + On output, :ref:`PR_GetFileInfo64` writes information about the given + file to the file information object. + + +Returns +~~~~~~~ + +One of the following values: + +- If the file information is successfully obtained, ``PR_SUCCESS``. +- If the file information is not successfully obtained, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_GetFileInfo64` stores information about the file with the +specified pathname in the :ref:`PRFileInfo64` structure pointed to by +``info``. The file size is returned as an unsigned 64-bit integer. + + +See Also +-------- + +For the 32-bit version of this function, see :ref:`PR_GetFileInfo`. To get +equivalent information on a file that's already open, use +:ref:`PR_GetOpenFileInfo64`. diff --git a/docs/nspr/reference/pr_gethostbyaddr.rst b/docs/nspr/reference/pr_gethostbyaddr.rst new file mode 100644 index 0000000000..7140c5c5dd --- /dev/null +++ b/docs/nspr/reference/pr_gethostbyaddr.rst @@ -0,0 +1,57 @@ +PR_GetHostByAddr +================ + +Looks up a host entry by its network address. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_GetHostByAddr( + const PRNetAddr *hostaddr, + char *buf, + PRIntn bufsize, + PRHostEnt *hostentry); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``hostaddr`` + A pointer to the IP address of host in question. +``buf`` + A pointer to a buffer, allocated by the caller, that is filled in + with host data on output. All of the pointers in the ``hostentry`` + structure point to data saved in this buffer. This buffer is + referenced by the runtime during a call to :ref:`PR_EnumerateHostEnt`. +``bufsize`` + Number of bytes in the ``buf`` parameter. The buffer must be at least + :ref:`PR_NETDB_BUF_SIZE` bytes. +``hostentry`` + This structure is allocated by the caller. On output, this structure + is filled in by the runtime if the function returns ``PR_SUCCESS``. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. + + +Description +~~~~~~~~~~~ + +:ref:`PR_GetHostByAddr` is used to perform reverse lookups of network +addresses. That is, given a valid network address (of type +:ref:`PRNetAddr`), :ref:`PR_GetHostByAddr` discovers the address' primary +name, any aliases, and any other network addresses for the same host. diff --git a/docs/nspr/reference/pr_gethostbyname.rst b/docs/nspr/reference/pr_gethostbyname.rst new file mode 100644 index 0000000000..f1a1a4a108 --- /dev/null +++ b/docs/nspr/reference/pr_gethostbyname.rst @@ -0,0 +1,48 @@ +PR_GetHostByName +================ + +Looks up a host by name. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_GetHostByName( + const char *hostname, + char *buf, + PRIntn bufsize, + PRHostEnt *hostentry); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``hostname`` + The character string defining the host name of interest. +``buf`` + A pointer to a buffer, allocated by the caller, that is filled in + with host data on output. All of the pointers in the ``hostentry`` + structure point to data saved in this buffer. This buffer is + referenced by the runtime during a call to :ref:`PR_EnumerateHostEnt`. +``bufsize`` + Number of bytes in the ``buf`` parameter. The buffer must be at least + :ref:`PR_NETDB_BUF_SIZE` bytes. +``hostentry`` + This structure is allocated by the caller. On output, this structure + is filled in by the runtime if the function returns ``PR_SUCCESS``. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getidentitieslayer.rst b/docs/nspr/reference/pr_getidentitieslayer.rst new file mode 100644 index 0000000000..9a15f9b60d --- /dev/null +++ b/docs/nspr/reference/pr_getidentitieslayer.rst @@ -0,0 +1,48 @@ +PR_GetIdentitiesLayer +===================== + +Finds the layer with the specified identity in the specified stack of +layers. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_GetIdentitiesLayer( + PRFileDesc* stack, + PRDescIdentity id); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``stack`` + A pointer to a :ref:`PRFileDesc` object that is a layer in a stack of + layers. +``id`` + The identity of the specified layer. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, a pointer to a file descriptor of the layer with the + specified identity in the given stack of layers. +- If not successful, ``NULL``. + + +Description +----------- + +The stack of layers to be searched is specified by the fd parameter, +which is a layer in the stack. Both the layers underneath fd and the +layers above fd are searched to find the layer with the specified +identity. diff --git a/docs/nspr/reference/pr_getinheritedfilemap.rst b/docs/nspr/reference/pr_getinheritedfilemap.rst new file mode 100644 index 0000000000..62d93058f4 --- /dev/null +++ b/docs/nspr/reference/pr_getinheritedfilemap.rst @@ -0,0 +1,44 @@ +PR_GetInheritedFileMap +====================== + +Imports a :ref:`PRFileMap` previously exported by my parent process via +``PR_CreateProcess``. + + +Syntax +------ + +.. code:: + + #include <prshma.h> + + NSPR_API( PRFileMap *) + PR_GetInheritedFileMap( + const char *shmname + ); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``shmname`` + The name provided to :ref:`PR_ProcessAttrSetInheritableFileMap`. + + +Returns +~~~~~~~ + +Pointer to :ref:`PRFileMap` or ``NULL`` on error. + + +Description +----------- + +:ref:`PR_GetInheritedFileMap` retrieves a PRFileMap object exported from +its parent process via ``PR_CreateProcess``. + +.. note:: + + **Note:** This function is not implemented. diff --git a/docs/nspr/reference/pr_getlayersidentity.rst b/docs/nspr/reference/pr_getlayersidentity.rst new file mode 100644 index 0000000000..88a06602bc --- /dev/null +++ b/docs/nspr/reference/pr_getlayersidentity.rst @@ -0,0 +1,30 @@ +PR_GetLayersIdentity +==================== + +Gets the unique identity for the layer of the specified file descriptor. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRDescIdentity PR_GetLayersIdentity(PRFileDesc* fd); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``fd`` + A pointer to a file descriptor. + + +Returns +~~~~~~~ + +If successful, the function returns the :ref:`PRDescIdentity` for the layer +of the specified file descriptor. diff --git a/docs/nspr/reference/pr_getlibraryname.rst b/docs/nspr/reference/pr_getlibraryname.rst new file mode 100644 index 0000000000..7bbe3b05ef --- /dev/null +++ b/docs/nspr/reference/pr_getlibraryname.rst @@ -0,0 +1,53 @@ +PR_GetLibraryName +================= + +Constructs a full library path name. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + char* PR_GetLibraryName ( + const char *dir, + const char *lib); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``dir`` + A ``NULL``-terminated string representing the path name of the + library, as returned by :ref:`PR_GetLibraryPath`. +``lib`` + The leaf name of the library of interest. + + +Returns +~~~~~~~ + +If successful, returns a new character string containing a constructed +path name. In case of error, returns ``NULL``. + + +Description +----------- + +This function constructs a full path name from the specified directory +name and library name. The constructed path name refers to the actual +dynamically loaded library. It is suitable for use in the +:ref:`PR_LoadLibrary` call. + +This function does not test for existence of the specified file, it just +constructs the full filename. The way the name is constructed is system +dependent. + +If sufficient storage cannot be allocated to contain the constructed +path name, the function returns ``NULL``. Storage for the result is +allocated by the runtime and becomes the responsibility of the caller. +When it is no longer used, free it using :ref:`PR_FreeLibraryName`. diff --git a/docs/nspr/reference/pr_getlibrarypath.rst b/docs/nspr/reference/pr_getlibrarypath.rst new file mode 100644 index 0000000000..c604edc9cd --- /dev/null +++ b/docs/nspr/reference/pr_getlibrarypath.rst @@ -0,0 +1,37 @@ +PR_GetLibraryPath +================= + +Retrieves the current default library path. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + char* PR_GetLibraryPath(void); + + +Parameters +~~~~~~~~~~ + +The function has no parameters. + + +Returns +~~~~~~~ + +A copy of the default library pathname string. In case of error, returns +NULL. + + +Description +----------- + +This function retrieves the current default library pathname, copies it, +and returns the copy. If sufficient storage cannot be allocated to +contain the copy, the function returns ``NULL``. Storage for the result +is allocated by the runtime and becomes the responsibility of the +caller. When it is no longer used, free it using :ref:`PR_FreeLibraryName`. diff --git a/docs/nspr/reference/pr_getnameforidentity.rst b/docs/nspr/reference/pr_getnameforidentity.rst new file mode 100644 index 0000000000..4db060c81f --- /dev/null +++ b/docs/nspr/reference/pr_getnameforidentity.rst @@ -0,0 +1,41 @@ +PR_GetNameForIdentity +===================== + +Gets the string associated with a layer's unique identity. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + const char* PR_GetNameForIdentity(PRDescIdentity ident); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``ident`` + A layer's identity. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, the function returns a pointer to the string + associated with the specified layer. +- If unsuccessful, the function returns ``NULL``. + + +Description +----------- + +A string may be associated with a layer when the layer is created. The +string is copied by the runtime, and :ref:`PR_GetNameForIdentity` returns a +pointer to that copy. diff --git a/docs/nspr/reference/pr_getopenfileinfo.rst b/docs/nspr/reference/pr_getopenfileinfo.rst new file mode 100644 index 0000000000..7722606141 --- /dev/null +++ b/docs/nspr/reference/pr_getopenfileinfo.rst @@ -0,0 +1,54 @@ +PR_GetOpenFileInfo +================== + +Gets an open file's information. File size is expressed as a 32-bit +integer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetOpenFileInfo( + PRFileDesc *fd, + PRFileInfo *info); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object for an open file. +``info`` + A pointer to a :ref:`PRFileInfo` object. On output, information about + the given file is written into the file information object. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If file information is successfully obtained, ``PR_SUCCESS``. +- If file information is not successfully obtained, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_GetOpenFileInfo` obtains the file type (normal file, directory, or +other), file size (as a 32-bit integer), and the file creation and +modification times of the open file represented by the file descriptor. + + +See Also +-------- + +For the 64-bit version of this function, see :ref:`PR_GetOpenFileInfo64`. +To get equivalent information on a file that's not already open, use +:ref:`PR_GetFileInfo`. diff --git a/docs/nspr/reference/pr_getopenfileinfo64.rst b/docs/nspr/reference/pr_getopenfileinfo64.rst new file mode 100644 index 0000000000..aa0fa83fa2 --- /dev/null +++ b/docs/nspr/reference/pr_getopenfileinfo64.rst @@ -0,0 +1,56 @@ +PR_GetOpenFileInfo64 +==================== + +Gets an open file's information. File size is expressed as a 64-bit +integer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetOpenFileInfo64( + PRFileDesc *fd, + PRFileInfo *info); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object for an open file. +``info`` + A pointer to a :ref:`PRFileInfo64` object. On output, information about + the given file is written into the file information object. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If file information is successfully obtained, ``PR_SUCCESS``. +- If file information is not successfully obtained, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_GetOpenFileInfo64` is the 64-bit version of +:ref:`PR_GetOpenFileInfo`. It obtains the file type (normal file, +directory, or other), file size (as a 64-bit integer), and the creation +and modification times of the open file represented by the file +descriptor. + + +See Also +-------- + +For the 32-bit version of this function, see :ref:`PR_GetOpenFileInfo`. To +get equivalent information on a file that's not already open, use +:ref:`PR_GetFileInfo64`. diff --git a/docs/nspr/reference/pr_getoserror.rst b/docs/nspr/reference/pr_getoserror.rst new file mode 100644 index 0000000000..5068018a63 --- /dev/null +++ b/docs/nspr/reference/pr_getoserror.rst @@ -0,0 +1,31 @@ +PR_GetOSError +============= + +Returns the current thread's last set OS-specific error code. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + PRInt32 PR_GetOSError(void) + + +Returns +~~~~~~~ + +The value returned is a 32-bit signed number. Its interpretation is left +to the caller. + + +Description +----------- + +Used for platform-specific code that requires the underlying OS error. +For portability, clients should not create dependencies on the values of +OS-specific error codes. However, this information is preserved, along +with a platform neutral error code, on a per thread basis. It is most +useful during development. diff --git a/docs/nspr/reference/pr_getpeername.rst b/docs/nspr/reference/pr_getpeername.rst new file mode 100644 index 0000000000..d45896444d --- /dev/null +++ b/docs/nspr/reference/pr_getpeername.rst @@ -0,0 +1,35 @@ +PR_GetPeerName +============== + +Gets the network address of the connected peer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetPeerName( + PRFileDesc *fd, + PRNetAddr *addr); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``addr`` + On return, the address of the peer connected to the socket. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getprotobyname.rst b/docs/nspr/reference/pr_getprotobyname.rst new file mode 100644 index 0000000000..d558b334dd --- /dev/null +++ b/docs/nspr/reference/pr_getprotobyname.rst @@ -0,0 +1,47 @@ +PR_GetProtoByName +================= + +Looks up a protocol entry based on the protocol's name. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_GetProtoByName( + const char* protocolname, + char* buffer, + PRInt32 bufsize, + PRProtoEnt* result); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``protocolname`` + A pointer to the character string of the protocol's name. +``buffer`` + A pointer to a scratch buffer for the runtime to return result. This + buffer is allocated by the caller. +``bufsize`` + Number of bytes in the ``buffer`` parameter. The buffer must be at + least :ref:`PR_NETDB_BUF_SIZE` bytes. +``result`` + On input, a pointer to a :ref:`PRProtoEnt` structure. On output, this + structure is filled in by the runtime if the function returns + ``PR_SUCCESS``. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getprotobynumber.rst b/docs/nspr/reference/pr_getprotobynumber.rst new file mode 100644 index 0000000000..423b1fa16a --- /dev/null +++ b/docs/nspr/reference/pr_getprotobynumber.rst @@ -0,0 +1,47 @@ +PR_GetProtoByNumber +=================== + +Looks up a protocol entry based on protocol's number. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_GetProtoByNumber( + PRInt32 protocolnumber, + char* buffer, + PRInt32 bufsize, + PRProtoEnt* result); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``protocolnumber`` + The number assigned to the protocol. +``buffer`` + A pointer to a scratch buffer for the runtime to return result. This + buffer is allocated by the caller. +``bufsize`` + Number of bytes in the ``buffer`` parameter. The buffer must be at + least :ref:`PR_NETDB_BUF_SIZE` bytes. +``result`` + On input, a pointer to a :ref:`PRNetAddr` structure. On output, this + structure is filled in by the runtime if the function returns + ``PR_SUCCESS``. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getrandomnoise.rst b/docs/nspr/reference/pr_getrandomnoise.rst new file mode 100644 index 0000000000..1d482572f1 --- /dev/null +++ b/docs/nspr/reference/pr_getrandomnoise.rst @@ -0,0 +1,56 @@ +PR_GetRandomNoise +================= + +Produces a random value for use as a seed value for another random +number generator. + + +Syntax +------ + +.. code:: + + #include <prrng.h> + + NSPR_API(PRSize) PR_GetRandomNoise( + void *buf, + PRSize size + ); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``buf`` + A pointer to a caller-supplied buffer to contain the generated random + number. ``buf`` must be at least as large as specified in ``size``. + +``size`` + The size, in bytes, of the requested random number. + + +Returns +~~~~~~~ + +:ref:`PRSize` value equal to the size of the random number actually +generated, or zero. The generated size may be less than the size +requested. A return value of zero means that :ref:`PR_GetRandomNoise` is +not implemented on this platform, or there is no available noise to be +returned at the time of the call. + + +Description +----------- + +:ref:`PR_GetRandomNoise` provides a random value, depending on platform. +The length of the random value is dependent on the platform and its +ability to provide a random value at that moment. + +:ref:`PR_GetRandomNoise` is intended to provide a "seed" value for a +another random number generator that may be suitable for cryptographic +operations. This implies that the random value provided may not be, by +itself, cryptographically secure. The value generated by +:ref:`PR_GetRandomNoise` is at best, extremely difficult to predict and is +as nondeterministic as the underlying platform permits. diff --git a/docs/nspr/reference/pr_getsocketoption.rst b/docs/nspr/reference/pr_getsocketoption.rst new file mode 100644 index 0000000000..3e2112300c --- /dev/null +++ b/docs/nspr/reference/pr_getsocketoption.rst @@ -0,0 +1,40 @@ +PR_GetSocketOption +================== + +Retrieves the socket options set for a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetSocketOption( + PRFileDesc *fd, + PRSocketOptionData *data); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing the socket whose + options are to be retrieved. +``data`` + A pointer to a structure of type :ref:`PRSocketOptionData`. On input, + the ``option`` field of this structure must be set to indicate which + socket option to retrieve for the socket represented by the ``fd`` + parameter. On output, this structure contains the requested socket + option data. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getsockname.rst b/docs/nspr/reference/pr_getsockname.rst new file mode 100644 index 0000000000..7cb6804a3c --- /dev/null +++ b/docs/nspr/reference/pr_getsockname.rst @@ -0,0 +1,35 @@ +PR_GetSockName +============== + +Gets network address for a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_GetSockName( + PRFileDesc *fd, + PRNetAddr *addr); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing the socket. +``addr`` + On return, the address of the socket. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_getspecialfd.rst b/docs/nspr/reference/pr_getspecialfd.rst new file mode 100644 index 0000000000..4cb50fc3c1 --- /dev/null +++ b/docs/nspr/reference/pr_getspecialfd.rst @@ -0,0 +1,56 @@ +PR_GetSpecialFD +=============== + +Gets the file descriptor that represents the standard input, output, or +error stream. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_GetSpecialFD(PRSpecialFD id); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``id`` + A pointer to an enumerator of type ``PRSpecialFD``, indicating the + type of I/O stream desired: ``PR_StandardInput``, + ``PR_StandardOutput``, or ``PR_StandardError``. + + +Returns +~~~~~~~ + +If the ``id`` parameter is valid, :ref:`PR_GetSpecialFD` returns a file +descriptor that represents the corresponding standard I/O stream. +Otherwise, :ref:`PR_GetSpecialFD` returns ``NULL`` and sets the error to +``PR_INVALID_ARGUMENT_ERROR``. + + +Description +----------- + +Type ``PRSpecialFD`` is defined as follows: + +.. code:: + + typedef enum PRSpecialFD{ + PR_StandardInput, + PR_StandardOutput, + PR_StandardError + } PRSpecialFD; + +``#define PR_STDIN PR_GetSpecialFD(PR_StandardInput)`` +``#define PR_STDOUT PR_GetSpecialFD(PR_StandardOutput)`` +``#define PR_STDERR PR_GetSpecialFD(PR_StandardError)`` + +File descriptors returned by :ref:`PR_GetSpecialFD` are owned by the +runtime and should not be closed by the caller. diff --git a/docs/nspr/reference/pr_getthreadpriority.rst b/docs/nspr/reference/pr_getthreadpriority.rst new file mode 100644 index 0000000000..ff678c9938 --- /dev/null +++ b/docs/nspr/reference/pr_getthreadpriority.rst @@ -0,0 +1,23 @@ +PR_GetThreadPriority +==================== + +Returns the priority of a specified thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRThreadPriority PR_GetThreadPriority(PRThread *thread); + + +Parameter +~~~~~~~~~ + +:ref:`PR_GetThreadPriority` has the following parameter: + +``thread`` + A valid identifier for the thread whose priority you want to know. diff --git a/docs/nspr/reference/pr_getthreadprivate.rst b/docs/nspr/reference/pr_getthreadprivate.rst new file mode 100644 index 0000000000..7303eae93b --- /dev/null +++ b/docs/nspr/reference/pr_getthreadprivate.rst @@ -0,0 +1,38 @@ +PR_GetThreadPrivate +=================== + +Recovers the per-thread private data for the current thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + void* PR_GetThreadPrivate(PRUintn index); + + +Parameter +~~~~~~~~~ + +:ref:`PR_GetThreadPrivate` has the following parameters: + +``index`` + The index into the per-thread private data table. + + +Returns +~~~~~~~ + +``NULL`` if the data has not been set. + + +Description +----------- + +:ref:`PR_GetThreadPrivate` may be called at any time during a thread's +execution. A thread can get access only to its own per-thread private +data. Do not delete the object that the private data refers to without +first clearing the thread's value. diff --git a/docs/nspr/reference/pr_getthreadscope.rst b/docs/nspr/reference/pr_getthreadscope.rst new file mode 100644 index 0000000000..32899683d9 --- /dev/null +++ b/docs/nspr/reference/pr_getthreadscope.rst @@ -0,0 +1,21 @@ +PR_GetThreadScope +================= + +Gets the scoping of the current thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRThreadScope PR_GetThreadScope(void); + + +Returns +~~~~~~~ + +A value of type :ref:`PRThreadScope` indicating whether the thread is local +or global. diff --git a/docs/nspr/reference/pr_getuniqueidentity.rst b/docs/nspr/reference/pr_getuniqueidentity.rst new file mode 100644 index 0000000000..a0b49ac66f --- /dev/null +++ b/docs/nspr/reference/pr_getuniqueidentity.rst @@ -0,0 +1,49 @@ +PR_GetUniqueIdentity +==================== + +Asks the runtime to allocate a unique identity for a layer identified by +the layer's name. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRDescIdentity PR_GetUniqueIdentity(const char *layer_name); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``layer_name`` + The string associated with the creation of a layer's identity. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, the :ref:`PRDescIdentity` for the layer associated with + the string specified in the layer named ``layer_name``. +- If the function cannot allocate enough dynamic memory, it fails and + returns the value ``PR_INVALID_IO_LAYER`` with the error code + ``PR_OUT_OF_MEMORY_ERROR``. + + +Description +----------- + +A string may be associated with a layer when the layer is created. +:ref:`PR_GetUniqueIdentity` allocates a unique layer identity and +associates it with the string. The string can be subsequently passed to +:ref:`PR_CreateIOLayerStub` to create a new file descriptor of that layer. + +Call :ref:`PR_GetUniqueIdentity` only once for any particular layer name. +If you're creating a custom I/O layer, cache the result, and then use +that cached result every time you call :ref:`PR_CreateIOLayerStub`. diff --git a/docs/nspr/reference/pr_gmtparameters.rst b/docs/nspr/reference/pr_gmtparameters.rst new file mode 100644 index 0000000000..d9abb9c0b6 --- /dev/null +++ b/docs/nspr/reference/pr_gmtparameters.rst @@ -0,0 +1,47 @@ +PR_GMTParameters +================ + +Returns the time zone offset information that maps the specified +:ref:`PRExplodedTime` to GMT. + +.. note:: + + **Note:** Since this function requires GMT as input, its primary use + is as "filler" for cases in which you need a do-nothing callback. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + PRTimeParameters PR_GMTParameters ( + const PRExplodedTime *gmt); + + +Parameter +~~~~~~~~~ + +``gmt`` + A pointer to the clock/calendar time whose offsets are to be + determined. This time should be specified in GMT. + + +Returns +~~~~~~~ + +A time parameters structure that expresses the time zone offsets at the +specified time. + + +Description +----------- + +This is a frequently-used time parameter callback function. You don't +normally call it directly; instead, you pass it as a parameter to +``PR_ExplodeTime()`` or ``PR_NormalizeTime()``. + +This is a trivial function; for any input, it returns a +:ref:`PRTimeParameters` structure with both fields set to zero. diff --git a/docs/nspr/reference/pr_htonl.rst b/docs/nspr/reference/pr_htonl.rst new file mode 100644 index 0000000000..094c59ced8 --- /dev/null +++ b/docs/nspr/reference/pr_htonl.rst @@ -0,0 +1,29 @@ +PR_htonl +======== + +Performs 32-bit conversion from host byte order to network byte order. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRUint32 PR_htonl(PRUint32 conversion); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``conversion`` + The 32-bit unsigned integer, in host byte order, to be converted. + + +Returns +~~~~~~~ + +The value of the ``conversion`` parameter in network byte order. diff --git a/docs/nspr/reference/pr_htons.rst b/docs/nspr/reference/pr_htons.rst new file mode 100644 index 0000000000..1e5b845ca9 --- /dev/null +++ b/docs/nspr/reference/pr_htons.rst @@ -0,0 +1,29 @@ +PR_htons +======== + +Performs 16-bit conversion from host byte order to network byte order. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRUint16 PR_htons(PRUint16 conversion); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``conversion`` + The 16-bit unsigned integer, in host byte order, to be converted. + + +Returns +~~~~~~~ + +The value of the ``conversion`` parameter in network byte order. diff --git a/docs/nspr/reference/pr_implement.rst b/docs/nspr/reference/pr_implement.rst new file mode 100644 index 0000000000..583716a15b --- /dev/null +++ b/docs/nspr/reference/pr_implement.rst @@ -0,0 +1,28 @@ +PR_IMPLEMENT +============ + +Used to define implementations of symbols that are to be exported from a +shared library. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + PR_IMPLEMENT(type)implementation + + +Description +----------- + +:ref:`PR_IMPLEMENT` is used to define implementations of externally visible +routines and globals. For syntax details for each platform, see +`prtypes.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtypes.h>`__. + +.. warning:: + + **Warning**: Some platforms do not allow the use of the underscore + character (_) as the first character of an exported symbol. diff --git a/docs/nspr/reference/pr_implodetime.rst b/docs/nspr/reference/pr_implodetime.rst new file mode 100644 index 0000000000..1426d57a79 --- /dev/null +++ b/docs/nspr/reference/pr_implodetime.rst @@ -0,0 +1,36 @@ +PR_ImplodeTime +============== + +Converts a clock/calendar time to an absolute time. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + PRTime PR_ImplodeTime(const PRExplodedTime *exploded); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``exploded`` + A pointer to the clock/calendar time to be converted. + + +Returns +~~~~~~~ + +An absolute time value. + + +Description +----------- + +This function converts the specified clock/calendar time to an absolute +time and returns the converted time value. diff --git a/docs/nspr/reference/pr_importfilemapfromstring.rst b/docs/nspr/reference/pr_importfilemapfromstring.rst new file mode 100644 index 0000000000..bc9694d557 --- /dev/null +++ b/docs/nspr/reference/pr_importfilemapfromstring.rst @@ -0,0 +1,39 @@ +PR_ImportFileMapFromString +========================== + +Creates a :ref:`PRFileMap` from an identifying string. + + +Syntax +~~~~~~ + +.. code:: + + #include <prshma.h> + + NSPR_API( PRFileMap * ) + PR_ImportFileMapFromString( + const char *fmstring + ); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +fmstring + A pointer to string created by :ref:`PR_ExportFileMapAsString`. + + +Returns +~~~~~~~ + +:ref:`PRFileMap` pointer or ``NULL`` on error. + + +Description +----------- + +:ref:`PR_ImportFileMapFromString` creates a :ref:`PRFileMap` object from a +string previously created by :ref:`PR_ExportFileMapAsString`. diff --git a/docs/nspr/reference/pr_importtcpsocket.rst b/docs/nspr/reference/pr_importtcpsocket.rst new file mode 100644 index 0000000000..4722744b3d --- /dev/null +++ b/docs/nspr/reference/pr_importtcpsocket.rst @@ -0,0 +1,70 @@ +PR_ImportTCPSocket +================== + +Imports a native TCP socket into NSPR. + + +Syntax +------ + +.. code:: + + #include "private/pprio.h" + + PRFileDesc* PR_ImportTCPSocket(PROsfd osfd); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``osfd`` + The native file descriptor for the TCP socket to import. On POSIX + systems, this is an ``int``. On Windows, this is a ``SOCKET``. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion, a pointer to the :ref:`PRFileDesc` object + created for the newly imported native TCP socket. +- If the import of the native TCP socket failed, ``NULL``. + + +Description +----------- + +A native TCP socket ``osfd`` can be imported into NSPR with +:ref:`PR_ImportTCPSocket`. The caller gives up control of the native TCP +socket ``osfd`` and should use the ``PRFileDesc*`` returned by +:ref:`PR_ImportTCPSocket` instead. + +Although :ref:`PR_ImportTCPSocket` is a supported function, it is declared +in ``"private/pprio.h"`` to stress the fact that this function depends +on the internals of the NSPR implementation. The caller needs to +understand what NSPR will do to the native file descriptor and make sure +that NSPR can use the native file descriptor successfully. + +For example, on POSIX systems, NSPR will put the native file descriptor +(an ``int``) in non-blocking mode by calling ``fcntl`` to set the +``O_NONBLOCK`` file status flag on the native file descriptor, and then +NSPR will call socket functions such as ``recv``, ``send``, and ``poll`` +on the native file descriptor. The caller must not do anything to the +native file descriptor before the :ref:`PR_ImportTCPSocket` call that will +prevent the native file descriptor from working in non-blocking mode. + +Warning +------- + +In theory, code that uses :ref:`PR_ImportTCPSocket` may break when NSPR's +implementation changes. In practice, this is unlikely to happen because +NSPR's implementation has been stable for years and because of NSPR's +strong commitment to backward compatibility. Using +:ref:`PR_ImportTCPSocket` is much more convenient than writing an NSPR I/O +layer that wraps your native TCP sockets. Of course, it is best if you +just use :ref:`PR_OpenTCPSocket` or :ref:`PR_NewTCPSocket`. If you are not +sure whether :ref:`PR_ImportTCPSocket` is right for you, please ask in the +mozilla.dev.tech.nspr newsgroup. diff --git a/docs/nspr/reference/pr_init.rst b/docs/nspr/reference/pr_init.rst new file mode 100644 index 0000000000..c047b2ed2d --- /dev/null +++ b/docs/nspr/reference/pr_init.rst @@ -0,0 +1,44 @@ +PR_Init +======= + +Initializes the runtime. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_Init( + PRThreadType type, + PRThreadPriority priority, + PRUintn maxPTDs); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_Init` has the following parameters: + +``type`` + This parameter is ignored. +``priority`` + This parameter is ignored. +``maxPTDs`` + This parameter is ignored. + + +Description +----------- + +NSPR is now implicitly initialized, usually by the first NSPR function +called by a program. :ref:`PR_Init` is necessary only if a program has +specific initialization-sequencing requirements. + +Call :ref:`PR_Init` as follows: + +.. code:: + + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); diff --git a/docs/nspr/reference/pr_init_clist.rst b/docs/nspr/reference/pr_init_clist.rst new file mode 100644 index 0000000000..d6d57afade --- /dev/null +++ b/docs/nspr/reference/pr_init_clist.rst @@ -0,0 +1,27 @@ +PR_INIT_CLIST +============= + +Initializes a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_INIT_CLIST (PRCList *listp); + + +Parameter +~~~~~~~~~ + +``listp`` + A pointer to the anchor of the linked list. + + +Description +----------- + +Initializes the specified list to be an empty list. diff --git a/docs/nspr/reference/pr_init_static_clist.rst b/docs/nspr/reference/pr_init_static_clist.rst new file mode 100644 index 0000000000..b837694efd --- /dev/null +++ b/docs/nspr/reference/pr_init_static_clist.rst @@ -0,0 +1,32 @@ +PR_INIT_STATIC_CLIST +==================== + +Statically initializes a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_INIT_STATIC_CLIST (PRCList *listp); + + +Parameter +~~~~~~~~~ + +``listp`` + A pointer to the anchor of the linked list. + + +Description +----------- + +PR_INIT_STATIC_CLIST statically initializes the specified list to be an +empty list. For example, + +:: + + PRCList free_object_list = PR_INIT_STATIC_CLIST(&free_object_list); diff --git a/docs/nspr/reference/pr_initialize.rst b/docs/nspr/reference/pr_initialize.rst new file mode 100644 index 0000000000..027f040a79 --- /dev/null +++ b/docs/nspr/reference/pr_initialize.rst @@ -0,0 +1,63 @@ +PR_Initialize +============= + +Provides an alternate form of explicit initialization. In addition to +establishing the sequence of operations, :ref:`PR_Initialize` implicitly +calls :ref:`PR_Cleanup` on exiting the primordial function. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + PRIntn PR_Initialize( + PRPrimordialFn prmain, + PRIntn argc, + char **argv, + PRUintn maxPTDs); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_Initialize` has the following parameters: + +``prmain`` + The function that becomes the primordial thread's root function. + Returning from prmain leads to termination of the process. +``argc`` + The length of the argument vector, whether passed in from the host's + program-launching facility or fabricated by the actual main program. + This approach conforms to standard C programming practice. +``argv`` + The base address of an array of strings that compromise the program's + argument vector. This approach conforms to standard C programming + practice. +``maxPTDs`` + This parameter is ignored. + + +Returns +~~~~~~~ + +The value returned from the root function, ``prmain``. + + +Description +----------- + +:ref:`PR_Initialize` initializes the NSPR runtime and places NSPR between +the caller and the runtime library. This allows ``main`` to be treated +like any other function, signaling its completion by returning and +allowing the runtime to coordinate the completion of the other threads +of the runtime. + +:ref:`PR_Initialize` does not return to its caller until all user threads +have terminated. + +The priority of the main (or primordial) thread is +``PR_PRIORITY_NORMAL``. The thread may adjust its own priority by using +:ref:`PR_SetThreadPriority`. diff --git a/docs/nspr/reference/pr_initialized.rst b/docs/nspr/reference/pr_initialized.rst new file mode 100644 index 0000000000..c5323637b1 --- /dev/null +++ b/docs/nspr/reference/pr_initialized.rst @@ -0,0 +1,23 @@ +PR_Initialized +============== + +Checks whether the runtime has been initialized. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + PRBool PR_Initialized(void); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If :ref:`PR_Init` has already been called, ``PR_TRUE``. +- If :ref:`PR_Init` has not already been called, ``PR_FALSE``. diff --git a/docs/nspr/reference/pr_initializenetaddr.rst b/docs/nspr/reference/pr_initializenetaddr.rst new file mode 100644 index 0000000000..c701334990 --- /dev/null +++ b/docs/nspr/reference/pr_initializenetaddr.rst @@ -0,0 +1,80 @@ +PR_InitializeNetAddr +==================== + +Initializes or reinitializes a network address. The storage for the +network address structure is allocated by, and remains the +responsibility of, the calling client. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_InitializeNetAddr( + PRNetAddrValue val, + PRUint16 port, + PRNetAddr *addr); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``val`` + The value to be assigned to the IP Address portion of the network + address. This must be ``PR_IpAddrNull``, ``PR_IpAddrAny``, or + ``PR_IpAddrLoopback``. +``port`` + The port number to be assigned in the network address structure. The + value is specified in host byte order. +``addr`` + A pointer to the :ref:`PRNetAddr` structure to be manipulated. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. This may occur, for example, if the + value of val is not within the ranges defined by ``PRNetAddrValue``. + You can retrieve the reason for the failure by calling + :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_InitializeNetAddr` allows the assignment of special network +address values and the port number, while also setting the state that +indicates the version of the address being used. + +The special network address values are identified by the enum +``PRNetAddrValue``: + +.. code:: + + typedef enum PRNetAddrValue{ + PR_IpAddrNull, + PR_IpAddrAny, + PR_IpAddrLoopback + } PRNetAddrValue; + +The enum has the following enumerators: + +``PR_IpAddrNull`` + Do not overwrite the IP address. This allows the caller to change the + network address' port number assignment without affecting the host + address. +``PR_IpAddrAny`` + Assign logical ``PR_INADDR_ANY`` to IP address. This wildcard value + is typically used to establish a socket on which to listen for + incoming connection requests. +``PR_IpAddrLoopback`` + Assign logical ``PR_INADDR_LOOPBACK``. A client can use this value to + connect to itself without knowing the host's network address. diff --git a/docs/nspr/reference/pr_insert_after.rst b/docs/nspr/reference/pr_insert_after.rst new file mode 100644 index 0000000000..b51377e3dc --- /dev/null +++ b/docs/nspr/reference/pr_insert_after.rst @@ -0,0 +1,32 @@ +PR_INSERT_AFTER +=============== + +Inserts an element after another element in a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_INSERT_AFTER ( + PRCList *elemp1 + PRCList *elemp2); + + +Parameters +~~~~~~~~~~ + +``elemp1`` + A pointer to the element to be inserted. +``elemp2`` + A pointer to the element after which ``elemp1`` is to be inserted. + + +Description +----------- + +PR_INSERT_AFTER inserts the element specified by ``elemp1`` into the +circular list, after the element specified by ``elemp2``. diff --git a/docs/nspr/reference/pr_insert_before.rst b/docs/nspr/reference/pr_insert_before.rst new file mode 100644 index 0000000000..6d6bcc8a3c --- /dev/null +++ b/docs/nspr/reference/pr_insert_before.rst @@ -0,0 +1,32 @@ +PR_INSERT_BEFORE +================ + +Inserts an element before another element in a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_INSERT_BEFORE ( + PRCList *elemp1 + PRCList *elemp2); + + +Parameters +~~~~~~~~~~ + +``elemp1`` + A pointer to the element to be inserted. +``elemp2`` + A pointer to the element before which ``elemp1`` is to be inserted. + + +Description +----------- + +PR_INSERT_BEFORE inserts the element specified by ``elemp1`` into the +circular list, before the element specified by ``elemp2``. diff --git a/docs/nspr/reference/pr_insert_link.rst b/docs/nspr/reference/pr_insert_link.rst new file mode 100644 index 0000000000..24a6dd9cfd --- /dev/null +++ b/docs/nspr/reference/pr_insert_link.rst @@ -0,0 +1,32 @@ +PR_INSERT_LINK +============== + +Inserts an element at the head of the list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_INSERT_LINK ( + PRCList *elemp, + PRCList *listp); + + +Parameters +~~~~~~~~~~ + +``elemp`` + A pointer to the element to be inserted. +``listp`` + A pointer to the list. + + +Description +----------- + +PR_INSERT_LINK inserts the specified element at the head of the +specified list. diff --git a/docs/nspr/reference/pr_interrupt.rst b/docs/nspr/reference/pr_interrupt.rst new file mode 100644 index 0000000000..67bf324e96 --- /dev/null +++ b/docs/nspr/reference/pr_interrupt.rst @@ -0,0 +1,71 @@ +PR_Interrupt +============ + +Sets the interrupt request for a target thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRStatus PR_Interrupt(PRThread *thread); + + +Parameter +~~~~~~~~~ + +:ref:`PR_Interrupt` has the following parameter: + +``thread`` + The thread whose interrupt request you want to set. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the specified thread is currently blocked, ``PR_SUCCESS``. +- Otherwise, ``PR_FAILURE``. + + +Description +----------- + +The purpose of :ref:`PR_Interrupt` is to request that a thread performing +some task stop what it is doing and return to some control point. It is +assumed that a control point has been mutually arranged between the +thread doing the interrupting and the thread being interrupted. When the +interrupted thread reaches the prearranged point, it can communicate +with its peer to discover the real reason behind the change in plans. + +The interrupt request remains in the thread's state until it is +delivered exactly once or explicitly canceled. The interrupted thread +returns ``PR_FAILURE`` (-1) with an error code (see :ref:`PR_GetError`) for +blocking operations that return a :ref:`PRStatus` (such as I/O operations, +monitor waits, or waiting on a condition). To check whether the thread +was interrupted, compare the result of :ref:`PR_GetError` with +``PR_PENDING_INTERRUPT_ERROR``. + +:ref:`PR_Interrupt` may itself fail if the target thread is invalid. + +Bugs +---- + +:ref:`PR_Interrupt` has the following limitations and known bugs: + +- There can be a delay for a thread to be interrupted from a blocking + I/O function. In all NSPR implementations, the maximum delay is at + most five seconds. In the pthreads-based implementation on Unix, the + maximum delay is 0.1 seconds. +- File I/O is considered instantaneous, so file I/O functions cannot be + interrupted. Unfortunately the standard input, output, and error + streams are treated as files by NSPR, so a :ref:`PR_Read` call on + ``PR_STDIN`` cannot be interrupted even though it may block + indefinitely. +- In the NT implementation, :ref:`PR_Connect` cannot be interrupted. +- In the NT implementation, a file descriptor is not usable and must be + closed after an I/O function on the file descriptor is interrupted. diff --git a/docs/nspr/reference/pr_intervalnow.rst b/docs/nspr/reference/pr_intervalnow.rst new file mode 100644 index 0000000000..360dd6455a --- /dev/null +++ b/docs/nspr/reference/pr_intervalnow.rst @@ -0,0 +1,50 @@ +PR_IntervalNow +============== + +Returns the value of NSPR's free-running interval timer. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRIntervalTime PR_IntervalNow(void); + + +Returns +~~~~~~~ + +A :ref:`PRIntervalTime` object. + + +Description +----------- + +You can use the value returned by ``PR_IntervalNow()`` to establish +epochs and to determine intervals (that is, compute the difference +between two times). ``PR_IntervalNow()`` is both very efficient and +nonblocking, so it is appropriate to use (for example) while holding a +mutex. + +The most common use for ``PR_IntervalNow()`` is to establish an epoch +and test for the expiration of intervals. In this case, you typically +call ``PR_IntervalNow()`` in a sequence that looks like this: + +.. code:: + + PRUint32 interval = ... ; // milliseconds + // ... + PRStatus rv; + PRIntervalTime epoch = PR_IntervalNow(); + PR_Lock(data->mutex); + while (!EvaluateData(data)) /* wait until condition is met */ + { + PRUint32 delta = PR_IntervalToMilliseconds(PR_IntervalNow() - epoch); + if (delta > interval) break; /* timeout */ + rv = PR_Wait(data->condition, PR_MillisecondsToInterval(interval - delta)); + if (PR_FAILURE == rv) break; /* likely an interrupt */ + } + PR_Unlock(data->mutex); diff --git a/docs/nspr/reference/pr_intervaltomicroseconds.rst b/docs/nspr/reference/pr_intervaltomicroseconds.rst new file mode 100644 index 0000000000..a8e3fec038 --- /dev/null +++ b/docs/nspr/reference/pr_intervaltomicroseconds.rst @@ -0,0 +1,34 @@ +PR_IntervalToMicroseconds +========================= + +Converts platform-dependent intervals to standard clock microseconds. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRUint32 PR_IntervalToMicroseconds(PRIntervalTime ticks); + + +Parameter +~~~~~~~~~ + +``ticks`` + The number of platform-dependent intervals to convert. + + +Returns +~~~~~~~ + +Equivalent in microseconds of the value passed in the ``ticks`` +parameter. + + +Description +----------- + +Conversion may cause overflow, which is not reported. diff --git a/docs/nspr/reference/pr_intervaltomilliseconds.rst b/docs/nspr/reference/pr_intervaltomilliseconds.rst new file mode 100644 index 0000000000..a68c4534bb --- /dev/null +++ b/docs/nspr/reference/pr_intervaltomilliseconds.rst @@ -0,0 +1,34 @@ +PR_IntervalToMilliseconds +========================= + +Converts platform-dependent intervals to standard clock milliseconds. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRUint32 PR_IntervalToMilliseconds(PRIntervalTime ticks); + + +Parameter +~~~~~~~~~ + +``ticks`` + The number of platform-dependent intervals to convert. + + +Returns +~~~~~~~ + +Equivalent in milliseconds of the value passed in the ``ticks`` +parameter. + + +Description +----------- + +Conversion may cause overflow, which is not reported. diff --git a/docs/nspr/reference/pr_intervaltoseconds.rst b/docs/nspr/reference/pr_intervaltoseconds.rst new file mode 100644 index 0000000000..16d77f0ade --- /dev/null +++ b/docs/nspr/reference/pr_intervaltoseconds.rst @@ -0,0 +1,33 @@ +PR_IntervalToSeconds +==================== + +Converts platform-dependent intervals to standard clock seconds. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRUint32 PR_IntervalToSeconds(PRIntervalTime ticks); + + +Parameter +~~~~~~~~~ + +``ticks`` + The number of platform-dependent intervals to convert. + + +Returns +~~~~~~~ + +Equivalent in seconds of the value passed in the ``ticks`` parameter. + + +Description +----------- + +Conversion may cause overflow, which is not reported. diff --git a/docs/nspr/reference/pr_joinjob.rst b/docs/nspr/reference/pr_joinjob.rst new file mode 100644 index 0000000000..1153cd9dcf --- /dev/null +++ b/docs/nspr/reference/pr_joinjob.rst @@ -0,0 +1,30 @@ +PR_JoinJob +========== + +Blocks the current thread until a job has completed. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRStatus) PR_JoinJob(PRJob *job); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``job`` + A pointer to a :ref:`PRJob` structure returned by a :ref:`PR_QueueJob` + function representing the job to be cancelled. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_jointhread.rst b/docs/nspr/reference/pr_jointhread.rst new file mode 100644 index 0000000000..a1bfddf81c --- /dev/null +++ b/docs/nspr/reference/pr_jointhread.rst @@ -0,0 +1,57 @@ +PR_JoinThread +============= + +Blocks the calling thread until a specified thread terminates. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRStatus PR_JoinThread(PRThread *thread); + + +Parameter +~~~~~~~~~ + +:ref:`PR_JoinThread` has the following parameter: + +``thread`` + A valid identifier for the thread that is to be joined. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS`` +- If unsuccessful--for example, if no joinable thread can be found that + corresponds to the specified target thread, or if the target thread + is unjoinable--``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_JoinThread` is used to synchronize the termination of a thread. +The function is synchronous in that it blocks the calling thread until +the target thread is in a joinable state. :ref:`PR_JoinThread` returns to +the caller only after the target thread returns from its root function. + +:ref:`PR_JoinThread` must not be called until after :ref:`PR_CreateThread` has +returned. If :ref:`PR_JoinThread` is not called on the same thread as +:ref:`PR_CreateThread`, then it is the caller's responsibility to ensure +that :ref:`PR_CreateThread` has completed. + +Several threads cannot wait for the same thread to complete. One of the +calling threads operates successfully, and the others terminate with the +error ``PR_FAILURE``. + +The calling thread is not blocked if the target thread has already +terminated. + +:ref:`PR_JoinThread` is interruptible. diff --git a/docs/nspr/reference/pr_jointhreadpool.rst b/docs/nspr/reference/pr_jointhreadpool.rst new file mode 100644 index 0000000000..86d8ecf822 --- /dev/null +++ b/docs/nspr/reference/pr_jointhreadpool.rst @@ -0,0 +1,31 @@ +PR_JoinThreadPool +================= + +Waits for all threads in a thread pool to complete, then releases +resources allocated to the thread pool. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRStatus) PR_JoinThreadPool( PRThreadPool *tpool ); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_list_head.rst b/docs/nspr/reference/pr_list_head.rst new file mode 100644 index 0000000000..e930c36295 --- /dev/null +++ b/docs/nspr/reference/pr_list_head.rst @@ -0,0 +1,33 @@ +PR_LIST_HEAD +============ + +Returns the head of a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PRCList *PR_LIST_HEAD (PRCList *listp); + + +Parameter +~~~~~~~~~ + +``listp`` + A pointer to the linked list. + + +Returns +~~~~~~~ + +A pointer to a list element. + + +Description +----------- + +:ref:`PR_LIST_HEAD` returns the head of the specified circular list. diff --git a/docs/nspr/reference/pr_list_tail.rst b/docs/nspr/reference/pr_list_tail.rst new file mode 100644 index 0000000000..87d9126f92 --- /dev/null +++ b/docs/nspr/reference/pr_list_tail.rst @@ -0,0 +1,33 @@ +PR_LIST_TAIL +============ + +Returns the tail of a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PRCList *PR_LIST_TAIL (PRCList *listp); + + +Parameter +~~~~~~~~~ + +``listp`` + A pointer to the linked list. + + +Returns +~~~~~~~ + +A pointer to a list element. + + +Description +----------- + +:ref:`PR_LIST_TAIL` returns the tail of the specified circular list. diff --git a/docs/nspr/reference/pr_listen.rst b/docs/nspr/reference/pr_listen.rst new file mode 100644 index 0000000000..1b1efefc21 --- /dev/null +++ b/docs/nspr/reference/pr_listen.rst @@ -0,0 +1,48 @@ +PR_Listen +========= + +Listens for connections on a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Listen( + PRFileDesc *fd, + PRIntn backlog); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket that will + be used to listen for new connections. +``backlog`` + The maximum length of the queue of pending connections. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion of listen request, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. Further information can be obtained + by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_Listen` turns the specified socket into a rendezvous socket. It +creates a queue for pending connections and starts to listen for +connection requests on the socket. The maximum size of the queue for +pending connections is specified by the ``backlog`` parameter. Pending +connections may be accepted by calling :ref:`PR_Accept`. diff --git a/docs/nspr/reference/pr_loadlibrary.rst b/docs/nspr/reference/pr_loadlibrary.rst new file mode 100644 index 0000000000..707973ec51 --- /dev/null +++ b/docs/nspr/reference/pr_loadlibrary.rst @@ -0,0 +1,46 @@ +PR_LoadLibrary +============== + +Loads a referenced library. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + PRLibrary* PR_LoadLibrary(const char *name); + + +Parameters +~~~~~~~~~~ + +The function has this parameter: + +``name`` + A platform-dependent character array that names the library to be + loaded, as returned by :ref:`PR_GetLibraryName`. + + +Returns +~~~~~~~ + +If successful, returns a reference to an opaque :ref:`PRLibrary` object. + +If the operation fails, returns ``NULL``. Use :ref:`PR_GetError` to find +the reason for the failure. + + +Description +----------- + +This function loads and returns a reference to the specified library. +The returned reference becomes the library's identity. The function +suppresses duplicate loading if the library is already known by the +runtime. + +Each call to :ref:`PR_LoadLibrary` must be paired with a corresponding call +to :ref:`PR_UnloadLibrary` in order to return the runtime to its original +state. diff --git a/docs/nspr/reference/pr_localtimeparameters.rst b/docs/nspr/reference/pr_localtimeparameters.rst new file mode 100644 index 0000000000..976db05547 --- /dev/null +++ b/docs/nspr/reference/pr_localtimeparameters.rst @@ -0,0 +1,39 @@ +PR_LocalTimeParameters +====================== + +Returns the time zone offset information that maps the specified +:ref:`PRExplodedTime` to local time. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + PRTimeParameters PR_LocalTimeParameters ( + const PRExplodedTime *gmt); + + +Parameter +~~~~~~~~~ + +``gmt`` + A pointer to the clock/calendar time whose offsets are to be + determined. This time should be specified in GMT. + + +Returns +~~~~~~~ + +A time parameters structure that expresses the time zone offsets at the +specified time. + + +Description +----------- + +This is a frequently-used time parameter callback function. You don't +normally call it directly; instead, you pass it as a parameter to +``PR_ExplodeTime()`` or ``PR_NormalizeTime()``. diff --git a/docs/nspr/reference/pr_lock.rst b/docs/nspr/reference/pr_lock.rst new file mode 100644 index 0000000000..53cb17deea --- /dev/null +++ b/docs/nspr/reference/pr_lock.rst @@ -0,0 +1,42 @@ +PR_Lock +======= + +Locks a specified lock object. + + +Syntax +------ + +.. code:: + + #include <prlock.h> + + void PR_Lock(PRLock *lock); + + +Parameter +~~~~~~~~~ + +:ref:`PR_Lock` has one parameter: + +``lock`` + A pointer to a lock object to be locked. + + +Description +----------- + +When :ref:`PR_Lock` returns, the calling thread is "in the monitor," also +called "holding the monitor's lock." Any thread that attempts to acquire +the same lock blocks until the holder of the lock exits the monitor. +Acquiring the lock is not an interruptible operation, nor is there any +timeout mechanism. + +:ref:`PR_Lock` is not reentrant. Calling it twice on the same thread +results in undefined behavior. + + +See Also +-------- + + - :ref:`PR_Unlock` diff --git a/docs/nspr/reference/pr_malloc.rst b/docs/nspr/reference/pr_malloc.rst new file mode 100644 index 0000000000..d475ab6a4b --- /dev/null +++ b/docs/nspr/reference/pr_malloc.rst @@ -0,0 +1,35 @@ +PR_MALLOC +========= + +Allocates memory of a specified size from the heap. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + void * PR_MALLOC(_bytes); + + +Parameter +~~~~~~~~~ + +``_bytes`` + Size of the requested memory block. + + +Returns +~~~~~~~ + +An untyped pointer to the allocated memory, or if the allocation attempt +fails, ``NULL``. Call ``PR_GetError()`` to retrieve the error returned +by the libc function ``malloc()``. + + +Description +----------- + +This macro allocates memory of the requested size from the heap. diff --git a/docs/nspr/reference/pr_memmap.rst b/docs/nspr/reference/pr_memmap.rst new file mode 100644 index 0000000000..6b37fe313a --- /dev/null +++ b/docs/nspr/reference/pr_memmap.rst @@ -0,0 +1,50 @@ +PR_MemMap +========= + +Maps a section of a file to memory. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + void* PR_MemMap( + PRFileMap *fmap, + PRInt64 offset, + PRUint32 len); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fmap`` + A pointer to the file-mapping object representing the file to be + memory-mapped. +``offset`` + The starting offset of the section of file to be mapped. The offset + must be aligned to whole pages. +``len`` + Length of the section of the file to be mapped. + + +Returns +~~~~~~~ + +The starting address of the memory region to which the section of file +is mapped. Returns ``NULL`` on error. + + +Description +----------- + +:ref:`PR_MemMap` maps a section of the file represented by the file mapping +``fmap`` to memory. The section of the file starts at ``offset`` and has +the length ``len``. + +When the file-mapping memory region is no longer needed, it should be +unmapped with a call to :ref:`PR_MemUnmap`. diff --git a/docs/nspr/reference/pr_microsecondstointerval.rst b/docs/nspr/reference/pr_microsecondstointerval.rst new file mode 100644 index 0000000000..9771809bb8 --- /dev/null +++ b/docs/nspr/reference/pr_microsecondstointerval.rst @@ -0,0 +1,30 @@ +PR_MicrosecondsToInterval +========================= + +Converts standard clock microseconds to platform-dependent intervals. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRIntervalTime PR_MicrosecondsToInterval(PRUint32 milli); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``micro`` + The number of microseconds to convert to interval form. + + +Returns +~~~~~~~ + +Platform-dependent equivalent of the value passed in the ``micro`` +parameter. diff --git a/docs/nspr/reference/pr_millisecondstointerval.rst b/docs/nspr/reference/pr_millisecondstointerval.rst new file mode 100644 index 0000000000..b456b0096d --- /dev/null +++ b/docs/nspr/reference/pr_millisecondstointerval.rst @@ -0,0 +1,30 @@ +PR_MillisecondsToInterval +========================= + +Converts standard clock milliseconds to platform-dependent intervals. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRIntervalTime PR_MillisecondsToInterval(PRUint32 milli); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``milli`` + The number of milliseconds to convert to interval form. + + +Returns +~~~~~~~ + +Platform-dependent equivalent of the value passed in the ``milli`` +parameter. diff --git a/docs/nspr/reference/pr_mkdir.rst b/docs/nspr/reference/pr_mkdir.rst new file mode 100644 index 0000000000..6d1a629f9a --- /dev/null +++ b/docs/nspr/reference/pr_mkdir.rst @@ -0,0 +1,67 @@ +PR_MkDir +======== + +Creates a directory with a specified name and access mode. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_MkDir( + const char *name, + PRIntn mode); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``name`` + The name of the directory to be created. All the path components up + to but not including the leaf component must already exist. +``mode`` + The access permission bits of the file mode of the new directory if + the file is created when ``PR_CREATE_FILE`` is on. + +Caveat: The mode parameter is currently applicable only on Unix +platforms. It may be applicable to other platforms in the future. + +Possible values include the following: + + - :ref:`00400`. Read by owner. + - :ref:`00200`. Write by owner. + - :ref:`00100`. Search by owner. + - :ref:`00040`. Read by group. + - :ref:`00020`. Write by group. + - :ref:`00010`. Search by group. + - :ref:`00004`. Read by others. + - :ref:`00002`. Write by others. + - :ref:`00001`. Search by others. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The actual reason can be retrieved + via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_MkDir` creates a new directory with the pathname ``name``. All the +path components up to but not including the leaf component must already +exist. For example, if the pathname of the directory to be created is +``a/b/c/d``, the directory ``a/b/c`` must already exist. + + +See Also +-------- + +:ref:`PR_RmDir` diff --git a/docs/nspr/reference/pr_msec_per_sec.rst b/docs/nspr/reference/pr_msec_per_sec.rst new file mode 100644 index 0000000000..86cabb124a --- /dev/null +++ b/docs/nspr/reference/pr_msec_per_sec.rst @@ -0,0 +1,16 @@ +PR_MSEC_PER_SEC +=============== + +A convenience macro to improve code readability as well as to avoid +mistakes in counting the number of zeros; represents the number of +milliseconds in a second. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + #define PR_MSEC_PER_SEC 1000UL diff --git a/docs/nspr/reference/pr_name.rst b/docs/nspr/reference/pr_name.rst new file mode 100644 index 0000000000..cddb792155 --- /dev/null +++ b/docs/nspr/reference/pr_name.rst @@ -0,0 +1,18 @@ +PR_NAME +======= + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + #define PR_NAME "NSPR" + + +Description +----------- + +NSPR Name. diff --git a/docs/nspr/reference/pr_netaddrtostring.rst b/docs/nspr/reference/pr_netaddrtostring.rst new file mode 100644 index 0000000000..d21f4d5ecc --- /dev/null +++ b/docs/nspr/reference/pr_netaddrtostring.rst @@ -0,0 +1,50 @@ +PR_NetAddrToString +================== + +Converts a character string to a network address. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_NetAddrToString( + const PRNetAddr *addr, + char *string, + PRUint32 size); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``addr`` + A pointer to the network address to be converted. +``string`` + A buffer that will hold the converted string on output. +``size`` + The size of the result buffer (``string``). + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. + + +Description +----------- + +The network address to be converted (``addr``) may be either an IPv4 or +IPv6 address structure, assuming that the NSPR library and the host +system are both configured to utilize IPv6 addressing. If ``addr`` is an +IPv4 address, ``size`` needs to be at least 16. If ``addr`` is an IPv6 +address, ``size`` needs to be at least 46. diff --git a/docs/nspr/reference/pr_netdb_buf_size.rst b/docs/nspr/reference/pr_netdb_buf_size.rst new file mode 100644 index 0000000000..6c5c79d560 --- /dev/null +++ b/docs/nspr/reference/pr_netdb_buf_size.rst @@ -0,0 +1,20 @@ +PR_NETDB_BUF_SIZE +================= + +Recommended size to use when specifying a scratch buffer for +:ref:`PR_GetHostByName`, :ref:`PR_GetHostByAddr`, :ref:`PR_GetProtoByName`, or +:ref:`PR_GetProtoByNumber`. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + #if defined(AIX) || defined(OSF1) + #define PR_NETDB_BUF_SIZE sizeof(struct protoent_data) + #else + #define PR_NETDB_BUF_SIZE 1024 + #endif diff --git a/docs/nspr/reference/pr_new.rst b/docs/nspr/reference/pr_new.rst new file mode 100644 index 0000000000..0fd9973419 --- /dev/null +++ b/docs/nspr/reference/pr_new.rst @@ -0,0 +1,36 @@ +PR_NEW +====== + +Allocates memory of a specified size from the heap. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + _type * PR_NEW(_struct); + + +Parameter +~~~~~~~~~ + +``_struct`` + The name of a type. + + +Returns +~~~~~~~ + +An pointer to a buffer sized to contain the type ``_struct``, or if the +allocation attempt fails, ``NULL``. Call ``PR_GetError()`` to retrieve +the error returned by the libc function. + + +Description +----------- + +This macro allocates memory whose size is ``sizeof(_struct)`` and +returns a pointer to that memory. diff --git a/docs/nspr/reference/pr_newcondvar.rst b/docs/nspr/reference/pr_newcondvar.rst new file mode 100644 index 0000000000..1ce70e8fe5 --- /dev/null +++ b/docs/nspr/reference/pr_newcondvar.rst @@ -0,0 +1,34 @@ +PR_NewCondVar +============= + +Creates a new condition variable. + + +Syntax +------ + +.. code:: + + #include <prcvar.h> + + PRCondVar* PR_NewCondVar(PRLock *lock); + + +Parameter +~~~~~~~~~ + +:ref:`PR_NewCondVar` has one parameter: + +``lock`` + The identity of the mutex that protects the monitored data, including + this condition variable. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, a pointer to the new condition variable object. +- If unsuccessful (for example, if system resources are unavailable), + ``NULL``. diff --git a/docs/nspr/reference/pr_newlock.rst b/docs/nspr/reference/pr_newlock.rst new file mode 100644 index 0000000000..7fbc51348e --- /dev/null +++ b/docs/nspr/reference/pr_newlock.rst @@ -0,0 +1,30 @@ +PR_NewLock +========== + +Creates a new lock. + + +Syntax +------ + +.. code:: + + #include <prlock.h> + + PRLock* PR_NewLock(void); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, a pointer to the new lock object. +- If unsuccessful (for example, the lock cannot be created because of + resource constraints), ``NULL``. + + +Description +----------- + +:ref:`PR_NewLock` creates a new opaque lock. diff --git a/docs/nspr/reference/pr_newmonitor.rst b/docs/nspr/reference/pr_newmonitor.rst new file mode 100644 index 0000000000..3f80340c77 --- /dev/null +++ b/docs/nspr/reference/pr_newmonitor.rst @@ -0,0 +1,31 @@ +PR_NewMonitor +============= + +Creates a new monitor object. The caller is responsible for the object +and is expected to destroy it when appropriate. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + PRMonitor* PR_NewMonitor(void); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, a pointer to a :ref:`PRMonitor` object. +- If unsuccessful (for example, if some operating system resource is + unavailable), ``NULL``. + + +Description +----------- + +A newly created monitor has an entry count of zero. diff --git a/docs/nspr/reference/pr_newpollableevent.rst b/docs/nspr/reference/pr_newpollableevent.rst new file mode 100644 index 0000000000..be4e0f9bd8 --- /dev/null +++ b/docs/nspr/reference/pr_newpollableevent.rst @@ -0,0 +1,24 @@ +PR_NewPollableEvent +=================== + +Create a pollable event file descriptor. + + +Syntax +------ + +.. code:: + + NSPR_API(PRFileDesc *) PR_NewPollableEvent( void); + + +Parameter +~~~~~~~~~ + +None. + + +Returns +~~~~~~~ + +Pointer to :ref:`PRFileDesc` or ``NULL``, on error. diff --git a/docs/nspr/reference/pr_newprocessattr.rst b/docs/nspr/reference/pr_newprocessattr.rst new file mode 100644 index 0000000000..a01e55498f --- /dev/null +++ b/docs/nspr/reference/pr_newprocessattr.rst @@ -0,0 +1,39 @@ +PR_NewProcessAttr +================= + +Creates a process attributes structure. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + PRProcessAttr *PR_NewProcessAttr(void); + + +Parameters +~~~~~~~~~~ + +The function has no parameters. + + +Returns +~~~~~~~ + +A pointer to the new process attributes structure. + + +Description +----------- + +This function creates a new :ref:`PRProcessAttr`\ structure that specifies +the attributes of a new process, then returns a pointer to the +structure. The new :ref:`PRProcessAttr`\ structure is initialized with +these default attributes: + +- The standard I/O streams (standard input, standard output, and + standard error) are not redirected. +- No file descriptors are inherited by the new process. diff --git a/docs/nspr/reference/pr_newtcpsocket.rst b/docs/nspr/reference/pr_newtcpsocket.rst new file mode 100644 index 0000000000..4a6b285669 --- /dev/null +++ b/docs/nspr/reference/pr_newtcpsocket.rst @@ -0,0 +1,56 @@ +PR_NewTCPSocket +=============== + +Creates a new IPv4 TCP socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_NewTCPSocket(void); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion, a pointer to the :ref:`PRFileDesc` object + created for the newly opened IPv4 TCP socket. +- If the creation of a new TCP socket failed, ``NULL``. + + +Description +----------- + +TCP (Transmission Control Protocol) is a connection-oriented, reliable +byte-stream protocol of the TCP/IP protocol suite. :ref:`PR_NewTCPSocket` +creates a new IPv4 TCP socket. A TCP connection is established by a +passive socket (the server) accepting a connection setup request from an +active socket (the client). Typically, the server binds its socket to a +well-known port with :ref:`PR_Bind`, calls :ref:`PR_Listen` to start listening +for connection setup requests, and calls :ref:`PR_Accept` to accept a +connection. The client makes a connection request using :ref:`PR_Connect`. + +After a connection is established, the client and server may send and +receive data between each other. To receive data, one can call +:ref:`PR_Read` or :ref:`PR_Recv`. To send data, one can call :ref:`PR_Write`, +:ref:`PR_Writev`, :ref:`PR_Send`, or :ref:`PR_TransmitFile`. :ref:`PR_AcceptRead` is +suitable for use by the server to accept a new client connection and +read the client's first request in one function call. + +A TCP connection can be shut down by :ref:`PR_Shutdown`, and the sockets +should be closed by :ref:`PR_Close`. + + +See Also +-------- + +:ref:`PR_NewTCPSocket` is deprecated because it is hardcoded to create an +IPv4 TCP socket. New code should use :ref:`PR_OpenTCPSocket` instead, which +allows the address family (IPv4 or IPv6) of the new TCP socket to be +specified. diff --git a/docs/nspr/reference/pr_newthreadprivateindex.rst b/docs/nspr/reference/pr_newthreadprivateindex.rst new file mode 100644 index 0000000000..8cb926bbee --- /dev/null +++ b/docs/nspr/reference/pr_newthreadprivateindex.rst @@ -0,0 +1,65 @@ +PR_NewThreadPrivateIndex +======================== + +Returns a new index for a per-thread private data table and optionally +associates a destructor with the data that will be assigned to the +index. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRStatus PR_NewThreadPrivateIndex( + PRUintn *newIndex, + PRThreadPrivateDTOR destructor); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_NewThreadPrivateIndex` has the following parameters: + +``newIndex`` + On output, an index that is valid for all threads in the process. You + use this index with :ref:`PR_SetThreadPrivate` and + :ref:`PR_GetThreadPrivate`. +``destructor`` + Specifies a destructor function :ref:`PRThreadPrivateDTOR` for the + private data associated with the index. This function can be + specified as ``NULL``. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If the total number of indices exceeds 128, ``PR_FAILURE``. + + +Description +----------- + +If :ref:`PR_NewThreadPrivateIndex` is successful, every thread in the same +process is capable of associating private data with the new index. Until +the data for an index is actually set, the value of the private data at +that index is ``NULL``. You pass this index to :ref:`PR_SetThreadPrivate` +and :ref:`PR_GetThreadPrivate` to set and retrieve data associated with the +index. + +When you allocate the index, you may also register a destructor function +of type :ref:`PRThreadPrivateDTOR`. If a destructor function is registered +with a new index, it will be called at one of two times, as long as the +private data is not ``NULL``: + +- when replacement private data is set with :ref:`PR_SetThreadPrivate` +- when a thread exits + +The index maintains independent data values for each binding thread. A +thread can get access only to its own thread-specific data. There is no +way to deallocate a private data index once it is allocated. diff --git a/docs/nspr/reference/pr_newudpsocket.rst b/docs/nspr/reference/pr_newudpsocket.rst new file mode 100644 index 0000000000..67aff3e5d4 --- /dev/null +++ b/docs/nspr/reference/pr_newudpsocket.rst @@ -0,0 +1,46 @@ +PR_NewUDPSocket +=============== + +Creates a new UDP socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_NewUDPSocket(void); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion, a pointer to the :ref:`PRFileDesc` object + created for the newly opened UDP socket. +- If the creation of a new UDP socket failed, ``NULL``. + + +Description +----------- + +UDP (User Datagram Protocol) is a connectionless, unreliable datagram +protocol of the TCP/IP protocol suite. UDP datagrams may be lost or +delivered in duplicates or out of sequence. + +:ref:`PR_NewUDPSocket` creates a new UDP socket. The socket may be bound to +a well-known port number with :ref:`PR_Bind`. Datagrams can be sent with +:ref:`PR_SendTo` and received with :ref:`PR_RecvFrom`. When the socket is no +longer needed, it should be closed with a call to :ref:`PR_Close`. + + +See Also +-------- + +:ref:`PR_NewUDPSocket` is deprecated because it is hardcoded to create an +IPv4 UDP socket. New code should use :ref:`PR_OpenUDPSocket` instead, which +allows the address family (IPv4 or IPv6) of the new UDP socket to be +specified. diff --git a/docs/nspr/reference/pr_newzap.rst b/docs/nspr/reference/pr_newzap.rst new file mode 100644 index 0000000000..55d77885b1 --- /dev/null +++ b/docs/nspr/reference/pr_newzap.rst @@ -0,0 +1,38 @@ +PR_NEWZAP +========= + +Allocates and clears memory from the heap for an instance of a given +type. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + _type * PR_NEWZAP(_struct); + + +Parameter +~~~~~~~~~ + +``_struct`` + The name of a type. + + +Returns +~~~~~~~ + +An pointer to a buffer sized to contain the type ``_struct``, or if the +allocation attempt fails, ``NULL``. The bytes in the buffer are all +initialized to 0. Call ``PR_GetError()`` to retrieve the error returned +by the libc function. + + +Description +----------- + +This macro allocates an instance of the specified type from the heap and +sets the content of that memory to zero. diff --git a/docs/nspr/reference/pr_next_link.rst b/docs/nspr/reference/pr_next_link.rst new file mode 100644 index 0000000000..1a48065e69 --- /dev/null +++ b/docs/nspr/reference/pr_next_link.rst @@ -0,0 +1,35 @@ +PR_NEXT_LINK +============ + +Returns the next element in a list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PRCList *PR_NEXT_LINK (PRCList *elemp); + + +Parameter +~~~~~~~~~ + +``elemp`` + A pointer to the element. + + +Returns +~~~~~~~ + +A pointer to a list element. + + +Description +----------- + +PR_NEXT_LINK returns a pointer to the element following the specified +element. It can be used to traverse a list. The following element is not +removed from the list. diff --git a/docs/nspr/reference/pr_normalizetime.rst b/docs/nspr/reference/pr_normalizetime.rst new file mode 100644 index 0000000000..47a82ae78b --- /dev/null +++ b/docs/nspr/reference/pr_normalizetime.rst @@ -0,0 +1,62 @@ +PR_NormalizeTime +================ + +Adjusts the fields of a clock/calendar time to their proper ranges, +using a callback function. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + void PR_NormalizeTime ( + PRExplodedTime *time, + PRTimeParamFn params); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``time`` + A pointer to a clock/calendar time in the :ref:`PRExplodedTime` format. +``params`` + A time parameter callback function. + + +Returns +~~~~~~~ + +Nothing; the ``time`` parameter is altered by the callback function. + + +Description +----------- + +This function adjusts the fields of the specified time structure using +the specified time parameter callback function, so that they are in the +proper range. + +Call this function in these situations: + +- To normalize a time after performing arithmetic operations directly + on the field values of the calendar time object. For example, if you + have a ``]`` object that represents the date 3 March 1998 and you + want to say "forty days from 3 March 1998", you can simply add 40 to + the ``tm_mday`` field and then call ``PR_NormalizeTime()``. + +- To calculate the optional field values ``tm_wday`` and ``tm_yday``. + For example, suppose you want to compute the day of week for 3 March + 1998. You can set ``tm_mday`` to 3, ``tm_month`` to 2, and + ``tm_year`` to 1998, and all the other fields to 0, then call + ``PR_NormalizeTime()`` with :ref:`PR_GMTParameters`. On return, + ``tm_wday`` (and ``tm_yday``) are set for you. + +- To convert from one time zone to another. For example, if the input + argument time is in time zone A and the input argument ``params`` + represents time zone B, when ``PR_NormalizeTime()`` returns, time + will be in time zone B. diff --git a/docs/nspr/reference/pr_notify.rst b/docs/nspr/reference/pr_notify.rst new file mode 100644 index 0000000000..c34d07f89b --- /dev/null +++ b/docs/nspr/reference/pr_notify.rst @@ -0,0 +1,48 @@ +PR_Notify +========= + +Notifies a monitor that a change in state of the monitored data has +occurred. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + PRStatus PR_Notify(PRMonitor *mon); + + +Parameters +~~~~~~~~~~ + +The function has the following parameter: + +``mon`` + A reference to an existing structure of type :ref:`PRMonitor`. The + monitor object referenced must be one for which the calling thread + currently holds the lock. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. + + +Description +----------- + +Notification of a monitor signals the change of state of some monitored +data. The changing of that data and the notification must all be +performed while in the monitor. When the notification occurs, the +runtime promotes a thread that is waiting on the monitor to a ready +state. If more than one thread is waiting, the selection of which thread +gets promoted cannot be determined in advance. This implies that all +threads waiting on a single monitor must have the same semantics. If no +thread is waiting on the monitor, the notify operation is a no-op. diff --git a/docs/nspr/reference/pr_notifyall.rst b/docs/nspr/reference/pr_notifyall.rst new file mode 100644 index 0000000000..0dd3a62b7e --- /dev/null +++ b/docs/nspr/reference/pr_notifyall.rst @@ -0,0 +1,46 @@ +PR_NotifyAll +============ + +Promotes all threads waiting on a specified monitor to a ready state. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + PRStatus PR_NotifyAll(PRMonitor *mon); + + +Parameters +~~~~~~~~~~ + +The function has the following parameter: + +``mon`` + A reference to an existing structure of type :ref:`PRMonitor`. The + monitor object referenced must be one for which the calling thread + currently holds the lock. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. + + +Description +----------- + +A call to :ref:`PR_NotifyAll` causes all of the threads waiting on the +monitor to be scheduled to be promoted to a ready state. If no threads +are waiting, the operation is no-op. + +:ref:`PR_NotifyAll` should be used with some care. The expense of +scheduling multiple threads increases dramatically as the number of +threads increases. diff --git a/docs/nspr/reference/pr_notifyallcondvar.rst b/docs/nspr/reference/pr_notifyallcondvar.rst new file mode 100644 index 0000000000..aa73167c99 --- /dev/null +++ b/docs/nspr/reference/pr_notifyallcondvar.rst @@ -0,0 +1,35 @@ +PR_NotifyAllCondVar +=================== + +Notifies all of the threads waiting on a specified condition variable. + + +Syntax +------ + +.. code:: + + #include <prcvar.h> + + PRStatus PR_NotifyAllCondVar(PRCondVar *cvar); + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful (for example, if the caller has not locked the lock + associated with the condition variable), ``PR_FAILURE``. + + +Description +----------- + +The calling thread must hold the lock that protects the condition, as +well as the invariants that are tightly bound to the condition. + +A call to :ref:`PR_NotifyAllCondVar` causes all of the threads waiting on +the specified condition variable to be promoted to a ready state. If no +threads are waiting, the operation is no-op. diff --git a/docs/nspr/reference/pr_notifycondvar.rst b/docs/nspr/reference/pr_notifycondvar.rst new file mode 100644 index 0000000000..e7289d9b06 --- /dev/null +++ b/docs/nspr/reference/pr_notifycondvar.rst @@ -0,0 +1,49 @@ +PR_NotifyCondVar +================ + +Notifies a condition variable of a change in its associated monitored +data. + + +Syntax +------ + +.. code:: + + #include <prcvar.h> + + PRStatus PR_NotifyCondVar(PRCondVar *cvar); + + +Parameter +~~~~~~~~~ + +:ref:`PR_NotifyCondVar` has one parameter: + +``cvar`` + The condition variable to notify. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful (for example, if the caller has not locked the lock + associated with the condition variable), ``PR_FAILURE``. + + +Description +----------- + +The calling thread must hold the lock that protects the condition, as +well as the invariants that are tightly bound to the condition. + +Notification of a condition variable signals a change of state in some +monitored data. When the notification occurs, the runtime promotes a +thread that is waiting on the condition variable to a ready state. If +more than one thread is waiting, the selection of which thread gets +promoted cannot be predicted. This implies that all threads waiting on a +single condition variable must have the same semantics. If no thread is +waiting on the condition variable, the notify operation is a no-op. diff --git a/docs/nspr/reference/pr_now.rst b/docs/nspr/reference/pr_now.rst new file mode 100644 index 0000000000..5f5efc0203 --- /dev/null +++ b/docs/nspr/reference/pr_now.rst @@ -0,0 +1,38 @@ +PR_Now +====== + +Returns the current time. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + PRTime PR_Now(void); + + +Parameters +~~~~~~~~~~ + +None. + + +Returns +~~~~~~~ + +The current time as a :ref:`PRTime` value. + + +Description +----------- + +``PR_Now()`` returns the current time as number of microseconds since +the NSPR epoch, which is midnight (00:00:00) 1 January 1970 UTC. + +You cannot assume that the values returned by ``PR_Now()`` are +monotonically increasing because the system clock of the computer may be +reset. To obtain monotonically increasing time stamps suitable for +measuring elapsed time, use ``PR_IntervalNow()``. diff --git a/docs/nspr/reference/pr_nsec_per_msec.rst b/docs/nspr/reference/pr_nsec_per_msec.rst new file mode 100644 index 0000000000..8d471bd300 --- /dev/null +++ b/docs/nspr/reference/pr_nsec_per_msec.rst @@ -0,0 +1,16 @@ +PR_NSEC_PER_MSEC +================ + +A convenience macro to improve code readability as well as to avoid +mistakes in counting the number of zeros; represents the number of +nanoseconds in a millisecond. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + #define PR_NSEC_PER_MSEC 1000000UL diff --git a/docs/nspr/reference/pr_nsec_per_sec.rst b/docs/nspr/reference/pr_nsec_per_sec.rst new file mode 100644 index 0000000000..78ceb7b326 --- /dev/null +++ b/docs/nspr/reference/pr_nsec_per_sec.rst @@ -0,0 +1,16 @@ +PR_NSEC_PER_SEC +=============== + +A convenience macro to improve code readability as well as to avoid +mistakes in counting the number of zeros; represents the number of +nanoseconds in a second. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + #define PR_NSEC_PER_SEC 1000000000UL diff --git a/docs/nspr/reference/pr_ntohl.rst b/docs/nspr/reference/pr_ntohl.rst new file mode 100644 index 0000000000..8c48f88f40 --- /dev/null +++ b/docs/nspr/reference/pr_ntohl.rst @@ -0,0 +1,29 @@ +PR_ntohl +======== + +Performs 32-bit conversion from network byte order to host byte order. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRUint32 PR_ntohl(PRUint32 conversion); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``conversion`` + The 32-bit unsigned integer, in network byte order, to be converted. + + +Returns +~~~~~~~ + +The value of the ``conversion`` parameter in host byte order. diff --git a/docs/nspr/reference/pr_ntohs.rst b/docs/nspr/reference/pr_ntohs.rst new file mode 100644 index 0000000000..a20c9d2851 --- /dev/null +++ b/docs/nspr/reference/pr_ntohs.rst @@ -0,0 +1,29 @@ +PR_ntohs +======== + +Performs 16-bit conversion from network byte order to host byte order. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRUint16 PR_ntohs(PRUint16 conversion); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``conversion`` + The 16-bit unsigned integer, in network byte order, to be converted. + + +Returns +~~~~~~~ + +The value of the ``conversion`` parameter in host byte order. diff --git a/docs/nspr/reference/pr_open.rst b/docs/nspr/reference/pr_open.rst new file mode 100644 index 0000000000..1dba4d6a56 --- /dev/null +++ b/docs/nspr/reference/pr_open.rst @@ -0,0 +1,117 @@ +PR_Open +======= + +Opens a file for reading, writing, or both. Also used to create a file. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_Open( + const char *name, + PRIntn flags, + PRIntn mode); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``name`` + The pathname of the file to be opened. +``flags`` + The file status flags define how the file is accessed. It is a + bitwise ``OR`` of the following bit flags. In most cases, only one of + the first three flags may be used. If the ``flags`` parameter does + not include any of the first three flags (``PR_RDONLY``, + ``PR_WRONLY``, or ``PR_RDWR``), the open file can't be read or + written, which is not useful. + +.. note:: + + **NOTE**: The constants PR_RDWR and friends are not in any interface + (`bug 433295 <https://bugzilla.mozilla.org/show_bug.cgi?id=433295>`__). + Thus they cannot be used in JavaScript, you have to use the octal + constants (see `File I/O Snippets </en/Code_snippets:File_I/O>`__). + ++--------------------+-------+---------------------------------------+ +| Name | Value | Description | ++====================+=======+=======================================+ +| ``PR_RDONLY`` | 0x01 | Open for reading only. | ++--------------------+-------+---------------------------------------+ +| ``PR_WRONLY`` | 0x02 | Open for writing only. | ++--------------------+-------+---------------------------------------+ +| ``PR_RDWR`` | 0x04 | Open for reading and writing. | ++--------------------+-------+---------------------------------------+ +| ``PR_CREATE_FILE`` | 0x08 | If the file does not exist, the file | +| | | is created. If the file exists, this | +| | | flag has no effect. | ++--------------------+-------+---------------------------------------+ +| ``PR_APPEND`` | 0x10 | The file pointer is set to the end of | +| | | the file prior to each write. | ++--------------------+-------+---------------------------------------+ +| ``PR_TRUNCATE`` | 0x20 | If the file exists, its length is | +| | | truncated to 0. | ++--------------------+-------+---------------------------------------+ +| ``PR_SYNC`` | 0x40 | If set, each write will wait for both | +| | | the file data and file status to be | +| | | physically updated. | ++--------------------+-------+---------------------------------------+ +| ``PR_EXCL`` | 0x80 | With ``PR_CREATE_FILE``, if the file | +| | | does not exist, the file is created. | +| | | If the file already exists, no action | +| | | and NULL is returned. | ++--------------------+-------+---------------------------------------+ + + + +``mode`` + When ``PR_CREATE_FILE`` flag is set and the file is created, these + flags define the access permission bits of the newly created file. + This feature is currently only applicable on Unix platforms. It is + ignored by any other platform but it may apply to other platforms in + the future. Possible values of the ``mode`` parameter are listed in + the table below. + +============ ===== ===================================== +Name Value Description +============ ===== ===================================== +``PR_IRWXU`` 0700 read, write, execute/search by owner. +``PR_IRUSR`` 0400 read permission, owner. +``PR_IWUSR`` 0200 write permission, owner. +``PR_IXUSR`` 0100 execute/search permission, owner. +``PR_IRWXG`` 0070 read, write, execute/search by group +``PR_IRGRP`` 0040 read permission, group +``PR_IWGRP`` 0020 write permission, group +``PR_IXGRP`` 0010 execute/search permission, group +``PR_IRWXO`` 0007 read, write, execute/search by others +``PR_IROTH`` 0004 read permission, others +``PR_IWOTH`` 0002 write permission, others +``PR_IXOTH`` 0001 execute/search permission, others +============ ===== ===================================== + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the file is successfully opened, a pointer to a dynamically + allocated :ref:`PRFileDesc` for the newly opened file. The + :ref:`PRFileDesc` should be freed by calling :ref:`PR_Close`. +- If the file was not opened successfully, a ``NULL`` pointer. + + +Description +----------- + +:ref:`PR_Open` creates a file descriptor (:ref:`PRFileDesc`) for the file with +the pathname ``name`` and sets the file status flags of the file +descriptor according to the value of ``flags``. If a new file is created +as a result of the :ref:`PR_Open` call, its file mode bits are set +according to the ``mode`` parameter. diff --git a/docs/nspr/reference/pr_openanonfilemap.rst b/docs/nspr/reference/pr_openanonfilemap.rst new file mode 100644 index 0000000000..30964c5dd7 --- /dev/null +++ b/docs/nspr/reference/pr_openanonfilemap.rst @@ -0,0 +1,51 @@ +PR_OpenAnonFileMap +================== + +Creates or opens a named semaphore with the specified name + + +Syntax +------ + +.. code:: + + #include <prshma.h> + + NSPR_API( PRFileMap *) + PR_OpenAnonFileMap( + const char *dirName, + PRSize size, + PRFileMapProtect prot + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``dirName`` + A pointer to a directory name that will contain the anonymous file. +``size`` + The size of the shared memory. +``prot`` + How the shared memory is mapped. + + +Returns +~~~~~~~ + +Pointer to :ref:`PRFileMap` or ``NULL`` on error. + + +Description +----------- + +If the shared memory already exists, a handle is returned to that shared +memory object. + +On Unix platforms, :ref:`PR_OpenAnonFileMap` uses ``dirName`` as a +directory name, without the trailing '/', to contain the anonymous file. +A filename is generated for the name. + +On Windows platforms, ``dirName`` is ignored. diff --git a/docs/nspr/reference/pr_opendir.rst b/docs/nspr/reference/pr_opendir.rst new file mode 100644 index 0000000000..9bfe91a6e7 --- /dev/null +++ b/docs/nspr/reference/pr_opendir.rst @@ -0,0 +1,41 @@ +PR_OpenDir +========== + +Opens the directory with the specified pathname. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRDir* PR_OpenDir(const char *name); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``name`` + The pathname of the directory to be opened. + + +Returns +~~~~~~~ + +- If the directory is successfully opened, a :ref:`PRDir` object is + dynamically allocated and the function returns a pointer to it. +- If the directory cannot be opened, the function returns ``NULL``. + + +Description +----------- + +:ref:`PR_OpenDir` opens the directory specified by the pathname ``name`` +and returns a pointer to a directory stream (a :ref:`PRDir` object) that +can be passed to subsequent :ref:`PR_ReadDir` calls to get the directory +entries (files and subdirectories) in the directory. The :ref:`PRDir` +pointer should eventually be closed by a call to :ref:`PR_CloseDir`. diff --git a/docs/nspr/reference/pr_opensemaphore.rst b/docs/nspr/reference/pr_opensemaphore.rst new file mode 100644 index 0000000000..6ac69cbe71 --- /dev/null +++ b/docs/nspr/reference/pr_opensemaphore.rst @@ -0,0 +1,58 @@ +PR_OpenSemaphore +================ + +Creates or opens a named semaphore with the specified name. + + +Syntax +------ + +.. code:: + + #include <pripcsem.h> + + #define PR_SEM_CREATE 0x1 /* create if not exist */ + + #define PR_SEM_EXCL 0x2 /* fail if already exists */ + + NSPR_API(PRSem *) PR_OpenSemaphore( + const char *name, + PRIntn flags, + PRIntn mode, + PRUintn value + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``name`` + The name to be given the semaphore. +``flags`` + How to create or open the semaphore. +``mode`` + Unix style file mode to be used when creating the semaphore. +``value`` + The initial value assigned to the semaphore. + + +Returns +~~~~~~~ + +A pointer to a PRSem structure or ``NULL/code> on error.`` + + +Description +~~~~~~~~~~~ + +If the named semaphore doesn't exist and the ``PR_SEM_CREATE`` flag is +specified, the named semaphore is created. The created semaphore needs +to be removed from the system with a :ref:`PR_DeleteSemaphore` call. + +If ``PR_SEM_CREATE`` is specified, the third argument is the access +permission bits of the new semaphore (same interpretation as the mode +argument to :ref:`PR_Open`) and the fourth argument is the initial value of +the new semaphore. ``If PR_SEM_CREATE`` is not specified, the third and +fourth arguments are ignored. diff --git a/docs/nspr/reference/pr_opensharedmemory.rst b/docs/nspr/reference/pr_opensharedmemory.rst new file mode 100644 index 0000000000..759a81dbf8 --- /dev/null +++ b/docs/nspr/reference/pr_opensharedmemory.rst @@ -0,0 +1,68 @@ +PR_OpenSharedMemory +=================== + +Opens an existing shared memory segment or, if one with the specified +name doesn't exist, creates a new one. + + +Syntax +------ + +.. code:: + + #include <prshm.h> + + NSPR_API( PRSharedMemory * ) + PR_OpenSharedMemory( + const char *name, + PRSize size, + PRIntn flags, + PRIntn mode + ); + + /* Define values for PR_OpenShareMemory(...,create) */ + #define PR_SHM_CREATE 0x1 /* create if not exist */ + #define PR_SHM_EXCL 0x2 /* fail if already exists */ + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +name + The name of the shared memory segment. +size + The size of the shared memory segment. +flags + Options for creating the shared memory. +mode + Same as passed to :ref:`PR_Open`. + + +Returns +~~~~~~~ + +Pointer to opaque structure ``PRSharedMemory``, or ``NULL`` if an error +occurs. Retrieve the reason for the failure by calling :ref:`PR_GetError` +and :ref:`PR_GetOSError`. + + +Description +----------- + +:ref:`PR_OpenSharedMemory` creates a new shared memory segment or +associates a previously created memory segment with the specified name. +When parameter ``create`` is (``PR_SHM_EXCL`` \| ``PR_SHM_CREATE``) and +the shared memory already exists, the function returns ``NULL`` with the +error set to ``PR_FILE_EXISTS_ERROR``. + +When parameter ``create`` is ``PR_SHM_CREATE`` and the shared memory +already exists, a handle to that memory segment is returned. If the +segment does not exist, it is created and a pointer to the related +``PRSharedMemory`` structure is returned. + +When parameter ``create`` is 0, and the shared memory exists, a pointer +to a ``PRSharedMemory`` structure is returned. If the shared memory does +not exist, ``NULL`` is returned with the error set to +``PR_FILE_NOT_FOUND_ERROR``. diff --git a/docs/nspr/reference/pr_opentcpsocket.rst b/docs/nspr/reference/pr_opentcpsocket.rst new file mode 100644 index 0000000000..c9c11799cf --- /dev/null +++ b/docs/nspr/reference/pr_opentcpsocket.rst @@ -0,0 +1,59 @@ +PR_OpenTCPSocket +================ + +Creates a new TCP socket of the specified address family. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_OpenTCPSocket(PRIntn af); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``af`` + The address family of the new TCP socket. Can be ``PR_AF_INET`` + (IPv4), ``PR_AF_INET6`` (IPv6), or ``PR_AF_LOCAL`` (Unix domain, + supported on POSIX systems only). + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion, a pointer to the :ref:`PRFileDesc` object + created for the newly opened TCP socket. +- If the creation of a new TCP socket failed, ``NULL``. + + +Description +----------- + +TCP (Transmission Control Protocol) is a connection-oriented, reliable +byte-stream protocol of the TCP/IP protocol suite. :ref:`PR_OpenTCPSocket` +creates a new TCP socket of the address family ``af``. A TCP connection +is established by a passive socket (the server) accepting a connection +setup request from an active socket (the client). Typically, the server +binds its socket to a well-known port with :ref:`PR_Bind`, calls +:ref:`PR_Listen` to start listening for connection setup requests, and +calls :ref:`PR_Accept` to accept a connection. The client makes a +connection request using :ref:`PR_Connect`. + +After a connection is established, the client and server may send and +receive data between each other. To receive data, one can call +:ref:`PR_Read` or :ref:`PR_Recv`. To send data, one can call :ref:`PR_Write`, +:ref:`PR_Writev`, :ref:`PR_Send`, or :ref:`PR_TransmitFile`. :ref:`PR_AcceptRead` is +suitable for use by the server to accept a new client connection and +read the client's first request in one function call. + +A TCP connection can be shut down by :ref:`PR_Shutdown`, and the sockets +should be closed by :ref:`PR_Close`. diff --git a/docs/nspr/reference/pr_openudpsocket.rst b/docs/nspr/reference/pr_openudpsocket.rst new file mode 100644 index 0000000000..f25373d7d8 --- /dev/null +++ b/docs/nspr/reference/pr_openudpsocket.rst @@ -0,0 +1,49 @@ +PR_OpenUDPSocket +================ + +Creates a new UDP socket of the specified address family. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc* PR_OpenUDPSocket(PRIntn af); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``af`` + The address family of the new UDP socket. Can be ``PR_AF_INET`` + (IPv4), ``PR_AF_INET6`` (IPv6), or ``PR_AF_LOCAL`` (Unix domain, + supported on POSIX systems only). + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion, a pointer to the :ref:`PRFileDesc` object + created for the newly opened UDP socket. +- If the creation of a new UDP socket failed, ``NULL``. + + +Description +----------- + +UDP (User Datagram Protocol) is a connectionless, unreliable datagram +protocol of the TCP/IP protocol suite. UDP datagrams may be lost or +delivered in duplicates or out of sequence. + +:ref:`PR_OpenUDPSocket` creates a new UDP socket of the address family +``af``. The socket may be bound to a well-known port number with +:ref:`PR_Bind`. Datagrams can be sent with :ref:`PR_SendTo` and received with +:ref:`PR_RecvFrom`. When the socket is no longer needed, it should be +closed with a call to :ref:`PR_Close`. diff --git a/docs/nspr/reference/pr_poll.rst b/docs/nspr/reference/pr_poll.rst new file mode 100644 index 0000000000..bc40620a2a --- /dev/null +++ b/docs/nspr/reference/pr_poll.rst @@ -0,0 +1,110 @@ +PR_Poll +======= + +Detects when I/O is ready for a set of socket file descriptors. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Poll( + PRPollDesc *pds, + PRIntn npds, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``pds`` + A pointer to the first element of an array of ``PRPollDesc`` + structures. +``npds`` + The number of elements in the ``pds`` array. If this parameter is + zero, :ref:`PR_Poll` is equivalent to :ref:`PR_Sleep` with a timeout. +``timeout`` + Amount of time the call will block waiting for I/O to become ready. + If this time expires without any I/O becoming ready, :ref:`PR_Poll` + returns zero. + + +Returns +~~~~~~~ + +The function returns one of these values: + +- If successful, the function returns a positive number indicating the + number of ``PRPollDesc`` structures in ``pds`` that have events. +- The value 0 indicates the function timed out. +- The value -1 indicates the function failed. The reason for the + failure can be obtained by calling :ref:`PR_GetError`. + + +Description +~~~~~~~~~~~ + +This function returns as soon as I/O is ready on one or more of the +underlying socket objects. A count of the number of ready descriptors is +returned unless a timeout occurs, in which case zero is returned. + +The ``in_flags`` field of the ``PRPollDesc`` data structure should be +set to the I/O events (readable, writable, exception, or some +combination) that the caller is interested in. On successful return, the +``out_flags`` field of the ``PRPollDesc`` data structure is set to +indicate what kind of I/O is ready on the respective descriptor. +:ref:`PR_Poll` uses the ``out_flags`` fields as scratch variables during +the call. If :ref:`PR_Poll` returns 0 or -1, the ``out_flags`` fields do +not contain meaningful values and must not be used. + +The ``PRPollDesc`` structure is defined as follows: + +.. code:: + + struct PRPollDesc { + PRFileDesc* fd; + PRInt16 in_flags; + PRInt16 out_flags; + }; + + typedef struct PRPollDesc PRPollDesc; + +The structure has the following fields: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket or a + pollable event. This field can be set to ``NULL`` to indicate to + :ref:`PR_Poll` that this ``PRFileDesc object`` should be ignored. + + .. note:: + + On Unix, the ``fd`` field can be set to a pointer to any + :ref:`PRFileDesc` object, including one representing a file or a + pipe. Cross-platform applications should only set the ``fd`` field + to a pointer to a :ref:`PRFileDesc` object representing a socket or a + pollable event because on Windows the ``select`` function can only + be used with sockets. +``in_flags`` + A bitwise ``OR`` of the following bit flags: + + - :ref:`PR_POLL_READ`: ``fd`` is readable. + - :ref:`PR_POLL_WRITE`: ``fd`` is writable. + - :ref:`PR_POLL_EXCEPT`: ``fd`` has an exception condition. + +``out_flags`` + A bitwise ``OR`` of the following bit flags: + + - :ref:`PR_POLL_READ` + - :ref:`PR_POLL_WRITE` + - :ref:`PR_POLL_EXCEPT` + - :ref:`PR_POLL_ERR`: ``fd`` has an error. + - :ref:`PR_POLL_NVAL`: ``fd`` is bad. + +Note that the ``PR_POLL_ERR`` and ``PR_POLL_NVAL`` flags are used only +in ``out_flags``. The ``PR_POLL_ERR`` and ``PR_POLL_NVAL`` events are +always reported by :ref:`PR_Poll`. diff --git a/docs/nspr/reference/pr_popiolayer.rst b/docs/nspr/reference/pr_popiolayer.rst new file mode 100644 index 0000000000..42fae4c074 --- /dev/null +++ b/docs/nspr/reference/pr_popiolayer.rst @@ -0,0 +1,53 @@ +PR_PopIOLayer +============= + +Removes a layer from the stack. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRFileDesc *PR_PopIOLayer( + PRFileDesc *stack, + PRDescIdentity id); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``stack`` + A pointer to a :ref:`PRFileDesc` object representing the stack from + which the specified layer is to be removed. +``id`` + Identity of the layer to be removed from the stack. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the layer is successfully removed from the stack, a pointer to the + removed layer. +- If the layer is not found in the stack or cannot be popped (for + example, the bottommost layer), the function returns ``NULL`` with + the error code ``PR_INVALID_ARGUMENT_ERROR``. + + +Description +----------- + +:ref:`PR_PopIOLayer` pops the specified layer from the stack. If the object +to be removed is found, :ref:`PR_PopIOLayer` returns a pointer to the +removed object The object then becomes the responsibility of the caller. + +Even if the identity indicates the top layer of the stack, the reference +returned is not the file descriptor for the stack and that file +descriptor remains valid. In other words, ``stack`` continues to point +to the top of the stack after the function returns. diff --git a/docs/nspr/reference/pr_postsemaphore.rst b/docs/nspr/reference/pr_postsemaphore.rst new file mode 100644 index 0000000000..e7145a60fe --- /dev/null +++ b/docs/nspr/reference/pr_postsemaphore.rst @@ -0,0 +1,30 @@ +PR_PostSemaphore +================ + +Increments the value of a specified semaphore. + + +Syntax +------ + +.. code:: + + #include <pripcsem.h> + + NSPR_API(PRStatus) PR_PostSemaphore(PRSem *sem); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``sem`` + A pointer to a ``PRSem`` structure returned from a call to + :ref:`PR_OpenSemaphore`. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_prev_link.rst b/docs/nspr/reference/pr_prev_link.rst new file mode 100644 index 0000000000..2b887db657 --- /dev/null +++ b/docs/nspr/reference/pr_prev_link.rst @@ -0,0 +1,35 @@ +PR_PREV_LINK +============ + +Returns the preceding element in a list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PRCList *PR_PREV_LINK (PRCList *elemp); + + +Parameter +~~~~~~~~~ + +``elemp`` + A pointer to the element. + + +Returns +~~~~~~~ + +A pointer to a list element. + + +Description +----------- + +:ref:`PR_PREV_LINK` returns a pointer to the element preceding the +specified element. It can be used to traverse a list. The preceding +element is not removed from the list. diff --git a/docs/nspr/reference/pr_processattrsetinheritablefilemap.rst b/docs/nspr/reference/pr_processattrsetinheritablefilemap.rst new file mode 100644 index 0000000000..c89f2740eb --- /dev/null +++ b/docs/nspr/reference/pr_processattrsetinheritablefilemap.rst @@ -0,0 +1,53 @@ +PR_ProcessAttrSetInheritableFileMap +=================================== + +Prepare filemap for export to my children processes via +``PR_CreateProcess``. + + +Syntax +------ + +.. code:: + + #include <prshma.h> + + NSPR_API(PRStatus) + PR_ProcessAttrSetInheritableFileMap( + PRProcessAttr *attr, + PRFileMap *fm, + const char *shmname + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``attr`` + Pointer to a PRProcessAttr structure used to pass data to + PR_CreateProcess. +``fm`` + Pointer to a PRFileMap structure to be passed to the child process. +``shmname`` + Pointer to the name for the PRFileMap; used by child. + + +Returns +~~~~~~~ + +:ref:`PRStatus` + + +Description +~~~~~~~~~~~ + +:ref:`PR_ProcessAttrSetInheritableFileMap` connects the :ref:`PRFileMap` to +:ref:`PRProcessAttr` with ``shmname``. A subsequent call to +``PR_CreateProcess`` makes the :ref:`PRFileMap` importable by the child +process. + +.. note:: + + **Note:** This function is not implemented. diff --git a/docs/nspr/reference/pr_processexit.rst b/docs/nspr/reference/pr_processexit.rst new file mode 100644 index 0000000000..862e48bb5e --- /dev/null +++ b/docs/nspr/reference/pr_processexit.rst @@ -0,0 +1,23 @@ +PR_ProcessExit +============== + +Causes an immediate, nongraceful, forced termination of the process. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_ProcessExit(PRIntn status); + + +Parameter +~~~~~~~~~ + +:ref:`PR_ProcessExit` has one parameter: + +status + The exit status code of the process. diff --git a/docs/nspr/reference/pr_pushiolayer.rst b/docs/nspr/reference/pr_pushiolayer.rst new file mode 100644 index 0000000000..067370108f --- /dev/null +++ b/docs/nspr/reference/pr_pushiolayer.rst @@ -0,0 +1,87 @@ +PR_PushIOLayer +============== + +Adds a layer onto the stack. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_PushIOLayer( + PRFileDesc *stack, + PRDescIdentity id, + PRFileDesc *layer); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``stack`` + A pointer to a :ref:`PRFileDesc` object representing the stack. +``id`` + A :ref:`PRDescIdentity` object for the layer on the stack above which + the new layer is to be added. +``layer`` + A pointer to a :ref:`PRFileDesc` object representing the new layer to be + added to the stack. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the layer is successfully pushed onto the stack, ``PR_SUCCESS``. +- If the layer is not successfully pushed onto the stack, + ``PR_FAILURE``. Use :ref:`PR_GetError` to get additional information + regarding the reason for the failure. + + +Description +----------- + +A file descriptor for a layer (possibly allocated using +:ref:`PR_CreateIOLayerStub`) may be pushed onto an existing stack of file +descriptors at any time. The new layer is inserted into the stack just +above the layer with the identity specified by ``id``. + +Even if the ``id`` parameter indicates the topmost layer of the stack, +the value of the file descriptor describing the original stack will not +change. In other words, ``stack`` continues to point to the top of the +stack after the function returns. + +Caution +------- + +Keeping the pointer to the stack even as layers are pushed onto the top +of the stack is accomplished by swapping the contents of the file +descriptor being pushed and the stack's current top layer file +descriptor. + +The intent is that the pointer to the stack remain the stack's identity +even if someone (perhaps covertly) has pushed other layers. Some subtle +ramifications: + +- The ownership of the storage pointed to by the caller's layer + argument is relinquished to the runtime. Accessing the object via the + pointer is not permitted while the runtime has ownership. The correct + mechanism to access the object is to get a pointer to it by calling + :ref:`PR_GetIdentitiesLayer`. + +- The contents of the caller's object are swapped into another + container, including the reference to the object's destructor. If the + original container was allocated using a different mechanism than + used by the runtime, the default calling of the layer's destructor by + the runtime will fail :ref:`PR_CreateIOLayerStub` is provided to + allocate layer objects and template implementations). The destructor + will be called on all layers when the stack is closed (see + :ref:`PR_Close`). If the containers are allocated by some method other + than :ref:`PR_CreateIOLayerStub`, it may be required that the stack have + the layers popped off (in reverse order that they were pushed) before + calling :ref:`PR_Close`. diff --git a/docs/nspr/reference/pr_queuejob.rst b/docs/nspr/reference/pr_queuejob.rst new file mode 100644 index 0000000000..0ad0eb3b8b --- /dev/null +++ b/docs/nspr/reference/pr_queuejob.rst @@ -0,0 +1,43 @@ +PR_QueueJob +=========== + +Queues a job to a thread pool for execution. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRJob *) + PR_QueueJob( + PRThreadPool *tpool, + PRJobFn fn, + void *arg, + PRBool joinable + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. +``fn`` + The function to be executed when the job is executed. +``arg`` + A pointer to an argument passed to ``fn``. +``joinable`` + If ``PR_TRUE``, the job is joinable. If ``PR_FALSE``, the job is not + joinable. See :ref:`PR_JoinJob`. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRJob` structure or ``NULL`` on error. diff --git a/docs/nspr/reference/pr_queuejob_connect.rst b/docs/nspr/reference/pr_queuejob_connect.rst new file mode 100644 index 0000000000..b5aeaf899e --- /dev/null +++ b/docs/nspr/reference/pr_queuejob_connect.rst @@ -0,0 +1,49 @@ +PR_QueueJob_Connect +=================== + +Causes a job to be queued when a socket can be connected. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRJob *) + PR_QueueJob_Connect( + PRThreadPool *tpool, + PRJobIoDesc *iod, + const PRNetAddr *addr, + PRJobFn fn, + void * arg, + PRBool joinable + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. +``iod`` + A pointer to a :ref:`PRJobIoDesc` structure. +``addr`` + Pointer to a :ref:`PRNetAddr` structure for the socket being connected. +``fn`` + The function to be executed when the job is executed. +``arg`` + A pointer to an argument passed to ``fn``. +``joinable`` + If ``PR_TRUE``, the job is joinable. If ``PR_FALSE``, the job is not + joinable. See :ref:`PR_JoinJob`. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRJob` structure or ``NULL`` on error. diff --git a/docs/nspr/reference/pr_queuejob_read.rst b/docs/nspr/reference/pr_queuejob_read.rst new file mode 100644 index 0000000000..0b715a7fa5 --- /dev/null +++ b/docs/nspr/reference/pr_queuejob_read.rst @@ -0,0 +1,46 @@ +PR_QueueJob_Read +================ + +Causes a job to be queued when a socket becomes readable. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRJob *) + PR_QueueJob_Read( + PRThreadPool *tpool, + PRJobIoDesc *iod, + PRJobFn fn, + void *arg, + PRBool joinable + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. +``iod`` + A pointer to a :ref:`PRJobIoDesc` structure. +``fn`` + The function to be executed when the job is executed. +``arg`` + A pointer to an argument passed to ``fn``. +``joinable`` + If ``PR_TRUE``, the job is joinable. If ``PR_FALSE``, the job is not + joinable. See :ref:`PR_JoinJob`. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRJob` structure or ``NULL`` on error. diff --git a/docs/nspr/reference/pr_queuejob_timer.rst b/docs/nspr/reference/pr_queuejob_timer.rst new file mode 100644 index 0000000000..4460433fa5 --- /dev/null +++ b/docs/nspr/reference/pr_queuejob_timer.rst @@ -0,0 +1,49 @@ +PR_QueueJob_Timer +================= + +Causes a job to be queued when a timer expires. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRJob *) + PR_QueueJob_Timer( + PRThreadPool *tpool, + PRIntervalTime timeout, + PRJobFn fn, + void * arg, + PRBool joinable + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. +``iod`` + A pointer to a :ref:`PRJobIoDesc` structure. +``timeout`` + A value, expressed as a :ref:`PRIntervalTime`, to wait before queuing + the job. +``fn`` + The function to be executed when the job is executed. +``arg`` + A pointer to an argument passed to ``fn``. +``joinable`` + If ``PR_TRUE``, the job is joinable. If ``PR_FALSE``, the job is not + joinable. See :ref:`PR_JoinJob`. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRJob` structure or ``NULL`` on error. diff --git a/docs/nspr/reference/pr_queuejob_write.rst b/docs/nspr/reference/pr_queuejob_write.rst new file mode 100644 index 0000000000..9551b3bc4b --- /dev/null +++ b/docs/nspr/reference/pr_queuejob_write.rst @@ -0,0 +1,46 @@ +PR_QueueJob_Write +================= + +Causes a job to be queued when a socket becomes writable. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRJob *) + PR_QueueJob_Write( + PRThreadPool *tpool, + PRJobIoDesc *iod, + PRJobFn fn, + void *arg, + PRBool joinable + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. +``iod`` + A pointer to a :ref:`PRJobIoDesc` structure. +``fn`` + The function to be executed when the job is executed. +``arg`` + A pointer to an argument passed to ``fn``. +``joinable`` + If ``PR_TRUE``, the job is joinable. If ``PR_FALSE``, the job is not + joinable. See :ref:`PR_JoinJob`. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRJob` structure or ``NULL`` on error. diff --git a/docs/nspr/reference/pr_queuejobaccept.rst b/docs/nspr/reference/pr_queuejobaccept.rst new file mode 100644 index 0000000000..234a2148f4 --- /dev/null +++ b/docs/nspr/reference/pr_queuejobaccept.rst @@ -0,0 +1,46 @@ +PR_QueueJob_Accept +================== + +Causes a job to be queued when a socket has a pending connection. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRJob *) + PR_QueueJob_Accept( + PRThreadPool *tpool, + PRJobIoDesc *iod, + PRJobFn fn, + void *arg, + PRBool joinable + ); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. +``iod`` + A pointer to a :ref:`PRJobIoDesc` structure. +``fn`` + The function to be executed when the job is executed. +``arg`` + A pointer to an argument passed to ``fn``. +``joinable`` + If ``PR_TRUE``, the job is joinable. If ``PR_FALSE``, the job is not + joinable. See :ref:`PR_JoinJob`. + + +Returns +~~~~~~~ + +Pointer to a :ref:`PRJob` structure or ``NULL`` on error. diff --git a/docs/nspr/reference/pr_read.rst b/docs/nspr/reference/pr_read.rst new file mode 100644 index 0000000000..a6d7c03efa --- /dev/null +++ b/docs/nspr/reference/pr_read.rst @@ -0,0 +1,50 @@ +PR_Read +======= + +Reads bytes from a file or socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Read(PRFileDesc *fd, + void *buf, + PRInt32 amount); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object for the file or socket. +``buf`` + A pointer to a buffer to hold the data read in. On output, the buffer + contains the data. +``amount`` + The size of ``buf`` (in bytes). + + +Returns +~~~~~~~ + +One of the following values: + +- A positive number indicates the number of bytes actually read in. +- The value 0 means end of file is reached or the network connection is + closed. +- The value -1 indicates a failure. To get the reason for the failure, + call :ref:`PR_GetError`. + + +Description +----------- + +The thread invoking :ref:`PR_Read` blocks until it encounters an +end-of-stream indication, some positive number of bytes (but no more +than ``amount`` bytes) are read in, or an error occurs. diff --git a/docs/nspr/reference/pr_readdir.rst b/docs/nspr/reference/pr_readdir.rst new file mode 100644 index 0000000000..1379b694c9 --- /dev/null +++ b/docs/nspr/reference/pr_readdir.rst @@ -0,0 +1,93 @@ +PR_ReadDir +========== + +Gets a pointer to the next entry in the directory. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRDirEntry* PR_ReadDir( + PRDir *dir, + PRDirFlags flags); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``dir`` + A pointer to a :ref:`PRDir` object that designates an open directory. +``flags`` + Specifies which directory entries, if any, to skip. Values can + include the following: + + - :ref:`PR_SKIP_NONE`. Do not skip any files. + - :ref:`PR_SKIP_DOT`. Skip the directory entry "." representing the + current directory. + - :ref:`PR_SKIP_DOT_DOT`. Skip the directory entry ".." representing + the parent directory. + - :ref:`PR_SKIP_BOTH`. Skip both "." and ".." + - :ref:`PR_SKIP_HIDDEN`. Skip hidden files. On Windows platforms and + the Mac OS, this value identifies files with the "hidden" + attribute set. On Unix platform, this value identifies files whose + names begin with a period ("."). + + +Returns +~~~~~~~ + +- A pointer to the next entry in the directory. +- If the end of the directory is reached or an error occurs, ``NULL``. + The reason can be retrieved via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_ReadDir` returns a pointer to a directory entry structure: + +.. code:: + + struct PRDirEntry { + const char *name; + }; + + typedef struct PRDirEntry PRDirEntry; + +The structure has the following field: + +``name`` + Name of entry, relative to directory name. + +The ``flags`` parameter is an enum of type ``PRDirFlags``: + +.. code:: + + typedef enum PRDirFlags { + PR_SKIP_NONE = 0x0, + PR_SKIP_DOT = 0x1, + PR_SKIP_DOT_DOT = 0x2, + PR_SKIP_BOTH = 0x3, + PR_SKIP_HIDDEN = 0x4 + } PRDirFlags; + +The memory associated with the returned PRDirEntry structure is managed +by NSPR. The caller must not free the ``PRDirEntry`` structure. +Moreover, the ``PRDirEntry`` structure returned by each :ref:`PR_ReadDir` +call is valid only until the next :ref:`PR_ReadDir` or :ref:`PR_CloseDir` call +on the same :ref:`PRDir` object. + +If the end of the directory is reached, :ref:`PR_ReadDir` returns ``NULL``, +and :ref:`PR_GetError` returns ``PR_NO_MORE_FILES_ERROR``. + + +See Also +-------- + +:ref:`PR_OpenDir` diff --git a/docs/nspr/reference/pr_realloc.rst b/docs/nspr/reference/pr_realloc.rst new file mode 100644 index 0000000000..011b389086 --- /dev/null +++ b/docs/nspr/reference/pr_realloc.rst @@ -0,0 +1,43 @@ + +PR_Realloc +========== + +Resizes allocated memory on the heap. + + +Syntax +------ + +.. code:: + + #include <prmem.h> + + void *PR_Realloc ( + void *ptr, + PRUint32 size); + + +Parameters +~~~~~~~~~~ + +``ptr`` + A pointer to the existing memory block being resized. +``size`` + The size of the new memory block. + + +Returns +~~~~~~~ + +An untyped pointer to the allocated memory, or if the allocation attempt +fails, ``NULL``. Call ``PR_GetError()`` to retrieve the error returned +by the libc function ``realloc()``. + + +Description +~~~~~~~~~~~ + +This function attempts to enlarge or shrink the memory block addressed +by ptr to a new size. The contents of the specified memory remains the +same up to the smaller of its old size and new size, although the new +memory block's address can be different from the original address. diff --git a/docs/nspr/reference/pr_recv.rst b/docs/nspr/reference/pr_recv.rst new file mode 100644 index 0000000000..bfc1b7e5f9 --- /dev/null +++ b/docs/nspr/reference/pr_recv.rst @@ -0,0 +1,56 @@ +PR_Recv +======= + +Receives bytes from a connected socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Recv( + PRFileDesc *fd, + void *buf, + PRInt32 amount, + PRIntn flags, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``buf`` + A pointer to a buffer to hold the data received. +``amount`` + The size of ``buf`` (in bytes). +``flags`` + Must be zero or ``PR_MSG_PEEK``. +``timeout`` + A value of type :ref:`PRIntervalTime` specifying the time limit for + completion of the receive operation. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- A positive number indicates the number of bytes actually received. +- The value 0 means the network connection is closed. +- The value -1 indicates a failure. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_Recv` blocks until some positive number of bytes are transferred, +a timeout occurs, or an error occurs. No more than ``amount`` bytes will +be transferred. diff --git a/docs/nspr/reference/pr_recvfrom.rst b/docs/nspr/reference/pr_recvfrom.rst new file mode 100644 index 0000000000..4d2cee79f6 --- /dev/null +++ b/docs/nspr/reference/pr_recvfrom.rst @@ -0,0 +1,62 @@ +PR_RecvFrom +=========== + +Receives bytes from a socket and stores the sending peer's address. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_RecvFrom( + PRFileDesc *fd, + void *buf, + PRInt32 amount, + PRIntn flags, + PRNetAddr *addr, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``buf`` + A pointer to a buffer containing the data received. +``amount`` + The size of ``buf`` (in bytes). +``flags`` + This obsolete parameter must always be zero. +``addr`` + A pointer to the :ref:`PRNetAddr` object that will be filled in with the + address of the sending peer on return. +``timeout`` + A value of type :ref:`PRIntervalTime` specifying the time limit for + completion of the receive operation. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- A positive number indicates the number of bytes actually received. +- The value 0 means the network connection is closed. +- The value -1 indicates a failure. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_RecvFrom` receives up to a specified number of bytes from socket, +which may or may not be connected. The operation blocks until one or +more bytes are transferred, a timeout has occurred, or there is an +error. No more than ``amount`` bytes will be transferred. +:ref:`PR_RecvFrom` is usually used with a UDP socket. diff --git a/docs/nspr/reference/pr_remove_and_init_link.rst b/docs/nspr/reference/pr_remove_and_init_link.rst new file mode 100644 index 0000000000..667a072b21 --- /dev/null +++ b/docs/nspr/reference/pr_remove_and_init_link.rst @@ -0,0 +1,29 @@ +PR_REMOVE_AND_INIT_LINK +======================= + +Removes an element from a circular list and initializes the linkage. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_REMOVE_AND_INIT_LINK (PRCList *elemp); + + +Parameter +~~~~~~~~~ + +``elemp`` + A pointer to the element. + + +Description +----------- + +:ref:`PR_REMOVE_AND_INIT_LINK` removes the specified element from its +circular list and initializes the links of the element to point to +itself. diff --git a/docs/nspr/reference/pr_remove_link.rst b/docs/nspr/reference/pr_remove_link.rst new file mode 100644 index 0000000000..ab5492f810 --- /dev/null +++ b/docs/nspr/reference/pr_remove_link.rst @@ -0,0 +1,27 @@ +PR_REMOVE_LINK +============== + +Removes an element from a circular list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + PR_REMOVE_LINK (PRCList *elemp); + + +Parameter +~~~~~~~~~ + +``elemp`` + A pointer to the element. + + +Description +----------- + +:ref:`PR_REMOVE_LINK` removes the specified element from its circular list. diff --git a/docs/nspr/reference/pr_rename.rst b/docs/nspr/reference/pr_rename.rst new file mode 100644 index 0000000000..67bb1b2673 --- /dev/null +++ b/docs/nspr/reference/pr_rename.rst @@ -0,0 +1,45 @@ +PR_Rename +========= + +Renames a file. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Rename( + const char *from, + const char *to); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``from`` + The old name of the file to be renamed. +``to`` + The new name of the file. + + +Returns +~~~~~~~ + +One of the following values: + +- If file is successfully renamed, ``PR_SUCCESS``. +- If file is not successfully renamed, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_Rename` renames a file from its old name (``from``) to a new name +(``to``). If a file with the new name already exists, :ref:`PR_Rename` +fails with the error code ``PR_FILE_EXISTS_ERROR``. In this case, +:ref:`PR_Rename` does not overwrite the existing filename. diff --git a/docs/nspr/reference/pr_rmdir.rst b/docs/nspr/reference/pr_rmdir.rst new file mode 100644 index 0000000000..7aa4aeb8c7 --- /dev/null +++ b/docs/nspr/reference/pr_rmdir.rst @@ -0,0 +1,46 @@ +PR_RmDir +======== + +Removes a directory with a specified name. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_RmDir(const char *name); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``name`` + The name of the directory to be removed. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The actual reason can be retrieved + via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_RmDir` removes the directory specified by the pathname ``name``. +The directory must be empty. If the directory is not empty, :ref:`PR_RmDir` +fails and :ref:`PR_GetError` returns the error code +``PR_DIRECTORY_NOT_EMPTY_ERROR``. + + +See Also +-------- + +:ref:`PR_MkDir` diff --git a/docs/nspr/reference/pr_secondstointerval.rst b/docs/nspr/reference/pr_secondstointerval.rst new file mode 100644 index 0000000000..18c8947a36 --- /dev/null +++ b/docs/nspr/reference/pr_secondstointerval.rst @@ -0,0 +1,30 @@ +PR_SecondsToInterval +==================== + +Converts standard clock seconds to platform-dependent intervals. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRIntervalTime PR_SecondsToInterval(PRUint32 seconds); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``seconds`` + The number of seconds to convert to interval form. + + +Returns +~~~~~~~ + +Platform-dependent equivalent of the value passed in the ``seconds`` +parameter. diff --git a/docs/nspr/reference/pr_seek.rst b/docs/nspr/reference/pr_seek.rst new file mode 100644 index 0000000000..b06351d059 --- /dev/null +++ b/docs/nspr/reference/pr_seek.rst @@ -0,0 +1,85 @@ +PR_Seek +======= + +Moves the current read-write file pointer by an offset expressed as a +32-bit integer. + +.. container:: blockIndicator deprecated deprecatedHeader + + | **Deprecated** + | This feature is no longer recommended. Though some browsers might + still support it, it may have already been removed from the + relevant web standards, may be in the process of being dropped, or + may only be kept for compatibility purposes. Avoid using it, and + update existing code if possible; see the `compatibility + table <#Browser_compatibility>`__ at the bottom of this page to + guide your decision. Be aware that this feature may cease to work + at any time. + +Deprecated in favor of :ref:`PR_Seek64`. + + +Syntax +~~~~~~ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Seek( + PRFileDesc *fd, + PRInt32 offset, + PRSeekWhence whence); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object. +``offset`` + A value, in bytes, used with the whence parameter to set the file + pointer. A negative value causes seeking in the reverse direction. +``whence`` + A value of type :ref:`PRSeekWhence` that specifies how to interpret the + ``offset`` parameter in setting the file pointer associated with the + fd parameter. The value for the ``whence`` parameter can be one of + the following: + + - :ref:`PR_SEEK_SET`. Sets the file pointer to the value of the + ``offset`` parameter. + - :ref:`PR_SEEK_CUR`. Sets the file pointer to its current location + plus the value of the ``offset`` parameter. + - :ref:`PR_SEEK_END`. Sets the file pointer to the size of the file + plus the value of the ``offset`` parameter. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the function completes successfully, it returns the resulting file + pointer location, measured in bytes from the beginning of the file. +- If the function fails, the file pointer remains unchanged and the + function returns -1. The error code can then be retrieved with + :ref:`PR_GetError`. + + +Description +----------- + +Here's an idiom for obtaining the current location of the file pointer +for the file descriptor ``fd``: + +``PR_Seek(fd, 0, PR_SEEK_CUR)`` + + +See Also +-------- + +If you need to move the file pointer by a large offset that's out of the +range of a 32-bit integer, use :ref:`PR_Seek64`. New code should use +:ref:`PR_Seek64` so that it can handle files larger than 2 GB. diff --git a/docs/nspr/reference/pr_seek64.rst b/docs/nspr/reference/pr_seek64.rst new file mode 100644 index 0000000000..3c144575dc --- /dev/null +++ b/docs/nspr/reference/pr_seek64.rst @@ -0,0 +1,73 @@ +PR_Seek64 +========= + +Moves the current read-write file pointer by an offset expressed as a +64-bit integer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt64 PR_Seek64( + PRFileDesc *fd, + PRInt64 offset, + PRSeekWhence whence); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object. +``offset`` + A value, in bytes, used with the whence parameter to set the file + pointer. A negative value causes seeking in the reverse direction. +``whence`` + A value of type :ref:`PRSeekWhence` that specifies how to interpret the + ``offset`` parameter in setting the file pointer associated with the + fd parameter. The value for the ``whence`` parameter can be one of + the following: + + - :ref:`PR_SEEK_SET`. Sets the file pointer to the value of the + ``offset`` parameter. + - :ref:`PR_SEEK_CUR`. Sets the file pointer to its current location + plus the value of the ``offset`` parameter. + - :ref:`PR_SEEK_END`. Sets the file pointer to the size of the file + plus the value of the ``offset`` parameter. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the function completes successfully, it returns the resulting file + pointer location, measured in bytes from the beginning of the file. +- If the function fails, the file pointer remains unchanged and the + function returns -1. The error code can then be retrieved with + :ref:`PR_GetError`. + + +Description +----------- + +This is the idiom for obtaining the current location (expressed as a +64-bit integer) of the file pointer for the file descriptor ``fd``: + +``PR_Seek64(fd, 0, PR_SEEK_CUR)`` + +If the operating system can handle only a 32-bit file offset, +:ref:`PR_Seek64` may fail with the error code ``PR_FILE_TOO_BIG_ERROR`` if +the ``offset`` parameter is out of the range of a 32-bit integer. + + +See Also +-------- + +:ref:`PR_Seek` diff --git a/docs/nspr/reference/pr_send.rst b/docs/nspr/reference/pr_send.rst new file mode 100644 index 0000000000..1ffdad63e4 --- /dev/null +++ b/docs/nspr/reference/pr_send.rst @@ -0,0 +1,56 @@ +PR_Send +======= + +Sends bytes from a connected socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Send( + PRFileDesc *fd, + const void *buf, + PRInt32 amount, + PRIntn flags, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``buf`` + A pointer to a buffer containing the data to be sent. +``amount`` + The size of ``buf`` (in bytes). +``flags`` + This obsolete parameter must always be zero. +``timeout`` + A value of type :ref:`PRIntervalTime` specifying the time limit for + completion of the receive operation. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- A positive number indicates the number of bytes successfully sent. If + the parameter fd is a blocking socket, this number must always equal + amount. +- The value -1 indicates a failure. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_Send` blocks until all bytes are sent, a timeout occurs, or an +error occurs. diff --git a/docs/nspr/reference/pr_sendto.rst b/docs/nspr/reference/pr_sendto.rst new file mode 100644 index 0000000000..ba3ce59868 --- /dev/null +++ b/docs/nspr/reference/pr_sendto.rst @@ -0,0 +1,58 @@ +PR_SendTo +========= + +Sends bytes a socket to a specified destination. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_SendTo( + PRFileDesc *fd, + const void *buf, + PRInt32 amount, + PRIntn flags, + const PRNetAddr *addr, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a socket. +``buf`` + A pointer to a buffer containing the data to be sent. +``amount`` + The size of ``buf`` (in bytes). +``flags`` + This obsolete parameter must always be zero. +``addr`` + A pointer to the address of the destination. +``timeout`` + A value of type :ref:`PRIntervalTime` specifying the time limit for + completion of the receive operation. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- A positive number indicates the number of bytes successfully sent. +- The value -1 indicates a failure. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_SendTo` sends a specified number of bytes from a socket to the +specified destination address. The calling thread blocks until all bytes +are sent, a timeout has occurred, or there is an error. diff --git a/docs/nspr/reference/pr_setconcurrency.rst b/docs/nspr/reference/pr_setconcurrency.rst new file mode 100644 index 0000000000..309a0312bc --- /dev/null +++ b/docs/nspr/reference/pr_setconcurrency.rst @@ -0,0 +1,42 @@ +PR_SetConcurrency +================= + +Creates extra virtual processor threads. Generally used with MP systems. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_SetConcurrency(PRUintn numCPUs); + + +Parameter +~~~~~~~~~ + +:ref:`PR_SetConcurrency` has one parameter: + +``numCPUs`` + The number of extra virtual processor threads to be created. + + +Description +----------- + +Setting concurrency controls the number of virtual processors that NSPR +uses to implement its ``M x N`` threading model. The ``M x N`` model is +not available on all host systems. On those where it is not available, +:ref:`PR_SetConcurrency` is ignored. + +Virtual processors are actually\ *global* threads, each of which is +designed to support an arbitrary number of\ *local* threads. Since +global threads are scheduled by the host operating system, this model is +particularly applicable to multiprocessor architectures, where true +parallelism is possible. However, it may also prove advantageous on +uniprocessor systems to reduce the impact of having a locally scheduled +thread calling incidental blocking functions. In such cases, all the +threads being supported by the virtual processor will block, but those +assigned to another virtual processor will be unaffected. diff --git a/docs/nspr/reference/pr_seterror.rst b/docs/nspr/reference/pr_seterror.rst new file mode 100644 index 0000000000..87d256139a --- /dev/null +++ b/docs/nspr/reference/pr_seterror.rst @@ -0,0 +1,35 @@ +PR_SetError +=========== + +Sets error information within a thread context. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + void PR_SetError(PRErrorCode errorCode, PRInt32 oserr) + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``errorCode`` + The NSPR (platform-independent) translation of the error. + +``oserr`` + The platform-specific error. If there is no appropriate OS error + number, a zero may be supplied. + + +Description +----------- + +NSPR does not validate the value of the error number or OS error number +being specified. The runtime merely stores the value and returns it when +requested. diff --git a/docs/nspr/reference/pr_seterrortext.rst b/docs/nspr/reference/pr_seterrortext.rst new file mode 100644 index 0000000000..5fa385cc52 --- /dev/null +++ b/docs/nspr/reference/pr_seterrortext.rst @@ -0,0 +1,43 @@ +PR_SetErrorText +=============== + +Sets the text associated with an error. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + void PR_SetErrorText(PRIntn textLength, const char *text) + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``textLength`` + The length of the text in the ``text``. May be ``NULL``. If not + ``NULL``, and if ``text`` is zero, the string is assumed to be a + null-terminated C string. Otherwise the text is assumed to be the + length specified and to possibly include ``NULL`` characters (as + might occur in a multilingual string). + +``text`` + The text to associate with the error. + + +Description +----------- + +The text is copied into the thread structure and remains there until the +next call to :ref:`PR_SetError`. If there is error text already present in +the thread, the previous value is first deleted. The new value is copied +into storage allocated and owned by NSPR and remains there until the +next call to :ref:`PR_SetError` or another call to :ref:`PR_SetErrorText`. + +NSPR makes no use of this function. Clients may use it for their own +purposes. diff --git a/docs/nspr/reference/pr_setlibrarypath.rst b/docs/nspr/reference/pr_setlibrarypath.rst new file mode 100644 index 0000000000..52336e62d9 --- /dev/null +++ b/docs/nspr/reference/pr_setlibrarypath.rst @@ -0,0 +1,45 @@ +PR_SetLibraryPath +================= + +Registers a default library pathname with a runtime. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + PRStatus PR_SetLibraryPath(const char *path); + + +Parameters +~~~~~~~~~~ + +The function has this parameter: + +``path`` + A pointer to a character array that contains the directory path that + the application should use as a default. The syntax of the pathname + is not defined, nor whether that pathname should be absolute or + relative. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. This may indicate that the function + cannot allocate sufficient storage to make a copy of the path string + + +Description +----------- + +This function registers a default library pathname with the runtime. +This allows an environment to express policy decisions globally and +lazily, rather than hardcoding and distributing the decisions throughout +the code. diff --git a/docs/nspr/reference/pr_setpollableevent.rst b/docs/nspr/reference/pr_setpollableevent.rst new file mode 100644 index 0000000000..e9de4eb19e --- /dev/null +++ b/docs/nspr/reference/pr_setpollableevent.rst @@ -0,0 +1,32 @@ +PR_SetPollableEvent +=================== + +Set a pollable event. + + +Syntax +------ + +.. code:: + + NSPR_API(PRStatus) PR_SetPollableEvent(PRFileDesc *event); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``event`` + Pointer to a :ref:`PRFileDesc` structure previously created via a call + to :ref:`PR_NewPollableEvent`. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + retrieved via :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_setsocketoption.rst b/docs/nspr/reference/pr_setsocketoption.rst new file mode 100644 index 0000000000..8484a4b727 --- /dev/null +++ b/docs/nspr/reference/pr_setsocketoption.rst @@ -0,0 +1,45 @@ +PR_SetSocketOption +================== + +Retrieves the socket options set for a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_SetSocketOption( + PRFileDesc *fd, + PRSocketOptionData *data); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing the socket whose + options are to be set. +``data`` + A pointer to a structure of type :ref:`PRSocketOptionData` specifying + the options to set. + + +Returns +~~~~~~~ + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +On input, the caller must set both the ``option`` and ``value`` fields +of the :ref:`PRSocketOptionData` object pointed to by the ``data`` +parameter. diff --git a/docs/nspr/reference/pr_setthreadpriority.rst b/docs/nspr/reference/pr_setthreadpriority.rst new file mode 100644 index 0000000000..32ca051656 --- /dev/null +++ b/docs/nspr/reference/pr_setthreadpriority.rst @@ -0,0 +1,37 @@ +PR_SetThreadPriority +==================== + +Sets the priority of a specified thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + void PR_SetThreadPriority( + PRThread *thread, + PRThreadPriority priority); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_SetThreadPriority` has the following parameters: + +``thread`` + A valid identifier for the thread whose priority you want to set. +``priority`` + The priority you want to set. + + +Description +----------- + +Modifying the priority of a thread other than the calling thread is +risky. It is difficult to ensure that the state of the target thread +permits a priority adjustment without ill effects. It is preferable for +a thread to specify itself in the thread parameter when it calls +:ref:`PR_SetThreadPriority`. diff --git a/docs/nspr/reference/pr_setthreadprivate.rst b/docs/nspr/reference/pr_setthreadprivate.rst new file mode 100644 index 0000000000..0f24c5b386 --- /dev/null +++ b/docs/nspr/reference/pr_setthreadprivate.rst @@ -0,0 +1,56 @@ +PR_SetThreadPrivate +=================== + +Sets per-thread private data. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRStatus PR_SetThreadPrivate(PRUintn index, void *priv); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_SetThreadPrivate` has the following parameters: + +``index`` + An index into the per-thread private data table. +``priv`` + The per-thread private data, or more likely, a pointer to the data. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If the index is invalid, ``PR_FAILURE``. + + +Description +----------- + +If the thread already has non-``NULL`` private data associated with it, +and if the destructor function for the index is known (not ``NULL``), +NSPR calls the destructor function associated with the index before +setting the new data value. The pointer at the index is swapped with +``NULL``. If the swapped out value is not ``NULL``, the destructor +function is called. On return, the private data associated with the +index is reassigned the new private data's value, even if it is +``NULL``. The runtime provides no protection for the private data. The +destructor is called with the runtime holding no locks. Synchronization +is the client's responsibility. + +The only way to eliminate thread private data at an index prior to the +thread's termination is to call :ref:`PR_SetThreadPrivate` with a ``NULL`` +argument. This causes the index's destructor function to be called, and +afterwards assigns a ``NULL`` in the table. A client must not delete the +referent object of a non-``NULL`` private data without first eliminating +it from the table. diff --git a/docs/nspr/reference/pr_shutdown.rst b/docs/nspr/reference/pr_shutdown.rst new file mode 100644 index 0000000000..faee7dfe15 --- /dev/null +++ b/docs/nspr/reference/pr_shutdown.rst @@ -0,0 +1,57 @@ +PR_Shutdown +=========== + +Shuts down part of a full-duplex connection on a specified socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Shutdown( + PRFileDesc *fd, + PRShutdownHow how); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object representing a connected socket. +``how`` + The kind of disallowed operations on the socket. Possible values + include the following: + + - :ref:`PR_SHUTDOWN_RCV`. Further receives will be disallowed. + - :ref:`PR_SHUTDOWN_SEND`. Further sends will be disallowed. + - :ref:`PR_SHUTDOWN_BOTH`. Further sends and receives will be + disallowed. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- Upon successful completion of shutdown request, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. Further information can be obtained + by calling :ref:`PR_GetError`. + + +Description +----------- + +The ``PRShutdownHow`` enumeration is defined as follows: + +.. code:: + + typedef enum PRShutdownHow{ + PR_SHUTDOWN_RCV = 0, + PR_SHUTDOWN_SEND = 1, + PR_SHUTDOWN_BOTH = 2 + } PRShutdownHow; diff --git a/docs/nspr/reference/pr_shutdownthreadpool.rst b/docs/nspr/reference/pr_shutdownthreadpool.rst new file mode 100644 index 0000000000..3fb411af64 --- /dev/null +++ b/docs/nspr/reference/pr_shutdownthreadpool.rst @@ -0,0 +1,30 @@ +PR_ShutdownThreadPool +===================== + +Notifies all threads in a thread pool to terminate. + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + NSPR_API(PRStatus) PR_ShutdownThreadPool( PRThreadPool *tpool ); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``tpool`` + A pointer to a :ref:`PRThreadPool` structure previously created by a + call to :ref:`PR_CreateThreadPool`. + + +Returns +~~~~~~~ + +:ref:`PRStatus` diff --git a/docs/nspr/reference/pr_sleep.rst b/docs/nspr/reference/pr_sleep.rst new file mode 100644 index 0000000000..b3ad0ec2cd --- /dev/null +++ b/docs/nspr/reference/pr_sleep.rst @@ -0,0 +1,52 @@ +PR_Sleep +======== + +Causes the current thread to yield for a specified amount of time. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + PRStatus PR_Sleep(PRIntervalTime ticks); + + +Parameter +~~~~~~~~~ + +:ref:`PR_Sleep` has the following parameter: + +``ticks`` + The number of ticks you want the thread to sleep for (see + :ref:`PRIntervalTime`). + + +Returns +~~~~~~~ + +Calling :ref:`PR_Sleep` with a parameter equivalent to +``PR_INTERVAL_NO_TIMEOUT`` is an error and results in a ``PR_FAILURE`` +error. + + +Description +----------- + +:ref:`PR_Sleep` simply waits on a condition for the amount of time +specified. If you set ticks to ``PR_INTERVAL_NO_WAIT``, the thread +yields. + +If ticks is not ``PR_INTERVAL_NO_WAIT``, :ref:`PR_Sleep` uses an existing +lock, but has to create a new condition for this purpose. If you have +already created such structures, it is more efficient to use them +directly. + +Calling :ref:`PR_Sleep` with the value of ticks set to +``PR_INTERVAL_NO_WAIT`` simply surrenders the processor to ready threads +of the same priority. All other values of ticks cause :ref:`PR_Sleep` to +block the calling thread for the specified interval. + +Threads blocked in :ref:`PR_Sleep` are interruptible. diff --git a/docs/nspr/reference/pr_static_assert.rst b/docs/nspr/reference/pr_static_assert.rst new file mode 100644 index 0000000000..4aa2e31c58 --- /dev/null +++ b/docs/nspr/reference/pr_static_assert.rst @@ -0,0 +1,46 @@ +PR_STATIC_ASSERT +================ + +Prevents code from compiling when an expression has the value ``FALSE`` +at compile time. + + +Syntax +------ + +.. code:: + + #include <prlog.h> + + PR_STATIC_ASSERT ( expression ); + + +Parameters +~~~~~~~~~~ + +The macro has this parameter: + +expression + Any valid expression which evaluates at compile-time to ``TRUE`` or + ``FALSE``. An expression which cannot be evaluated at compile time + will cause a compiler error; see :ref:`PR_ASSERT` for a runtime + alternative. + + +Returns +~~~~~~~ + +Nothing + + +Description +----------- + +This macro evaluates the specified expression. When the result is zero +(``FALSE``) program compilation will fail with a compiler error; +otherwise compilation completes successfully. The compiler error will +include the number of the line for which the compile-time assertion +failed. + +This macro may only be used in locations where an ``extern`` function +declaration may be used. diff --git a/docs/nspr/reference/pr_stringtonetaddr.rst b/docs/nspr/reference/pr_stringtonetaddr.rst new file mode 100644 index 0000000000..af6e3b3e4f --- /dev/null +++ b/docs/nspr/reference/pr_stringtonetaddr.rst @@ -0,0 +1,48 @@ +PR_StringToNetAddr +================== + +Converts a character string to a network address. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + PRStatus PR_StringToNetAddr( + const char *string, + PRNetAddr *addr); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``string`` + The string to be converted. +``addr`` + On output, the equivalent network address. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. You can retrieve the reason for the + failure by calling :ref:`PR_GetError`. + + +Description +----------- + +For IPv4 addresses, the input string represents numbers in the Internet +standard "." notation. IPv6 addresses are indicated as strings using ":" +characters separating octets, with numerous caveats for shortcutting +(see RFC #1884). If the NSPR library and the host are configured to +support IPv6, both formats are supported. Otherwise, use of anything +other than IPv4 dotted notation results in an error. diff --git a/docs/nspr/reference/pr_strtod.rst b/docs/nspr/reference/pr_strtod.rst new file mode 100644 index 0000000000..af870ce03b --- /dev/null +++ b/docs/nspr/reference/pr_strtod.rst @@ -0,0 +1,50 @@ +PR_strtod +========= + +Converts the prefix of a decimal string to the nearest double-precision +floating point number. + + +Syntax +------ + +.. code:: + + #include <prdtoa.h> + + PRFloat64 PR_strtod(const char *s00, char **se); + + +Parameters +~~~~~~~~~~ + +The function has these parameters: + +``s00`` + The input string to be scanned. +``se`` + A pointer that, if not ``NULL``, will be assigned the address of the + last character scanned in the input string. + + +Returns +~~~~~~~ + +The result of the conversion is a ``PRFloat64`` value equivalent to the +input string. If the parameter ``se`` is not ``NULL`` the location it +references is also set. + + +Description +----------- + +:ref:`PR_strtod` converts the prefix of the input decimal string pointed to +by ``s00`` to a nearest double-precision floating point number. Ties are +broken by the IEEE round-even rule. The string is scanned up to the +first unrecognized character. If the value of ``se`` is not +(``char **``) ``NULL``, :ref:`PR_strtod` stores a pointer to the character +terminating the scan in ``*se``. If the answer would overflow, a +properly signed ``HUGE_VAL`` (infinity) is returned. If the answer would +underflow, a properly signed 0 is returned. In both cases, +``PR_GetError()`` returns the error code ``PR_RANGE_ERROR``. If no +number can be formed, ``se`` is set to ``s00``, and 0 is returned. diff --git a/docs/nspr/reference/pr_sync.rst b/docs/nspr/reference/pr_sync.rst new file mode 100644 index 0000000000..5d6df28689 --- /dev/null +++ b/docs/nspr/reference/pr_sync.rst @@ -0,0 +1,40 @@ +PR_Sync +======= + +Synchronizes any buffered data for a file descriptor to its backing +device (disk). + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_Sync(PRFileDesc *fd); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``fd`` + Pointer to a :ref:`PRFileDesc` object representing a file. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- On successful completion, ``PR_SUCCESS``. +- If the function fails, ``PR_FAILURE``. + + +Description +----------- + +:ref:`PR_Sync` writes all the in-memory buffered data of the specified file +to the disk. diff --git a/docs/nspr/reference/pr_tickspersecond.rst b/docs/nspr/reference/pr_tickspersecond.rst new file mode 100644 index 0000000000..362a817d94 --- /dev/null +++ b/docs/nspr/reference/pr_tickspersecond.rst @@ -0,0 +1,36 @@ +PR_TicksPerSecond +================= + +Returns the number of ticks per second currently used to determine the +value of :ref:`PRIntervalTime`. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + PRUint32 PR_TicksPerSecond(void); + + +Returns +~~~~~~~ + +An integer between 1000 and 100000 indicating the number of ticks per +second counted by :ref:`PRIntervalTime` on the current platform. This value +is platform-dependent and does not change after NSPR is initialized. + + +Description +----------- + +The value returned by ``PR_TicksPerSecond()`` lies between +``PR_INTERVAL_MIN`` and ``PR_INTERVAL_MAX``. + +The relationship between a :ref:`PRIntervalTime` tick and standard clock +units is platform-dependent. PR\_\ ``PR_TicksPerSecond()`` allows you to +discover exactly what that relationship is. Seconds per tick (the +inverse of PR\_\ ``PR_TicksPerSecond()``) is always between 10 +microseconds and 1 millisecond. diff --git a/docs/nspr/reference/pr_transmitfile.rst b/docs/nspr/reference/pr_transmitfile.rst new file mode 100644 index 0000000000..c9812b072e --- /dev/null +++ b/docs/nspr/reference/pr_transmitfile.rst @@ -0,0 +1,76 @@ +PR_TransmitFile +=============== + +Sends a complete file across a connected socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_TransmitFile( + PRFileDesc *networkSocket, + PRFileDesc *sourceFile, + const void *headers, + PRInt32 hlen, + PRTransmitFileFlags flags, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``networkSocket`` + A pointer to a :ref:`PRFileDesc` object representing the connected + socket to send data over. +``sourceFile`` + A pointer to a :ref:`PRFileDesc` object representing the file to send. +``headers`` + A pointer to the buffer holding the headers to be sent before sending + data. +``hlen`` + Length of the ``headers`` buffer in bytes. +``flags`` + One of the following flags: + + - :ref:`PR_TRANSMITFILE_KEEP_OPEN` indicates that the socket will be kept + open after the data is sent. + - :ref:`PR_TRANSMITFILE_CLOSE_SOCKET` indicates that the connection should + be closed immediately after successful transfer of the file. + +``timeout`` + Time limit for completion of the transmit operation. + + +Returns +~~~~~~~ + +- A positive number indicates the number of bytes successfully written, + including both the headers and the file. +- The value -1 indicates a failure. If an error occurs while sending + the file, the ``PR_TRANSMITFILE_CLOSE_SOCKET`` flag is ignored. The + reason for the failure can be obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +The :ref:`PR_TransmitFile` function sends a complete file (``sourceFile``) +across a connected socket (``networkSocket``). If ``headers`` is +non-``NULL``, :ref:`PR_TransmitFile` sends the headers across the socket +before sending the file. + +The enumeration ``PRTransmitFileFlags``, used in the ``flags`` +parameter, is defined as follows: + +.. code:: + + typedef enum PRTransmitFileFlags { + PR_TRANSMITFILE_KEEP_OPEN = 0, + PR_TRANSMITFILE_CLOSE_SOCKET = 1 + } PRTransmitFileFlags; diff --git a/docs/nspr/reference/pr_unblockclockinterrupts.rst b/docs/nspr/reference/pr_unblockclockinterrupts.rst new file mode 100644 index 0000000000..79bf984272 --- /dev/null +++ b/docs/nspr/reference/pr_unblockclockinterrupts.rst @@ -0,0 +1,14 @@ +PR_UnblockClockInterrupts +========================= + +Unblocks the timer signal used for preemptive scheduling. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + void PR_UnblockClockInterrupts(void); diff --git a/docs/nspr/reference/pr_unloadlibrary.rst b/docs/nspr/reference/pr_unloadlibrary.rst new file mode 100644 index 0000000000..fc9659c4e4 --- /dev/null +++ b/docs/nspr/reference/pr_unloadlibrary.rst @@ -0,0 +1,41 @@ +PR_UnloadLibrary +================ + +Unloads a library loaded with :ref:`PR_LoadLibrary`. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + PRStatus PR_UnloadLibrary(PRLibrary *lib); + + +Parameters +~~~~~~~~~~ + +The function has this parameter: + +``lib`` + A reference previously returned from :ref:`PR_LoadLibrary`. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. Use :ref:`PR_GetError` to find the + reason for the failure. + + +Description +----------- + +This function undoes the effect of a :ref:`PR_LoadLibrary`. After calling +this function, future references to the library using its identity as +returned by :ref:`PR_LoadLibrary` will be invalid. diff --git a/docs/nspr/reference/pr_unlock.rst b/docs/nspr/reference/pr_unlock.rst new file mode 100644 index 0000000000..4243a7510f --- /dev/null +++ b/docs/nspr/reference/pr_unlock.rst @@ -0,0 +1,43 @@ +PR_Unlock +========= + +Releases a specified lock object. Releasing an unlocked lock results in +an error. + +Attempting to release a lock that was locked by a different thread +causes undefined behavior. + + +Syntax +------ + +.. code:: + + #include <prlock.h> + + PRStatus PR_Unlock(PRLock *lock); + + +Parameter +~~~~~~~~~ + +:ref:`PR_Unlock` has one parameter: + +``lock`` + A pointer to a lock object to be released. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful (for example, if the caller does not own the lock), + ``PR_FAILURE``. + + +See Also +-------- + +- `PR_Lock <PR_Lock>`__ diff --git a/docs/nspr/reference/pr_unmap.rst b/docs/nspr/reference/pr_unmap.rst new file mode 100644 index 0000000000..85182b6e02 --- /dev/null +++ b/docs/nspr/reference/pr_unmap.rst @@ -0,0 +1,45 @@ +PR_MemUnmap +=========== + +Unmap a memory region that is backed by a memory-mapped file. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRStatus PR_MemUnmap( + void *addr, + PRUint32 len); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``addr`` + The starting address of the memory region to be unmapped. +``len`` + The length, in bytes, of the memory region. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the memory region is successfully unmapped, ``PR_SUCCESS``. +- If the memory region is not successfully unmapped, ``PR_FAILURE``. + The error code can be retrieved via :ref:`PR_GetError`. + + +Description +----------- + +:ref:`PR_MemUnmap` removes the file mapping for the memory region +(``addr``, ``addr + len``). The parameter ``addr`` is the return value +of an earlier call to :ref:`PR_MemMap`. diff --git a/docs/nspr/reference/pr_usec_per_msec.rst b/docs/nspr/reference/pr_usec_per_msec.rst new file mode 100644 index 0000000000..afed88bd57 --- /dev/null +++ b/docs/nspr/reference/pr_usec_per_msec.rst @@ -0,0 +1,16 @@ +PR_USEC_PER_MSEC +================ + +A convenience macro to improve code readability as well as to avoid +mistakes in counting the number of zeros; represents the number of +microseconds in a millisecond. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + #define PR_USEC_PER_MSEC 1000UL diff --git a/docs/nspr/reference/pr_usec_per_sec.rst b/docs/nspr/reference/pr_usec_per_sec.rst new file mode 100644 index 0000000000..8389f7db6b --- /dev/null +++ b/docs/nspr/reference/pr_usec_per_sec.rst @@ -0,0 +1,16 @@ +PR_USEC_PER_SEC +=============== + +A convenience macro to improve code readability as well as to avoid +mistakes in counting the number of zeros; represents the number of +microseconds in a second. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + #define PR_USEC_PER_SEC 1000000UL diff --git a/docs/nspr/reference/pr_version.rst b/docs/nspr/reference/pr_version.rst new file mode 100644 index 0000000000..bb838b14ff --- /dev/null +++ b/docs/nspr/reference/pr_version.rst @@ -0,0 +1,19 @@ +PR_VERSION +========== + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + #define PR_VERSION "2.1 yyyymmdd" + + +Description +----------- + +The format of the version string is\ *MajorVersion.MinorVersion +BuildDate*. diff --git a/docs/nspr/reference/pr_versioncheck.rst b/docs/nspr/reference/pr_versioncheck.rst new file mode 100644 index 0000000000..5d42827ad3 --- /dev/null +++ b/docs/nspr/reference/pr_versioncheck.rst @@ -0,0 +1,50 @@ +PR_VersionCheck +=============== + +Compares the version of NSPR assumed by the caller (the imported +version) with the version being offered by the runtime (the exported +version). + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + PRBool PR_VersionCheck(const char *importedVersion); + + +Parameter +~~~~~~~~~ + +:ref:`PR_VersionCheck` has one parameter: + +``importedVersion`` + The version of the shared library being imported. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If the version of the shared library is compatible with that expected + by the caller, ``PR_TRUE``. +- If the versions are not compatible, ``PR_FALSE``. + + +Description +----------- + +:ref:`PR_VersionCheck` tests whether the version of the library being +imported (``importedVersion``) is compatible with the running version of +the shared library. This is a string comparison of sorts, though the +details of the comparison will vary over time. + + +See Also +-------- + +- `PR_VERSION <PR_VERSION>`__ diff --git a/docs/nspr/reference/pr_wait.rst b/docs/nspr/reference/pr_wait.rst new file mode 100644 index 0000000000..3eb6e16f30 --- /dev/null +++ b/docs/nspr/reference/pr_wait.rst @@ -0,0 +1,82 @@ +PR_Wait +======= + +Waits for an application-defined state of the monitored data to exist. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + PRStatus PR_Wait( + PRMonitor *mon, + PRIntervalTime ticks); + + +Parameters +~~~~~~~~~~ + +The function has the following parameter: + +``mon`` + A reference to an existing structure of type :ref:`PRMonitor`. The + monitor object referenced must be one for which the calling thread + currently holds the lock. +``ticks`` + The amount of time (in :ref:`PRIntervalTime` units) that the thread is + willing to wait for an explicit notification before being + rescheduled. + + +Returns +~~~~~~~ + +The function returns one of the following values: + + - :ref:`PR_SUCCESS`` means the thread is being resumed from the ``PR_Wait` + call either because it was explicitly notified or because the time + specified by the parameter ``ticks`` has expired. + - :ref:`PR_FAILURE` means ``PR_Wait`` encountered a system error (such as + an invalid monitor reference) or the thread was interrupted by + another thread. + + +Description +----------- + +A call to :ref:`PR_Wait` causes the thread to release the monitor's lock, +just as if it had called :ref:`PR_ExitMonitor` as many times as it had +called :ref:`PR_EnterMonitor`. This has the effect of making the monitor +available to other threads. When the wait is over, the thread regains +control of the monitor's lock with the same entry count it had before +the wait began. + +A thread waiting on the monitor resumes when the monitor is notified or +when the timeout specified by the ``ticks`` parameter elapses. The +resumption from the wait is merely a hint that a change of state has +occurred. It is the responsibility of the programmer to evaluate the +data and act accordingly. This is usually done by evaluating a Boolean +expression involving the monitored data. While the Boolean expression is +false, the thread should wait. The thread should act on the data only +when the expression is true. The boolean expression must be evaluated +while in the monitor and within a loop. + +In pseudo-code, the sequence is as follows: + +| ``PR_EnterMonitor(&ml);`` +| ``while (!expression) wait;`` +| ``... act on the state change ...`` +| ``PR_ExitMonitor(&ml);`` + +A thread can be resumed from a wait for a variety of reasons. The most +obvious is that it was notified by another thread. If the value of +timeout is not ``PR_INTERVAL_NO_TIMEOUT``, :ref:`PR_Wait` resumes execution +after the specified interval has expired. If a timeout value is used, +the Boolean expression must include elapsed time as part of the +monitored data. + +Resuming from the wait is merely an opportunity to evaluate the +expression, not an assertion that the expression is true. diff --git a/docs/nspr/reference/pr_waitcondvar.rst b/docs/nspr/reference/pr_waitcondvar.rst new file mode 100644 index 0000000000..f915464f7b --- /dev/null +++ b/docs/nspr/reference/pr_waitcondvar.rst @@ -0,0 +1,68 @@ +PR_WaitCondVar +============== + +Waits on a condition. + + +Syntax +------ + +.. code:: + + #include <prcvar.h> + + PRStatus PR_WaitCondVar( + PRCondVar *cvar, + PRIntervalTime timeout); + + +Parameters +~~~~~~~~~~ + +:ref:`PR_WaitCondVar` has the following parameters: + +``cvar`` + The condition variable on which to wait. +``timeout`` + The value ``PR_INTERVAL_NO_TIMEOUT`` requires that a condition be + notified (or the thread interrupted) before it will resume from the + wait. The value ``PR_INTERVAL_NO_WAIT`` causes the thread to release + the lock, possibly causing a rescheduling within the runtime, then + immediately attempt to reacquire the lock and resume. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful (for example, if the caller has not locked the lock + associated with the condition variable or the thread was interrupted + with :ref:`PR_Interrupt`), ``PR_FAILURE``. The details can be determined + with :ref:`PR_GetError`. + + +Description +----------- + +Before the call to :ref:`PR_WaitCondVar`, the lock associated with the +condition variable must be held by the calling thread. After a call to +:ref:`PR_WaitCondVar`, the lock is released and the thread is blocked in a +"waiting on condition" state until another thread notifies the condition +or a caller-specified amount of time expires. + +When the condition variable is notified, a thread waiting on that +condition moves from the "waiting on condition" state to the "ready" +state. When scheduled, the thread attempts to reacquire the lock that it +held when :ref:`PR_WaitCondVar` was called. + +Any value other than ``PR_INTERVAL_NO_TIMEOUT`` or +``PR_INTERVAL_NO_WAIT`` for the timeout parameter will cause the thread +to be rescheduled due to either explicit notification or the expiration +of the specified interval. The latter must be determined by treating +time as one part of the monitored data being protected by the lock and +tested explicitly for an expired interval. To detect the expiration of +the specified interval, call :ref:`PR_IntervalNow` before and after the +call to :ref:`PR_WaitCondVar` and compare the elapsed time with the +specified interval. diff --git a/docs/nspr/reference/pr_waitforpollableevent.rst b/docs/nspr/reference/pr_waitforpollableevent.rst new file mode 100644 index 0000000000..5996dd4872 --- /dev/null +++ b/docs/nspr/reference/pr_waitforpollableevent.rst @@ -0,0 +1,33 @@ +PR_WaitForPollableEvent +======================= + +Blocks the calling thread until the pollable event is set, and then +atomically unsetting the event before returning. + + +Syntax +------ + +.. code:: + + NSPR_API(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``event`` + Pointer to a :ref:`PRFileDesc` structure previously created via a call + to :ref:`PR_NewPollableEvent`. + + +Returns +~~~~~~~ + +The function returns one of the following values: + +- If successful, ``PR_SUCCESS``. +- If unsuccessful, ``PR_FAILURE``. The reason for the failure can be + retrieved via :ref:`PR_GetError`. diff --git a/docs/nspr/reference/pr_waitsemaphore.rst b/docs/nspr/reference/pr_waitsemaphore.rst new file mode 100644 index 0000000000..1a0c7b3d1c --- /dev/null +++ b/docs/nspr/reference/pr_waitsemaphore.rst @@ -0,0 +1,42 @@ +PR_WaitSemaphore +================ + +Returns the value of the environment variable. + + +Syntax +------ + +.. code:: + + #include <pripcsem.h> + + NSPR_API(PRStatus) PR_WaitSemaphore(PRSem *sem); + + +Parameter +~~~~~~~~~ + +The function has the following parameter: + +``sem`` + A pointer to a ``PRSem`` structure returned from a call to + :ref:`PR_OpenSemaphore`. + + +Returns +~~~~~~~ + +:ref:`PRStatus` + + +Description +----------- + +:ref:`PR_WaitSemaphore` tests the value of the semaphore. If the value of +the semaphore is > 0, the value of the semaphore is decremented and the +function returns. If the value of the semaphore is 0, the function +blocks until the value becomes > 0, then the semaphore is decremented +and the function returns. + +The "test and decrement" operation is performed atomically. diff --git a/docs/nspr/reference/pr_write.rst b/docs/nspr/reference/pr_write.rst new file mode 100644 index 0000000000..2ec2f1e5c6 --- /dev/null +++ b/docs/nspr/reference/pr_write.rst @@ -0,0 +1,50 @@ +PR_Write +======== + +Writes a buffer of data to a file or socket. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Write( + PRFileDesc *fd, + const void *buf, + PRInt32 amount); + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to the :ref:`PRFileDesc` object for a file or socket. +``buf`` + A pointer to the buffer holding the data to be written. +``amount`` + The amount of data, in bytes, to be written from the buffer. + + +Returns +~~~~~~~ + +One of the following values: + +- A positive number indicates the number of bytes successfully written. +- The value -1 indicates that the operation failed. The reason for the + failure is obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +The thread invoking :ref:`PR_Write` blocks until all the data is written or +the write operation fails. Therefore, the return value is equal to +either ``amount`` (success) or -1 (failure). Note that if :ref:`PR_Write` +returns -1, some data (less than ``amount`` bytes) may have been written +before an error occurred. diff --git a/docs/nspr/reference/pr_writev.rst b/docs/nspr/reference/pr_writev.rst new file mode 100644 index 0000000000..0100b72afc --- /dev/null +++ b/docs/nspr/reference/pr_writev.rst @@ -0,0 +1,79 @@ +PR_Writev +========= + +Writes data to a socket from multiple buffers. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + PRInt32 PR_Writev( + PRFileDesc *fd, + PRIOVec *iov, + PRInt32 size, + PRIntervalTime timeout); + + #define PR_MAX_IOVECTOR_SIZE 16 + + +Parameters +~~~~~~~~~~ + +The function has the following parameters: + +``fd`` + A pointer to a :ref:`PRFileDesc` object for a socket. +``iov`` + An array of ``PRIOVec`` structures that describe the buffers to write + from. +``size`` + Number of ``PRIOVec`` structures in the ``iov`` array. The value of + this parameter must not be greater than ``PR_MAX_IOVECTOR_SIZE``. If + it is, the function will fail and the error will be set to + ``PR_BUFFER_OVERFLOW_ERROR``. +``timeout`` + A value of type :ref:`PRIntervalTime` describing the time limit for + completion of the entire write operation. + + +Returns +~~~~~~~ + +One of the following values: + +- A positive number indicates the number of bytes successfully written. +- The value -1 indicates that the operation failed. The reason for the + failure can be obtained by calling :ref:`PR_GetError`. + + +Description +----------- + +The thread calling :ref:`PR_Writev` blocks until all the data is written or +the write operation fails. Therefore, the return value is equal to +either the sum of all the buffer lengths (on success) or -1 (on +failure). Note that if :ref:`PR_Writev` returns -1, part of the data may +have been written before an error occurred. If the timeout parameter is +not ``PR_INTERVAL_NO_TIMEOUT`` and all the data cannot be written in the +specified interval, :ref:`PR_Writev` returns -1 with the error code +``PR_IO_TIMEOUT_ERROR``. + +This is the type definition for ``PRIOVec``: + +.. code:: + + typedef struct PRIOVec { + char *iov_base; + int iov_len; + } PRIOVec; + +The ``PRIOVec`` structure has the following fields: + +``iov_base`` + A pointer to the beginning of the buffer. +``iov_len`` + The size of the buffer. diff --git a/docs/nspr/reference/praccesshow.rst b/docs/nspr/reference/praccesshow.rst new file mode 100644 index 0000000000..b269dd93a1 --- /dev/null +++ b/docs/nspr/reference/praccesshow.rst @@ -0,0 +1,17 @@ +PRAccessHow +=========== + +This is the declaration for the enumeration :ref:`PRAccessHow`, used in the +``how`` parameter of :ref:`PR_Access`: + +.. code:: + + #include <prio.h> + + typedef enum PRAccessHow { + PR_ACCESS_EXISTS = 1, + PR_ACCESS_WRITE_OK = 2, + PR_ACCESS_READ_OK = 3 + } PRAccessHow; + +See `PR_Access <en/PR_Access>`__ for what each of these values mean. diff --git a/docs/nspr/reference/prbool.rst b/docs/nspr/reference/prbool.rst new file mode 100644 index 0000000000..098cbae81b --- /dev/null +++ b/docs/nspr/reference/prbool.rst @@ -0,0 +1,27 @@ +PRBool +====== + +Boolean value. + + +Syntax +~~~~~~ + +.. code:: + + #include <prtypes.h> + + typedef enum { PR_FALSE = 0, PR_TRUE = 1 } PRBool; + + +Description +~~~~~~~~~~~ + +Wherever possible, do not use PRBool in Mozilla C++ code. Use standard +C++ ``bool`` instead. + +Otherwise, use :ref:`PRBool` for variables and parameter types. Use +``PR_FALSE`` and ``PR_TRUE`` for clarity of target type in assignments +and actual arguments. Use ``if (bool)``, ``while (!bool)``, +``(bool) ? x : y``, and so on to test Boolean values, just as you would +C ``int``-valued conditions. diff --git a/docs/nspr/reference/prcalloncefn.rst b/docs/nspr/reference/prcalloncefn.rst new file mode 100644 index 0000000000..da37a9c86e --- /dev/null +++ b/docs/nspr/reference/prcalloncefn.rst @@ -0,0 +1,22 @@ +PRCallOnceFN +============ + +Defines the signature of the function a client must implement. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + typedef PRStatus (PR_CALLBACK *PRCallOnceFN)(void); + + +Description +----------- + +The function is called to perform the initialization desired. The +function is expected to return a :ref:`PRStatus` indicating the outcome of +the process. diff --git a/docs/nspr/reference/prcalloncetype.rst b/docs/nspr/reference/prcalloncetype.rst new file mode 100644 index 0000000000..6d306d0222 --- /dev/null +++ b/docs/nspr/reference/prcalloncetype.rst @@ -0,0 +1,41 @@ +PRCallOnceType +============== + +Structure for tracking initialization. + + +Syntax +------ + +.. code:: + + #include <prinit.h> + + typedef struct PRCallOnceType { + PRIntn initialized; + PRInt32 inProgress; + PRStatus status; + } PRCallOnceType; + + +Fields +~~~~~~ + +The structure has these fields: + +``initialized`` + If not zero, the initialization process has been completed. +``inProgress`` + If not zero, the initialization process is currently being executed. + Calling threads that observe this status block until inProgress is + zero. +``status`` + An indication of the outcome of the initialization process. + + +Description +----------- + +The client is responsible for initializing the :ref:`PRCallOnceType` +structure to all zeros. This initialization must be accomplished before +any threading issues exist. diff --git a/docs/nspr/reference/prclist.rst b/docs/nspr/reference/prclist.rst new file mode 100644 index 0000000000..05dfdd5255 --- /dev/null +++ b/docs/nspr/reference/prclist.rst @@ -0,0 +1,27 @@ +PRCList +======= + +A circular linked list. + + +Syntax +------ + +.. code:: + + #include <prclist.h> + + typedef struct PRCListStr PRCList; + + typedef struct PRCListStr { + PRCList *next; + PRCList *previous; + }; + + +Description +----------- + +PRClist defines a node in a circular linked list. It can be used as the +anchor of a list and can be embedded in data structures that are +maintained in a linked list. diff --git a/docs/nspr/reference/prcondvar.rst b/docs/nspr/reference/prcondvar.rst new file mode 100644 index 0000000000..6d40fe224d --- /dev/null +++ b/docs/nspr/reference/prcondvar.rst @@ -0,0 +1,20 @@ +PRCondVar +========= + +Structure for a condition variable. + + +Syntax +------ + +.. code:: + + #include <prcvar.h> + + typedef struct PRCondVar PRCondVar; + + +Description +----------- + +An NSPR condition variable is an opaque object identified by a pointer. diff --git a/docs/nspr/reference/prdescidentity.rst b/docs/nspr/reference/prdescidentity.rst new file mode 100644 index 0000000000..9f9ad2767f --- /dev/null +++ b/docs/nspr/reference/prdescidentity.rst @@ -0,0 +1,36 @@ +PRDescIdentity +============== + +The identity of a file descriptor's layer. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef PRUintn PRDescIdentity; + + +Description +----------- + +File descriptors may be layered. Each layer has it own identity. +Identities are allocated by the runtime and are to be associated (by the +layer implementor) with all file descriptors of that layer. It is then +possible to scan the chain of layers and find a layer that one +recognizes, then predict that it will implement a desired protocol. + +There are three well-known identities: + + - :ref:`PR_INVALID_IO_LAYER`, an invalid layer identity, for error return + - :ref:`PR_TOP_IO_LAYER`, the identity of the top of the stack + - :ref:`PR_NSPR_IO_LAYER`, the identity used by NSPR proper + +Layers are created by :ref:`PR_GetUniqueIdentity`. A string may be +associated with a layer when the layer is created. The string is copied +by the runtime, and :ref:`PR_GetNameForIdentity` returns a reference to +that copy. There is no way to delete a layer's identity after the layer +is created. diff --git a/docs/nspr/reference/prdir.rst b/docs/nspr/reference/prdir.rst new file mode 100644 index 0000000000..feabd3eafc --- /dev/null +++ b/docs/nspr/reference/prdir.rst @@ -0,0 +1,26 @@ +PRDir +===== + +Directory structure used with `Directory I/O +Functions <I_O_Functions#Directory_I.2FO_Functions>`__. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef struct PRDir PRDir; + + +Description +----------- + +The opaque structure :ref:`PRDir` represents an open directory in the file +system. The function :ref:`PR_OpenDir` opens a specified directory and +returns a pointer to a :ref:`PRDir` structure, which can be passed to +:ref:`PR_ReadDir` repeatedly to obtain successive entries (files or +subdirectories in the open directory). To close the directory, pass the +:ref:`PRDir` pointer to :ref:`PR_CloseDir`. diff --git a/docs/nspr/reference/prerrorcode.rst b/docs/nspr/reference/prerrorcode.rst new file mode 100644 index 0000000000..9207ab80f7 --- /dev/null +++ b/docs/nspr/reference/prerrorcode.rst @@ -0,0 +1,30 @@ +PRErrorCode +=========== + + +Type for error codes that can be retrieved with :ref:`PR_GetError`. You can +also set your own errors using :ref:`PR_SetError`. + + +Syntax +------ + +.. code:: + + #include <prerror.h> + + typedef PRInt32 PRErrorCode + + +Description +----------- + +The service NSPR offers in this area is the ability to associate a +thread-specific condition with an error number. The error number +namespace is not well managed. NSPR assumes error numbers starting at +-6000 (decimal) and progressing towards zero. At present less than 100 +error codes have been defined. If NSPR's error handling is adopted by +calling clients, then some sort of partitioning of the namespace will +have to be employed. NSPR does not attempt to address this issue. + +For NSPR errors, see `Error Codes <NSPR_Error_Handling#Error_Code>`__. diff --git a/docs/nspr/reference/prexplodedtime.rst b/docs/nspr/reference/prexplodedtime.rst new file mode 100644 index 0000000000..c970394709 --- /dev/null +++ b/docs/nspr/reference/prexplodedtime.rst @@ -0,0 +1,70 @@ +PRExplodedTime +============== + +A clock/calendar representation of times. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + typedef struct PRExplodedTime { + PRInt32 tm_usec; + PRInt32 tm_sec; + PRInt32 tm_min; + PRInt32 tm_hour; + PRInt32 tm_mday; + PRInt32 tm_month; + PRInt16 tm_year; + PRInt8 tm_wday; + PRInt16 tm_yday; + PRTimeParameters tm_params; + } PRExplodedTime; + + +Description +----------- + +The :ref:`PRExplodedTime` structure represents clock/calendar time. +:ref:`PRExplodedTime` has the familiar time components: year, month, day of +month, hour, minute, second. It also has a microsecond component, as +well as the day of week and the day of year. In addition, +:ref:`PRExplodedTime` includes a :ref:`PRTimeParameters` structure +representing the local time zone information, so that the time point is +non-ambiguously specified. + +The essential members of :ref:`PRExplodedTime` are: + + - :ref:`tm_year`: absolute year, AD (by "absolute," we mean if the year is + 2000, this field's value is 2000). + - :ref:`tm_month`: number of months past tm_year. The range is [0, 11]. 0 + is January and 11 is December. + - :ref:`tm_mday`: the day of month. The range is [1, 31]. Note that it + starts from 1 as opposed to 0. + - :ref:`tm_hour`: number of hours past tm_mday. The range is [0, 23]. + - :ref:`tm_min`: number of minutes past tm_hour. The range is [0, 59]. + - :ref:`tm_sec`: number of seconds past tm_min. The range is [0, 61]. The + values 60 and 61 are for accommodating up to two leap seconds. + - :ref:`tm_usec`: number of microseconds past tm_sec. The range is [0, + 999999]. + - :ref:`tm_params`: a `PRTimeParameters` structure representing the + local time zone information. + +The nonessential members of :ref:`PRExplodedTime` are: + + - :ref:`tm_wday`: day of week. The range is [0, 6]. 0 is Sunday, 1 is + Monday, and 6 is Saturday. + - :ref:`tm_yday`: day of year. The range is [0, 365]. 0 is the 1st of + January. + +On input to NSPR functions, only the essential members of +:ref:`PRExplodedTime` must be specified. The two nonessential members (day +of week and day of year) are ignored by NSPR functions as input. When an +NSPR function returns a :ref:`PRExplodedTime` object or sets a +:ref:`PRExplodedTime` object as output, all of the :ref:`PRExplodedTime` +members are set, including the nonessential members. You can also use +``PR_NormalizeTime()`` to calculate the values of the nonessential +members. diff --git a/docs/nspr/reference/prfiledesc.rst b/docs/nspr/reference/prfiledesc.rst new file mode 100644 index 0000000000..50df48f83f --- /dev/null +++ b/docs/nspr/reference/prfiledesc.rst @@ -0,0 +1,53 @@ +PRFileDesc +========== + +A file descriptor used to represent any open file, such as a normal +file, an end point of a pipe, or a socket (end point of network +communication). + + +Syntax +------ + +.. code:: + + #include <prio.h> + + struct PRFileDesc { + PRIOMethods *methods; + PRFilePrivate *secret; + PRFileDesc *lower, *higher; + void (*dtor)(PRFileDesc *fd); + PRDescIdentity identity; + }; + + typedef struct PRFileDesc PRFileDesc; + + +Parameters +~~~~~~~~~~ + +``methods`` + The I/O methods table. See :ref:`PRIOMethods`. +``secret`` + Layer-dependent implementation data. See :ref:`PRFilePrivate`. +``lower`` + Pointer to lower layer. +``higher`` + Pointer to higher layer. +``dtor`` + A destructor function for the layer. +``identity`` + Identity of this particular layer. See :ref:`PRDescIdentity`. + + +Description +----------- + +The fields of this structure are significant only if you are +implementing a layer on top of NSPR, such as SSL. Otherwise, you use +functions such as :ref:`PR_Open` and :ref:`PR_NewTCPSocket` to obtain a file +descriptor, which you should treat as an opaque structure. + +For more details about the use of :ref:`PRFileDesc` and related structures, +see `File Descriptor Types <I_O_Types#File_Descriptor_Types>`__. diff --git a/docs/nspr/reference/prfileinfo.rst b/docs/nspr/reference/prfileinfo.rst new file mode 100644 index 0000000000..2fe487ac2f --- /dev/null +++ b/docs/nspr/reference/prfileinfo.rst @@ -0,0 +1,49 @@ +PRFileInfo +========== + +File information structure used with :ref:`PR_GetFileInfo` and +:ref:`PR_GetOpenFileInfo`. + + +Syntax +~~~~~~ + +.. code:: + + #include <prio.h> + + struct PRFileInfo { + PRFileType type; + PRUint32 size; + PRTime creationTime; + PRTime modifyTime; + }; + + typedef struct PRFileInfo PRFileInfo; + + + + +Fields +~~~~~~ + +The structure has the following fields: + +``type`` + Type of file. See :ref:`PRFileType`. +``size`` + Size, in bytes, of file's contents. +``creationTime`` + Creation time per definition of :ref:`PRTime`. See + `prtime.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtime.h>`__. +``modifyTime`` + Last modification time per definition of :ref:`PRTime`. See + `prtime.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtime.h>`__. + + +Description +----------- + +The :ref:`PRFileInfo` structure provides information about a file, a +directory, or some other kind of file system object, as specified by the +``type`` field. diff --git a/docs/nspr/reference/prfileinfo64.rst b/docs/nspr/reference/prfileinfo64.rst new file mode 100644 index 0000000000..329a98bccc --- /dev/null +++ b/docs/nspr/reference/prfileinfo64.rst @@ -0,0 +1,47 @@ +PRFileInfo64 +============ + +File information structure used with :ref:`PR_GetFileInfo64` and +:ref:`PR_GetOpenFileInfo64`. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + struct PRFileInfo64 { + PRFileType type; + PRUint64 size; + PRTime creationTime; + PRTime modifyTime; + }; + + typedef struct PRFileInfo64 PRFileInfo64; + + +Fields +~~~~~~ + +The structure has the following fields: + +``type`` + Type of file. See :ref:`PRFileType`. +``size`` + 64-bit size, in bytes, of file's contents. +``creationTime`` + Creation time per definition of :ref:`PRTime`. See + `prtime.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtime.h>`__. +``modifyTime`` + Last modification time per definition of :ref:`PRTime`. See + `prtime.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtime.h>`__. + + +Description +----------- + +The :ref:`PRFileInfo64` structure provides information about a file, a +directory, or some other kind of file system object, as specified by the +``type`` field. diff --git a/docs/nspr/reference/prfilemap.rst b/docs/nspr/reference/prfilemap.rst new file mode 100644 index 0000000000..3002ee034d --- /dev/null +++ b/docs/nspr/reference/prfilemap.rst @@ -0,0 +1,27 @@ +PRFileMap +========= + +Type returned by :ref:`PR_CreateFileMap` and passed to :ref:`PR_MemMap` and +:ref:`PR_CloseFileMap`. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef struct PRFileMap PRFileMap; + + +Description +----------- + +The opaque structure :ref:`PRFileMap` represents a memory-mapped file +object. Before actually mapping a file to memory, you must create a +memory-mapped file object by calling :ref:`PR_CreateFileMap`, which returns +a pointer to :ref:`PRFileMap`. Then sections of the file can be mapped into +memory by passing the :ref:`PRFileMap` pointer to :ref:`PR_MemMap`. The +memory-mapped file object is closed by passing the :ref:`PRFileMap` pointer +to :ref:`PR_CloseFileMap`. diff --git a/docs/nspr/reference/prfileprivate.rst b/docs/nspr/reference/prfileprivate.rst new file mode 100644 index 0000000000..dc264d7d85 --- /dev/null +++ b/docs/nspr/reference/prfileprivate.rst @@ -0,0 +1,24 @@ +PRFilePrivate +============= + + +Layer-dependent implementation data. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef struct PRFilePrivate PRFilePrivate; + + +Description +----------- + +A layer implementor should collect all the private data of the layer in +the :ref:`PRFilePrivate` structure. Each layer has its own definition of +:ref:`PRFilePrivate`, which is hidden from other layers as well as from the +users of the layer. diff --git a/docs/nspr/reference/prfiletype.rst b/docs/nspr/reference/prfiletype.rst new file mode 100644 index 0000000000..2382f50cca --- /dev/null +++ b/docs/nspr/reference/prfiletype.rst @@ -0,0 +1,34 @@ +PRFileType +========== + + +Type for enumerators used in the type field of the :ref:`PRFileInfo` and +:ref:`PRFileInfo64` structures. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef enum PRFileType{ + PR_FILE_FILE = 1, + PR_FILE_DIRECTORY = 2, + PR_FILE_OTHER = 3 + } PRFileType; + + +Enumerators +~~~~~~~~~~~ + +The enumeration has the following enumerators: + +``PR_FILE_FILE`` + The information in the structure describes a file. +``PR_FILE_DIRECTORY`` + The information in the structure describes a directory. +``PR_FILE_OTHER`` + The information in the structure describes some other kind of file + system object. diff --git a/docs/nspr/reference/prfloat64.rst b/docs/nspr/reference/prfloat64.rst new file mode 100644 index 0000000000..704eabec96 --- /dev/null +++ b/docs/nspr/reference/prfloat64.rst @@ -0,0 +1,15 @@ + +PRFloat64 +========= + +The NSPR floating-point type is always 64 bits. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef double PRFloat64; diff --git a/docs/nspr/reference/prhostent.rst b/docs/nspr/reference/prhostent.rst new file mode 100644 index 0000000000..daf2d89d40 --- /dev/null +++ b/docs/nspr/reference/prhostent.rst @@ -0,0 +1,69 @@ +PRHostEnt +========= + +A structure that defines a list of network addresses. This structure is +output from :ref:`PR_GetHostByName` and :ref:`PR_GetHostByAddr` and passed to +:ref:`PR_EnumerateHostEnt`. Clients should avoid directly accessing any of +the structure's fields. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + typedef struct PRHostEnt { + char *h_name; + char **h_aliases; + #if defined(_WIN32) + PRInt16 h_addrtype; + PRInt16 h_length; + #else + PRInt32 h_addrtype; + PRInt32 h_length; + #endif + char **h_addr_list; + } PRHostEnt; + + +Fields +~~~~~~ + +The structure has the following fields: + +``h_name`` + Pointer to the official name of host. +``h_aliases`` + Pointer to a pointer to list of aliases. The list is terminated with + a ``NULL`` entry. +``h_addrtype`` + Host address type. For valid NSPR usage, this field must have a value + indicating either an IPv4 or an IPv6 address. +``h_length`` + Length of internal representation of the address in bytes. All of the + addresses in the list are of the same type and therefore of the same + length. +``h_addr_list`` + Pointer to a pointer to a list of addresses from name server (in + network byte order). The list is terminated with a ``NULL`` entry. + + +Description +----------- + +This structure is used by many of the network address functions. All +addresses are passed in host order and returned in network order +(suitable for use in system calls). + +Use the network address functions to manipulate the :ref:`PRHostEnt` +structure. To make the transition to IP version 6 easier, it's best to +treat :ref:`PRHostEnt` as an opaque structure. + +Note +---- + +``WINSOCK.H`` defines ``h_addrtype`` and ``h_length`` as a 16-bit field, +whereas other platforms treat it as a 32-bit field. The ``#ifdef`` in +the structure allows direct assignment of the :ref:`PRHostEnt` structure. diff --git a/docs/nspr/reference/print16.rst b/docs/nspr/reference/print16.rst new file mode 100644 index 0000000000..8701a0ea5d --- /dev/null +++ b/docs/nspr/reference/print16.rst @@ -0,0 +1,14 @@ +PRInt16 +======= + +Guaranteed to be a signed 16-bit integer on all platforms. + + +Syntax +------ + +:: + + #include <prtypes.h> + + typedefdefinition PRInt16; diff --git a/docs/nspr/reference/print32.rst b/docs/nspr/reference/print32.rst new file mode 100644 index 0000000000..8b179c6f37 --- /dev/null +++ b/docs/nspr/reference/print32.rst @@ -0,0 +1,22 @@ +PRInt32 +======= + +Guaranteed to be a signed 32-bit integer on all platforms. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedefdefinition PRInt32; + + +Description +----------- + +May be defined as an ``int`` or a ``long``, depending on the platform. +For syntax details for each platform, see +`prtypes.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtypes.h>`__. diff --git a/docs/nspr/reference/print64.rst b/docs/nspr/reference/print64.rst new file mode 100644 index 0000000000..3ef8c31d3f --- /dev/null +++ b/docs/nspr/reference/print64.rst @@ -0,0 +1,22 @@ +PRInt64 +======= + +Guaranteed to be a signed 64-bit integer on all platforms. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef definition PRInt64; + + +Description +----------- + +May be defined in several different ways, depending on the platform. For +syntax details for each platform, see +`prtypes.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtypes.h>`__. diff --git a/docs/nspr/reference/print8.rst b/docs/nspr/reference/print8.rst new file mode 100644 index 0000000000..6dd21a8efe --- /dev/null +++ b/docs/nspr/reference/print8.rst @@ -0,0 +1,14 @@ +PRInt8 +====== + +Guaranteed to be a signed 8-bit integer on all platforms. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef definition PRInt8; diff --git a/docs/nspr/reference/printervaltime.rst b/docs/nspr/reference/printervaltime.rst new file mode 100644 index 0000000000..9367d6ad7f --- /dev/null +++ b/docs/nspr/reference/printervaltime.rst @@ -0,0 +1,72 @@ +PRIntervalTime +============== + +A platform-dependent type that represents a monotonically increasing +integer--the NSPR runtime clock. + + +Syntax +------ + +.. code:: + + #include <prinrval.h> + + typedef PRUint32 PRIntervalTime; + + #define PR_INTERVAL_MIN 1000UL + #define PR_INTERVAL_MAX 100000UL + + #define PR_INTERVAL_NO_WAIT 0UL + #define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL + + +Description +----------- + +The units of :ref:`PRIntervalTime` are platform-dependent. They are chosen +to be appropriate for the host OS, yet provide sufficient resolution and +period to be useful to clients. + +The increasing interval value represented by :ref:`PRIntervalTime` wraps. +It should therefore never be used for intervals greater than +approximately 6 hours. Interval times are accurate regardless of host +processing requirements and are very cheap to acquire. + +The constants ``PR_INTERVAL_MIN`` and ``PR_INTERVAL_MAX`` define a range +in ticks per second. These constants bound both the period and the +resolution of a :ref:`PRIntervalTime` object. + +The reserved constants ``PR_INTERVAL_NO_WAIT`` and +``PR_INTERVAL_NO_TIMEOUT`` have special meaning for NSPR. They indicate +that the process should wait no time (return immediately) or wait +forever (never time out), respectively. + +.. _Important_Note: + +Important Note +~~~~~~~~~~~~~~ + +The counters used for interval times are allowed to overflow. Since the +sampling of the counter used to define an arbitrary epoch may have any +32-bit value, some care must be taken in the use of interval times. The +proper coding style to test the expiration of an interval is as follows: + +.. code:: + + if ((PRIntervalTime)(now - epoch) > interval) + <... interval has expired ...> + +As long as the interval and the elapsed time (now - epoch) do not exceed +half the namespace allowed by a :ref:`PRIntervalTime` (2\ :sup:`31`-1), the +expression shown above provides the expected result even if the signs of +now and epoch differ. + +The resolution of a :ref:`PRIntervalTime` object is defined by the API. +NSPR guarantees that there will be at least 1000 ticks per second and +not more than 100000. At the maximum resolution of 10000 ticks per +second, each tick represents 1/100000 of a second. At that rate, a +32-bit register will overflow in approximately 28 hours, making the +maximum useful interval approximately 6 hours. Waiting on events more +than half a day in the future must therefore be based on a calendar +time. diff --git a/docs/nspr/reference/printn.rst b/docs/nspr/reference/printn.rst new file mode 100644 index 0000000000..0d7a465da8 --- /dev/null +++ b/docs/nspr/reference/printn.rst @@ -0,0 +1,17 @@ +PRIntn +====== + +This type is one of the most appropriate for automatic variables. It is +guaranteed to be at least 16 bits, though various architectures may +define it to be wider (for example, 32 or even 64 bits). This types is +never valid for fields of a structure. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef int PRIntn; diff --git a/docs/nspr/reference/priomethods.rst b/docs/nspr/reference/priomethods.rst new file mode 100644 index 0000000000..8e50ae1781 --- /dev/null +++ b/docs/nspr/reference/priomethods.rst @@ -0,0 +1,132 @@ +PRIOMethods +=========== + +The table of I/O methods used in a file descriptor. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + struct PRIOMethods { + PRDescType file_type; + PRCloseFN close; + PRReadFN read; + PRWriteFN write; + PRAvailableFN available; + PRAvailable64FN available64; + PRFsyncFN fsync; + PRSeekFN seek; + PRSeek64FN seek64; + PRFileInfoFN fileInfo; + PRFileInfo64FN fileInfo64; + PRWritevFN writev; + PRConnectFN connect; + PRAcceptFN accept; + PRBindFN bind; + PRListenFN listen; + PRShutdownFN shutdown; + PRRecvFN recv; + PRSendFN send; + PRRecvfromFN recvfrom; + PRSendtoFN sendto; + PRPollFN poll; + PRAcceptreadFN acceptread; + PRTransmitfileFN transmitfile; + PRGetsocknameFN getsockname; + PRGetpeernameFN getpeername; + PRGetsockoptFN getsockopt; + PRSetsockoptFN setsockopt; + }; + + typedef struct PRIOMethods PRIOMethods; + + +Parameters +~~~~~~~~~~ + +``file_type`` + Type of file represented (tos). +``close`` + Close file and destroy descriptor. +``read`` + Read up to the specified number of bytes into buffer. +``write`` + Write specified number of bytes from buffer. +``available`` + Determine number of bytes available for reading. +``available64`` + Same as previous field, except 64-bit. +``fsync`` + Flush all in-memory buffers of file to permanent store. +``seek`` + Position the file pointer to the desired place. +``seek64`` + Same as previous field, except 64-bit. +``fileInfo`` + Get information about an open file. +``fileInfo64`` + Same as previous field, except 64-bit. +``writev`` + Write from a vector of buffers. +``connect`` + Connect to the specified network address. +``accept`` + Accept a connection from a network peer. +``bind`` + Associate a network address with the file descriptor. +``listen`` + Prepare to listen for network connections. +``shutdown`` + Shut down a network connection. +``recv`` + Receive up to the specified number of bytes. +``send`` + Send all the bytes specified. +``recvfrom`` + Receive up to the specified number of bytes and report network + source. +``sendto`` + Send bytes to specified network address. +``poll`` + Test the file descriptor to see if it is ready for I/O. +``acceptread`` + Accept and read from a new network file descriptor. +``transmitfile`` + Transmit an entire file to the specified socket. +``getsockname`` + Get network address associated with a file descriptor. +``getpeername`` + Get peer's network address. +``getsockopt`` + Get current setting of specified socket option. +``setsockopt`` + Set value of specified socket option. + + +Description +----------- + +You don't need to know the type declaration for each function listed in +the method table unless you are implementing a layer. For information +about each function, see the corresponding function description in this +document. For example, the ``write`` method in :ref:`PRIOMethods` +implements the :ref:`PR_Write` function. For type definition details, see +``prio.h``. + +The I/O methods table provides procedural access to the functions of the +file descriptor. It is the responsibility of a layer implementor to +provide suitable functions at every entry point (that is, for every +function in the I/O methods table). If a layer provides no +functionality, it should call the next lower (higher) function of the +same name (for example, the "close" method would return +``fd->lower->method->close(fd->lower)``). + +Not all functions in the methods table are implemented for all types of +files. For example, the seek method is implemented for normal files but +not for sockets. In cases where this partial implementation occurs, the +function returns an error indication with an error code of +``PR_INVALID_METHOD_ERROR``. diff --git a/docs/nspr/reference/pripv6addr.rst b/docs/nspr/reference/pripv6addr.rst new file mode 100644 index 0000000000..94250f5ad1 --- /dev/null +++ b/docs/nspr/reference/pripv6addr.rst @@ -0,0 +1,26 @@ +PRIPv6Addr +========== + +Type used in the ``ipv6.ip`` field of the :ref:`PRNetAddr` structure. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + #if defined(_PR_INET6) + typedef struct in6_addr PRIPv6Addr; + #endif /* defined(_PR_INET6) */ + + +Description +----------- + +PRIPv6Addr represents a 128-bit IPv6 address. It is equivalent to struct +``in6_addr`` in the Berkeley socket interface. :ref:`PRIPv6Addr` is always +manipulated as a byte array. Unlike the IPv4 address (a 4-byte unsigned +integer) or the port number (a 2-byte unsigned integer), it has no +network or host byte order. diff --git a/docs/nspr/reference/prjob.rst b/docs/nspr/reference/prjob.rst new file mode 100644 index 0000000000..7407f43cf1 --- /dev/null +++ b/docs/nspr/reference/prjob.rst @@ -0,0 +1,10 @@ +PRJob +===== + + +Syntax +------ + +:: + + #include <prtpool.h> diff --git a/docs/nspr/reference/prjobfn.rst b/docs/nspr/reference/prjobfn.rst new file mode 100644 index 0000000000..46e6bbc3f0 --- /dev/null +++ b/docs/nspr/reference/prjobfn.rst @@ -0,0 +1,12 @@ +PRJobFn +======= + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + typedef void (PR_CALLBACK *PRJobFn)(void *arg); diff --git a/docs/nspr/reference/prjobiodesc.rst b/docs/nspr/reference/prjobiodesc.rst new file mode 100644 index 0000000000..60d10a6dc2 --- /dev/null +++ b/docs/nspr/reference/prjobiodesc.rst @@ -0,0 +1,16 @@ +PRJobIoDesc +=========== + + +Syntax +------ + +.. code:: + + #include <prtpool.h> + + typedef struct PRJobIoDesc { + PRFileDesc *socket; + PRErrorCode error; + PRIntervalTime timeout; + } PRJobIoDesc; diff --git a/docs/nspr/reference/prlibrary.rst b/docs/nspr/reference/prlibrary.rst new file mode 100644 index 0000000000..d0c8ba1ad7 --- /dev/null +++ b/docs/nspr/reference/prlibrary.rst @@ -0,0 +1,22 @@ +PRLibrary +========= + +An opaque structure identifying a library. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + typedef struct PRLibrary PRLibrary; + + +Description +----------- + +A PRLibrary is an opaque structure. A reference to such a structure can +be returned by some of the functions in the runtime and serve to +identify a particular instance of a library. diff --git a/docs/nspr/reference/prlinger.rst b/docs/nspr/reference/prlinger.rst new file mode 100644 index 0000000000..9506dc0240 --- /dev/null +++ b/docs/nspr/reference/prlinger.rst @@ -0,0 +1,56 @@ +PRLinger +======== + +Structure used with the ``PR_SockOpt_Linger`` socket option to specify +the time interval (in :ref:`PRIntervalTime` units) to linger on closing a +socket if any data remain in the socket send buffer. + + +Syntax +~~~~~~ + +.. code:: + + #include <prio.h> + + typedef struct PRLinger { + PRBool polarity; + PRIntervalTime linger; + } PRLinger; + + +Fields +~~~~~~ + +The structure has the following fields: + +``polarity`` + Polarity of the option's setting: ``PR_FALSE`` means the option is + off, in which case the value of ``linger`` is ignored. ``PR_TRUE`` + means the option is on, and the value of ``linger`` will be used to + determine how long :ref:`PR_Close` waits before returning. +``linger`` + Time (in :ref:`PRIntervalTime` units) to linger before closing if any + data remain in the socket send buffer. + + +Description +~~~~~~~~~~~ + +By default, :ref:`PR_Close` returns immediately, but if there are any data +remaining in the socket send buffer, the system attempts to deliver the +data to the peer. The ``PR_SockOpt_Linger`` socket option, with a value +represented by a structure of type :ref:`PRLinger`, makes it possible to +change this default as follows: + +- If ``polarity`` is set to ``PR_FALSE``, :ref:`PR_Close` returns + immediately, but if there are any data remaining in the socket send + buffer, the runtime attempts to deliver the data to the peer. +- If ``polarity`` is set to ``PR_TRUE`` and ``linger`` is set to 0 + (``PR_INTERVAL_NO_WAIT``), the runtime aborts the connection when it + is closed and discards any data remaining in the socket send buffer. +- If ``polarity`` is set to ``PR_TRUE`` and ``linger`` is nonzero, the + runtime *lingers* when the socket is closed. That is, if any data + remains in the socket send buffer, :ref:`PR_Close` blocks until either + all the data is sent and acknowledged by the peer or the interval + specified by ``linger`` expires. diff --git a/docs/nspr/reference/prlock.rst b/docs/nspr/reference/prlock.rst new file mode 100644 index 0000000000..a7a736d340 --- /dev/null +++ b/docs/nspr/reference/prlock.rst @@ -0,0 +1,22 @@ +PRLock +====== + +A mutual exclusion lock. + + +Syntax +------ + +.. code:: + + #include <prlock.h> + + typedef struct PRLock PRLock; + + +Description +----------- + +NSPR represents a lock as an opaque entity to clients of the functions +described in `"Locks" <en/NSPR_API_Reference/Locks>`__. Functions that +operate on locks do not have timeouts and are not interruptible. diff --git a/docs/nspr/reference/prlogmoduleinfo.rst b/docs/nspr/reference/prlogmoduleinfo.rst new file mode 100644 index 0000000000..ea616e435a --- /dev/null +++ b/docs/nspr/reference/prlogmoduleinfo.rst @@ -0,0 +1,23 @@ +PR_NewLogModule +=============== + + +The ``PRLogModuleInfo`` structure controls logging from within your +application. To log your program's activity, create a +``PRLogModuleInfo`` structure using +`:ref:`PR_NewLogModule` <http://www-archive.mozilla.org/projects/nspr/reference/html/prlog.html#25372>`__ +. + + +Syntax +------ + +:: + + #include <prlog.h> + + typedef struct PRLogModuleInfo { + const char *name; + PRLogModuleLevel level; + struct PRLogModuleInfo *next; + } PRLogModuleInfo; diff --git a/docs/nspr/reference/prlogmodulelevel.rst b/docs/nspr/reference/prlogmodulelevel.rst new file mode 100644 index 0000000000..d9ed3f78ca --- /dev/null +++ b/docs/nspr/reference/prlogmodulelevel.rst @@ -0,0 +1,26 @@ +PRLogModuleLevel +================ + +The enumerated type :ref:`PRLogModuleLevel` defines levels of logging +available to application programs. + + +Syntax +------ + +:: + + #include <prlog.h> + + typedef enum PRLogModuleLevel { + PR_LOG_NONE = 0, + PR_LOG_ALWAYS = 1, + PR_LOG_ERROR = 2, + PR_LOG_WARNING = 3, + PR_LOG_DEBUG = 4, + + PR_LOG_NOTICE = PR_LOG_DEBUG, + PR_LOG_WARN = PR_LOG_WARNING, + PR_LOG_MIN = PR_LOG_DEBUG, + PR_LOG_MAX = PR_LOG_DEBUG + } PRLogModuleLevel; diff --git a/docs/nspr/reference/prmcastrequest.rst b/docs/nspr/reference/prmcastrequest.rst new file mode 100644 index 0000000000..9c7c63ecef --- /dev/null +++ b/docs/nspr/reference/prmcastrequest.rst @@ -0,0 +1,40 @@ +PRMcastRequest +============== + +Structure used to specify values for the ``PR_SockOpt_AddMember`` and +``PR_SockOpt_DropMember`` socket options that define a request to join +or leave a multicast group. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + struct PRMcastRequest { + PRNetAddr mcaddr; + PRNetAddr ifaddr; + }; + + typedef struct PRMcastRequest PRMcastRequest; + + +Fields +~~~~~~ + +The structure has the following fields: + +``mcaddr`` + IP multicast address of group. +``ifaddr`` + Local IP address of interface. + + +Description +----------- + +The ``mcaddr`` and ``ifaddr`` fields are of the type :ref:`PRNetAddr`, but +their ``port`` fields are ignored. Only the IP address (``inet.ip``) +fields are used. diff --git a/docs/nspr/reference/prmonitor.rst b/docs/nspr/reference/prmonitor.rst new file mode 100644 index 0000000000..5a420f9452 --- /dev/null +++ b/docs/nspr/reference/prmonitor.rst @@ -0,0 +1,15 @@ +PRMonitor +========= + +An opaque structure managed entirely by the client. Clients create them +when needed and must destroy them when no longer needed. + + +Syntax +------ + +.. code:: + + #include <prmon.h> + + typedef struct PRMonitor PRMonitor; diff --git a/docs/nspr/reference/prnetaddr.rst b/docs/nspr/reference/prnetaddr.rst new file mode 100644 index 0000000000..71fe1a65d4 --- /dev/null +++ b/docs/nspr/reference/prnetaddr.rst @@ -0,0 +1,85 @@ +PRNetAddr +========= + +Type used with `Socket Manipulation +Functions <Socket_Manipulation_Functions>`__ to specify a network +address. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + union PRNetAddr { + struct { + PRUint16 family; + char data[14]; + } raw; + struct { + PRUint16 family; + PRUint16 port; + PRUint32 ip; + char pad[8]; + } inet; + #if defined(_PR_INET6) + struct { + PRUint16 family; + PRUint16 port; + PRUint32 flowinfo; + PRIPv6Addr ip; + } ipv6; + #endif /* defined(_PR_INET6) */ + }; + + typedef union PRNetAddr PRNetAddr; + + +Fields +~~~~~~ + +The structure has the following fields: + +``family`` + Address family: ``PR_AF_INET|PR_AF_INET6`` for ``raw.family``, + ``PR_AF_INET`` for ``inet.family``, ``PR_AF_INET6`` for + ``ipv6.family``. +``data`` + Raw address data. +``port`` + Port number of TCP or UDP, in network byte order. +``ip`` + The actual 32 (for ``inet.ip``) or 128 (for ``ipv6.ip``) bits of IP + address. The ``inet.ip`` field is in network byte order. +``pad`` + Unused. +``flowinfo`` + Routing information. + + +Description +----------- + +The union :ref:`PRNetAddr` represents a network address. NSPR supports only +the Internet address family. By default, NSPR is built to support only +IPv4, but it's possible to build the NSPR library to support both IPv4 +and IPv6. Therefore, the ``family`` field can be ``PR_AF_INET`` only for +default NSPR, and can also be ``PR_AF_INET6`` if the binary supports +``IPv6``. + +:ref:`PRNetAddr` is binary-compatible with the socket address structures in +the familiar Berkeley socket interface, although this fact should not be +relied upon. The raw member of the union is equivalent to +``struct sockaddr``, the ``inet`` member is equivalent to +``struct sockaddr_in``, and if the binary is built with ``IPv6`` +support, the ``ipv6`` member is equivalent to ``struct sockaddr_in6``. +(Note that :ref:`PRNetAddr` does not have the ``length`` field that is +present in ``struct sockaddr_in`` on some Unix platforms.) + +The macros ``PR_AF_INET``, ``PR_AF_INET6``, ``PR_INADDR_ANY``, +``PR_INADDR_LOOPBACK`` are defined if ``prio.h`` is included. +``PR_INADDR_ANY`` and ``PR_INADDR_LOOPBACK`` are special ``IPv4`` +addresses in host byte order, so they must be converted to network byte +order before being assigned to the ``inet.ip`` field. diff --git a/docs/nspr/reference/process_initialization.rst b/docs/nspr/reference/process_initialization.rst new file mode 100644 index 0000000000..c5b0fd1763 --- /dev/null +++ b/docs/nspr/reference/process_initialization.rst @@ -0,0 +1,63 @@ +Process Initialization +====================== + +This chapter describes the NSPR API for versioning, process +initialization, and shutdown of NSPR. + +- `Identity and Versioning <#Identity_and_Versioning>`__ +- `Initialization and Cleanup <#Initialization_and_Cleanup>`__ +- `Module Initialization <#Module_Initialization>`__ + +.. _Identity_and_Versioning: + +Identity and Versioning +----------------------- + +.. _Name_and_Version_Constants: + +Name and Version Constants +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_NAME` + - :ref:`PR_VERSION` + - :ref:`PR_VersionCheck` + +.. _Initialization_and_Cleanup: + +Initialization and Cleanup +-------------------------- + +NSPR detects whether the library has been initialized and performs +implicit initialization if it hasn't. Implicit initialization should +suffice unless a program has specific sequencing requirements or needs +to characterize the primordial thread. Explicit initialization is rarely +necessary. + +Implicit initialization assumes that the initiator is the primordial +thread and that the thread is a user thread of normal priority. + + - :ref:`PR_Init` + - :ref:`PR_Initialize` + - :ref:`PR_Initialized` + - :ref:`PR_Cleanup` + - :ref:`PR_DisableClockInterrupts` + - :ref:`PR_BlockClockInterrupts` + - :ref:`PR_UnblockClockInterrupts` + - :ref:`PR_SetConcurrency` + - :ref:`PR_ProcessExit` + - :ref:`PR_Abort` + +.. _Module_Initialization: + +Module Initialization +~~~~~~~~~~~~~~~~~~~~~ + +Initialization can be tricky in a threaded environment, especially +initialization that must happen exactly once. :ref:`PR_CallOnce` ensures +that such initialization code is called only once. This facility is +recommended in situations where complicated global initialization is +required. + + - :ref:`PRCallOnceType` + - :ref:`PRCallOnceFN` + - :ref:`PR_CallOnce` diff --git a/docs/nspr/reference/process_management_and_interprocess_communication.rst b/docs/nspr/reference/process_management_and_interprocess_communication.rst new file mode 100644 index 0000000000..c508c7362c --- /dev/null +++ b/docs/nspr/reference/process_management_and_interprocess_communication.rst @@ -0,0 +1,64 @@ +Process Management And Interprocess Communication +================================================= + +This chapter describes the NSPR routines that deal with processes. A +process is an instance of a program. NSPR provides routines to create a +new process and to wait for the termination of another process. + +NSPR does not provide an equivalent of the Unix ``fork()``. The +newly-created process executes its program from the beginning. A new +process can inherit specified file descriptors from its parent, and the +parent can redirect the standard I/O streams of the child process to +specified file descriptors. + +Note that the functions described in this chapter are not available for +MacOS or Win16 operating systems. + +.. _Process_Management_Types_and_Constants: + +Process Management Types and Constants +-------------------------------------- + +The types defined for process management are: + + - :ref:`PRProcess` + - :ref:`PRProcessAttr` + +.. _Process_Management_Functions: + +Process Management Functions +---------------------------- + +The process manipulation function fall into these categories: + +- `Setting the Attributes of a New + Process <#Setting_the_Attributes_of_a_New_Process>`__ +- `Creating and Managing + Processes <#Creating_and_Managing_Processes>`__ + +.. _Setting_the_Attributes_of_a_New_Process: + +Setting the Attributes of a New Process +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The functions that create and manipulate attribute sets of new processes +are: + + - :ref:`PR_NewProcessAttr` + - :ref:`PR_ResetProcessAttr` + - :ref:`PR_DestroyProcessAttr` + - :ref:`PR_ProcessAttrSetStdioRedirect` + - :ref:`PR_ProcessAttrSetCurrentDirectory` + - :ref:`PR_ProcessAttrSetInheritableFD` + +.. _Creating_and_Managing_Processes: + +Creating and Managing Processes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The functions that create and manage processes are: + + - :ref:`PR_CreateProcess` + - :ref:`PR_DetachProcess` + - :ref:`PR_WaitProcess` + - :ref:`PR_KillProcess` diff --git a/docs/nspr/reference/prpackedbool.rst b/docs/nspr/reference/prpackedbool.rst new file mode 100644 index 0000000000..c32888de84 --- /dev/null +++ b/docs/nspr/reference/prpackedbool.rst @@ -0,0 +1,20 @@ +PRPackedBool +============ + +Packed Boolean value. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef PRUint8 PRPackedBool; + + +Description +----------- + +Use :ref:`PRPackedBool` within structures where bit fields are not desirable but minimum and consistent overhead matters. diff --git a/docs/nspr/reference/prprimordialfn.rst b/docs/nspr/reference/prprimordialfn.rst new file mode 100644 index 0000000000..5bb4266ff1 --- /dev/null +++ b/docs/nspr/reference/prprimordialfn.rst @@ -0,0 +1,19 @@ +PRPrimordialFn +============== + +The type for the root function used by :ref:`PR_Initialize` is specified as +follows: + + +Syntax +------ + +.. code:: + + typedef PRIntn (PR_CALLBACK *PRPrimordialFn)(PRIntn argc, char **argv); + + +See Also +-------- + + - :ref:`PR_Initialize` diff --git a/docs/nspr/reference/prprocess.rst b/docs/nspr/reference/prprocess.rst new file mode 100644 index 0000000000..b17db0b3da --- /dev/null +++ b/docs/nspr/reference/prprocess.rst @@ -0,0 +1,20 @@ +PRProcess +========= + +Represents a process. + + +Syntax +------ + +:: + + #include <prproces.h> + + typedef struct PRProcess PRProcess; + + +Description +----------- + +A pointer to the opaque :ref:`PRProcess` structure identifies a process. diff --git a/docs/nspr/reference/prprocessattr.rst b/docs/nspr/reference/prprocessattr.rst new file mode 100644 index 0000000000..65e48e1201 --- /dev/null +++ b/docs/nspr/reference/prprocessattr.rst @@ -0,0 +1,23 @@ +PRProcessAttr +============= + +Represents the attributes of a new process. + + +Syntax +------ + +:: + + #include <prproces.h> + + typedef struct PRProcessAttr PRProcessAttr; + + +Description +----------- + +This opaque structure describes the attributes of a process to be +created. Pass a pointer to a :ref:`PRProcessAttr` into ``PR_CreateProcess`` +when you create a new process, specifying information such as standard +input/output redirection and file descriptor inheritance. diff --git a/docs/nspr/reference/prprotoent.rst b/docs/nspr/reference/prprotoent.rst new file mode 100644 index 0000000000..6d913a1cc8 --- /dev/null +++ b/docs/nspr/reference/prprotoent.rst @@ -0,0 +1,37 @@ +PRProtoEnt +========== + +Protocol entry returned by :ref:`PR_GetProtoByName` and +:ref:`PR_GetProtoByNumber`. + + +Syntax +------ + +.. code:: + + #include <prnetdb.h> + + typedef struct PRProtoEnt { + char *p_name; + char **p_aliases; + #if defined(_WIN32) + PRInt16 p_num; + #else + PRInt32 p_num; + #endif + } PRProtoEnt; + + +Fields +~~~~~~ + +The structure has the following fields: + +``p_name`` + Pointer to official protocol name. +``p_aliases`` + Pointer to a pointer to a list of aliases. The list is terminated + with a ``NULL`` entry. +``p_num`` + Protocol number. diff --git a/docs/nspr/reference/prptrdiff.rst b/docs/nspr/reference/prptrdiff.rst new file mode 100644 index 0000000000..c069649215 --- /dev/null +++ b/docs/nspr/reference/prptrdiff.rst @@ -0,0 +1,14 @@ +PRPtrdiff +========= + +Signed pointer difference type. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef ptrdiff_t PRPtrdiff; diff --git a/docs/nspr/reference/prseekwhence.rst b/docs/nspr/reference/prseekwhence.rst new file mode 100644 index 0000000000..4d6ae71371 --- /dev/null +++ b/docs/nspr/reference/prseekwhence.rst @@ -0,0 +1,35 @@ +PRSeekWhence +============ + +Specifies how to interpret the ``offset`` parameter in setting the file +pointer associated with the ``fd`` parameter for the :ref:`PR_Seek` and +:ref:`PR_Seek64` functions. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef PRSeekWhence { + PR_SEEK_SET = 0, + PR_SEEK_CUR = 1, + PR_SEEK_END = 2 + } PRSeekWhence; + + +Enumerators +~~~~~~~~~~~ + +The enumeration has the following enumerators: + +``PR_SEEK_SET`` + Sets the file pointer to the value of the ``offset`` parameter. +``PR_SEEK_CUR`` + Sets the file pointer to its current location plus the value of the + ``offset`` parameter. +``PR_SEEK_END`` + Sets the file pointer to the size of the file plus the value of the + ``offset`` parameter. diff --git a/docs/nspr/reference/prsize.rst b/docs/nspr/reference/prsize.rst new file mode 100644 index 0000000000..8d0810574e --- /dev/null +++ b/docs/nspr/reference/prsize.rst @@ -0,0 +1,15 @@ +PRSize +====== + +A type for representing the size of an object (not the size of a +pointer). This is the same as the corresponding type in ``libc``. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef size_t PRSize; diff --git a/docs/nspr/reference/prsocketoptiondata.rst b/docs/nspr/reference/prsocketoptiondata.rst new file mode 100644 index 0000000000..442d1559e9 --- /dev/null +++ b/docs/nspr/reference/prsocketoptiondata.rst @@ -0,0 +1,83 @@ +PRSocketOptionData +================== + +Type for structure used with :ref:`PR_GetSocketOption` and +:ref:`PR_SetSocketOption` to specify options for file descriptors that +represent sockets. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef struct PRSocketOptionData + { + PRSockOption option; + union + { + PRUintn ip_ttl; + PRUintn mcast_ttl; + PRUintn tos; + PRBool non_blocking; + PRBool reuse_addr; + PRBool keep_alive; + PRBool mcast_loopback; + PRBool no_delay; + PRSize max_segment; + PRSize recv_buffer_size; + PRSize send_buffer_size; + PRLinger linger; + PRMcastRequest add_member; + PRMcastRequest drop_member; + PRNetAddr mcast_if; + } value; + } PRSocketOptionData; + + +Fields +~~~~~~ + +The structure has the following fields: + +``ip_ttl`` + IP time-to-live. +``mcast_ttl`` + IP multicast time-to-live. +``tos`` + IP type-of-service and precedence. +``non_blocking`` + Nonblocking (network) I/O. +``reuse_addr`` + Allow local address reuse. +``keep_alive`` + Periodically test whether connection is still alive. +``mcast_loopback`` + IP multicast loopback. +``no_delay`` + Disable Nagle algorithm. Don't delay send to coalesce packets. +``max_segment`` + TCP maximum segment size. +``recv_buffer_size`` + Receive buffer size. +``send_buffer_size`` + Send buffer size. +``linger`` + Time to linger on close if data are present in socket send buffer. +``add_member`` + Join an IP multicast group. +``drop_member`` + Leave an IP multicast group. +``mcast_if`` + IP multicast interface address. + + +Description +~~~~~~~~~~~ + +:ref:`PRSocketOptionData` is a name-value pair for a socket option. The +``option`` field (of enumeration type :ref:`PRSockOption`) specifies the +name of the socket option, and the ``value`` field (a union of all +possible values) specifies the value of the option. diff --git a/docs/nspr/reference/prsockoption.rst b/docs/nspr/reference/prsockoption.rst new file mode 100644 index 0000000000..daaa20cb21 --- /dev/null +++ b/docs/nspr/reference/prsockoption.rst @@ -0,0 +1,79 @@ +PRSockOption +============ + +Enumeration type used in the ``option`` field of :ref:`PRSocketOptionData` +to form the name portion of a name-value pair. + + +Syntax +------ + +.. code:: + + #include <prio.h> + + typedef enum PRSockOption { + PR_SockOpt_Nonblocking, + PR_SockOpt_Linger, + PR_SockOpt_Reuseaddr, + PR_SockOpt_Keepalive, + PR_SockOpt_RecvBufferSize, + PR_SockOpt_SendBufferSize, + PR_SockOpt_IpTimeToLive, + PR_SockOpt_IpTypeOfService, + PR_SockOpt_AddMember, + PR_SockOpt_DropMember, + PR_SockOpt_McastInterface, + PR_SockOpt_McastTimeToLive, + PR_SockOpt_McastLoopback, + PR_SockOpt_NoDelay, + PR_SockOpt_MaxSegment, + PR_SockOpt_Last + } PRSockOption; + + +Enumerators +~~~~~~~~~~~ + +The enumeration has the following enumerators: + +``PR_SockOpt_Nonblocking`` + Nonblocking I/O. +``PR_SockOpt_Linger`` + Time to linger on close if data is present in the socket send buffer. +``PR_SockOpt_Reuseaddr`` + Allow local address reuse. +``PR_SockOpt_Keepalive`` + Periodically test whether connection is still alive. +``PR_SockOpt_RecvBufferSize`` + Receive buffer size. +``PR_SockOpt_SendBufferSize`` + Send buffer size. +``PR_SockOpt_IpTimeToLive`` + IP time-to-live. +``PR_SockOpt_IpTypeOfService`` + IP type-of-service and precedence. +``PR_SockOpt_AddMember`` + Join an IP multicast group. +``PR_SockOpt_DropMember`` + Leave an IP multicast group. +``PR_SockOpt_McastInterface`` + IP multicast interface address. +``PR_SockOpt_McastTimeToLive`` + IP multicast time-to-live. +``PR_SockOpt_McastLoopback`` + IP multicast loopback. +``PR_SockOpt_NoDelay`` + Disable Nagle algorithm. Don't delay send to coalesce packets. +``PR_SockOpt_MaxSegment`` + Maximum segment size. +``PR_SockOpt_Last`` + Always one greater than the maximum valid socket option numerator. + + +Description +----------- + +The :ref:`PRSockOption` enumeration consists of all the socket options +supported by NSPR. The ``option`` field of :ref:`PRSocketOptionData` should +be set to an enumerator of type :ref:`PRSockOption`. diff --git a/docs/nspr/reference/prstaticlinktable.rst b/docs/nspr/reference/prstaticlinktable.rst new file mode 100644 index 0000000000..ce76ab10a3 --- /dev/null +++ b/docs/nspr/reference/prstaticlinktable.rst @@ -0,0 +1,22 @@ +PRStaticLinkTable +================= + +A static link table entry can be created by a client of the runtime so +that other clients can access static or dynamic libraries transparently. +The basic function on a dynamic library is to acquire a pointer to a +function that the library exports. If, during initialization, such +entries are manually created, then future attempts to link to the +symbols can be treated in a consistent fashion. + + +Syntax +------ + +.. code:: + + #include <prlink.h> + + typedef struct PRStaticLinkTable { + const char *name; + void (*fp)(); + } PRStaticLinkTable; diff --git a/docs/nspr/reference/prstatus.rst b/docs/nspr/reference/prstatus.rst new file mode 100644 index 0000000000..15106b276b --- /dev/null +++ b/docs/nspr/reference/prstatus.rst @@ -0,0 +1,14 @@ +PRStatus +======== + +Type for status code returned by some functions. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; diff --git a/docs/nspr/reference/prthread.rst b/docs/nspr/reference/prthread.rst new file mode 100644 index 0000000000..7f479735f4 --- /dev/null +++ b/docs/nspr/reference/prthread.rst @@ -0,0 +1,26 @@ +PRThread +======== + +An NSPR thread. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef struct PRThread PRThread; + + +Description +~~~~~~~~~~~ + +In NSPR, a thread is represented by a pointer to an opaque structure of +type :ref:`PRThread`. This pointer is a required parameter for most of the +functions that operate on threads. + +A ``PRThread*`` is the successful result of creating a new thread. The +identifier remains valid until it returns from its root function and, if +the thread was created joinable, is joined. diff --git a/docs/nspr/reference/prthreadpool.rst b/docs/nspr/reference/prthreadpool.rst new file mode 100644 index 0000000000..3659f189c7 --- /dev/null +++ b/docs/nspr/reference/prthreadpool.rst @@ -0,0 +1,10 @@ +PRThreadPool +============ + + +Syntax +------ + +.. code:: + + #include <prtpool.h> diff --git a/docs/nspr/reference/prthreadpriority.rst b/docs/nspr/reference/prthreadpriority.rst new file mode 100644 index 0000000000..97c5c358da --- /dev/null +++ b/docs/nspr/reference/prthreadpriority.rst @@ -0,0 +1,62 @@ +PRThreadPriority +================ + +A thread's priority setting. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef enum PRThreadPriority + { + PR_PRIORITY_FIRST = 0, + PR_PRIORITY_LOW = 0, + PR_PRIORITY_NORMAL = 1, + PR_PRIORITY_HIGH = 2, + PR_PRIORITY_URGENT = 3, + PR_PRIORITY_LAST = 3 + } PRThreadPriority; + + +Enumerators +~~~~~~~~~~~ + +``PR_PRIORITY_FIRST`` + Placeholder. +``PR_PRIORITY_LOW`` + The lowest possible priority. This priority is appropriate for + threads that are expected to perform intensive computation. +``PR_PRIORITY_NORMAL`` + The most commonly expected priority. +``PR_PRIORITY_HIGH`` + Slightly higher priority than ``PR_PRIORITY_NORMAL``. This priority + is for threads performing work of high urgency but short duration. +``PR_PRIORITY_URGENT`` + Highest priority. Only one thread at a time typically has this + priority. +``PR_PRIORITY_LAST`` + Placeholder + + +Description +----------- + +In general, an NSPR thread of higher priority has a statistically better +chance of running relative to threads of lower priority. However, +because of the multiple strategies NSPR uses to implement threading on +various host platforms, NSPR priorities are not precisely defined. At +best they are intended to specify a preference in the amount of CPU time +that a higher-priority thread might expect relative to a lower-priority +thread. This preference is still subject to resource availability and +must not be used in place of proper synchronization. + + +See Also +-------- + +`Setting Thread +Priorities <Introduction_to_NSPR#Setting_Thread_Priorities>`__. diff --git a/docs/nspr/reference/prthreadprivatedtor.rst b/docs/nspr/reference/prthreadprivatedtor.rst new file mode 100644 index 0000000000..6a9339d07d --- /dev/null +++ b/docs/nspr/reference/prthreadprivatedtor.rst @@ -0,0 +1,24 @@ +PRThreadPrivateDTOR +=================== + +The destructor function passed to PR_NewThreadPrivateIndex that is +associated with the resulting thread private index. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv); + + +Description +~~~~~~~~~~~ + +Until the data associated with an index is actually set with a call to +:ref:`PR_SetThreadPrivate`, the value of the data is ``NULL``. If the data +associated with the index is not ``NULL``, NSPR passes a reference to +the data to the destructor function when the thread terminates. diff --git a/docs/nspr/reference/prthreadscope.rst b/docs/nspr/reference/prthreadscope.rst new file mode 100644 index 0000000000..c468704295 --- /dev/null +++ b/docs/nspr/reference/prthreadscope.rst @@ -0,0 +1,56 @@ +PRThreadScope +============= + +The scope of an NSPR thread, specified as a parameter to +:ref:`PR_CreateThread` or returned by :ref:`PR_GetThreadScope`. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef enum PRThreadScope { + PR_LOCAL_THREAD, + PR_GLOBAL_THREAD + PR_GLOBAL_BOUND_THREAD + } PRThreadScope; + + +Enumerators +~~~~~~~~~~~ + +``PR_LOCAL_THREAD`` + A local thread, scheduled locally by NSPR within the process. +``PR_GLOBAL_THREAD`` + A global thread, scheduled by the host OS. +``PR_GLOBAL_BOUND_THREAD`` + A global bound (kernel) thread, scheduled by the host OS + + +Description +----------- + +An enumerator of type :ref:`PRThreadScope` specifies how a thread is +scheduled: either locally by NSPR within the process (a local thread) or +globally by the host (a global thread). + +Global threads are scheduled by the host OS and compete with all other +threads on the host OS for resources. They are subject to fairly +sophisticated scheduling techniques. + +Local threads are scheduled by NSPR within the process. The process is +assumed to be globally scheduled, but NSPR can manipulate local threads +without system intervention. In most cases, this leads to a significant +performance benefit. + +However, on systems that require NSPR to make a distinction between +global and local threads, global threads are invariably required to do +any form of I/O. If a thread is likely to do a lot of I/O, making it a +global thread early is probably warranted. + +On systems that don't make a distinction between local and global +threads, NSPR silently ignores the scheduling request. To find the scope +of the thread, call :ref:`PR_GetThreadScope`. diff --git a/docs/nspr/reference/prthreadstack.rst b/docs/nspr/reference/prthreadstack.rst new file mode 100644 index 0000000000..374ac3ac07 --- /dev/null +++ b/docs/nspr/reference/prthreadstack.rst @@ -0,0 +1,31 @@ +PRThreadStack +============= + +.. container:: blockIndicator obsolete obsoleteHeader + + | **Obsolete** + | This feature is obsolete. Although it may still work in some + browsers, its use is discouraged since it could be removed at any + time. Try to avoid using it. + +The opaque :ref:`PRThreadStack` structure is only used in the third +argument "``PRThreadStack *stack``" to the :ref:`PR_AttachThread` function. +The '``stack``' argument is now obsolete and ignored by +:ref:`PR_AttachThread`. You should pass ``NULL`` as the 'stack' argument to +:ref:`PR_AttachThread`. + +.. _Definition: + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef struct PRThreadStack PRThreadStack; + +.. _Definition_2: + + +- diff --git a/docs/nspr/reference/prthreadstate.rst b/docs/nspr/reference/prthreadstate.rst new file mode 100644 index 0000000000..7285779f39 --- /dev/null +++ b/docs/nspr/reference/prthreadstate.rst @@ -0,0 +1,54 @@ +PRThreadState +============= + +A thread's thread state is either joinable or unjoinable. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef enum PRThreadState { + PR_JOINABLE_THREAD, + PR_UNJOINABLE_THREAD + } PRThreadState; + + +Enumerators +~~~~~~~~~~~ + +``PR_UNJOINABLE_THREAD`` + Thread termination happens implicitly when the thread returns from + the root function. The time of release of the resources assigned to + the thread cannot be determined in advance. Threads created with a + ``PR_UNJOINABLE_THREAD`` state cannot be used as arguments to + :ref:`PR_JoinThread`. +``PR_JOINABLE_THREAD`` + Joinable thread references remain valid after they have returned from + their root function until :ref:`PR_JoinThread` is called. This approach + facilitates management of the process' critical resources. + + +Description +----------- + +A thread is a critical resource and must be managed. + +The lifetime of a thread extends from the time it is created to the time +it returns from its root function. What happens when it returns from its +root function depends on the thread state passed to :ref:`PR_CreateThread` +when the thread was created. + +If a thread is created as a joinable thread, it continues to exist after +returning from its root function until another thread joins it. The join +process permits strict synchronization of thread termination and +therefore promotes effective resource management. + +If a thread is created as an unjoinable (also called detached) thread, +it terminates and cleans up after itself after returning from its root +function. This results in some ambiguity after the thread's root +function has returned and before the thread has finished terminating +itself. diff --git a/docs/nspr/reference/prthreadtype.rst b/docs/nspr/reference/prthreadtype.rst new file mode 100644 index 0000000000..4934af7a2f --- /dev/null +++ b/docs/nspr/reference/prthreadtype.rst @@ -0,0 +1,40 @@ +PRThreadType +============ + +The type of an NSPR thread, specified as a parameter to +:ref:`PR_CreateThread`. + + +Syntax +------ + +.. code:: + + #include <prthread.h> + + typedef enum PRThreadType { + PR_USER_THREAD, + PR_SYSTEM_THREAD + } PRThreadType; + + +Enumerators +~~~~~~~~~~~ + +``PR_USER_THREAD`` + :ref:`PR_Cleanup` blocks until the last thread of type + ``PR_USER_THREAD`` terminates. +``PR_SYSTEM_THREAD`` + NSPR ignores threads of type ``PR_SYSTEM_THREAD`` when determining + when a call to :ref:`PR_Cleanup` should return. + + +Description +----------- + +Threads can be either user threads or system threads. NSPR allows the +client to synchronize the termination of all user threads and ignores +those created as system threads. This arrangement implies that a system +thread should not have volatile data that needs to be safely stored +away. The applicability of system threads is somewhat dubious; +therefore, they should be used with caution. diff --git a/docs/nspr/reference/prtime.rst b/docs/nspr/reference/prtime.rst new file mode 100644 index 0000000000..8498e942ff --- /dev/null +++ b/docs/nspr/reference/prtime.rst @@ -0,0 +1,33 @@ +PRTime +====== + +A representation of absolute times. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + typedef PRInt64 PRTime; + + +Description +----------- + +This type is a 64-bit integer representing the number of microseconds +since the NSPR epoch, midnight (00:00:00) 1 January 1970 Coordinated +Universal Time (UTC). A time after the epoch has a positive value, and a +time before the epoch has a negative value. + +In NSPR, we use the more familiar term Greenwich Mean Time (GMT) in +place of UTC. Although UTC and GMT are not exactly the same in their +precise definitions, they can generally be treated as if they were. + +.. note:: + + **Note:** Keep in mind that while :ref:`PRTime` stores times in + microseconds since epoch, JavaScript date objects store times in + milliseconds since epoch. diff --git a/docs/nspr/reference/prtimeparameters.rst b/docs/nspr/reference/prtimeparameters.rst new file mode 100644 index 0000000000..4ddd01c7cd --- /dev/null +++ b/docs/nspr/reference/prtimeparameters.rst @@ -0,0 +1,54 @@ +PRTimeParameters +================ + +A representation of time zone information. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + typedef struct PRTimeParameters { + PRInt32 tp_gmt_offset; + PRInt32 tp_dst_offset; + } PRTimeParameters; + + +Description +----------- + +Each geographic location has a standard time zone, and if Daylight +Saving Time (DST) is practiced, a daylight time zone. The +:ref:`PRTimeParameters` structure represents the local time zone +information in terms of the offset (in seconds) from GMT. The overall +offset is broken into two components: + +``tp_gmt_offset`` + The offset of the local standard time from GMT. + +``tp_dst_offset`` + If daylight savings time (DST) is in effect, the DST adjustment from + the local standard time. This is most commonly 1 hour, but may also + be 30 minutes or some other amount. If DST is not in effect, the + tp_dst_offset component is 0. + +For example, the US Pacific Time Zone has both a standard time zone +(Pacific Standard Time, or PST) and a daylight time zone (Pacific +Daylight Time, or PDT). + +- In PST, the local time is 8 hours behind GMT, so ``tp_gmt_offset`` is + -28800 seconds. ``tp_dst_offset`` is 0, indicating that daylight + saving time is not in effect. + +- In PDT, the clock is turned forward by one hour, so the local time is + 7 hours behind GMT. This is broken down as -8 + 1 hours, so + ``tp_gmt_offset`` is -28800 seconds, and ``tp_dst_offset`` is 3600 + seconds. + +A second example is Japan, which is 9 hours ahead of GMT. Japan does not +use daylight saving time, so the only time zone is Japan Standard Time +(JST). In JST ``tp_gmt_offset`` is 32400 seconds, and ``tp_dst_offset`` +is 0. diff --git a/docs/nspr/reference/prtimeparamfn.rst b/docs/nspr/reference/prtimeparamfn.rst new file mode 100644 index 0000000000..1efd6a5895 --- /dev/null +++ b/docs/nspr/reference/prtimeparamfn.rst @@ -0,0 +1,24 @@ +PRTimeParamFn +============= + +This type defines a callback function to calculate and return the time +parameter offsets from a calendar time object in GMT. + + +Syntax +------ + +.. code:: + + #include <prtime.h> + + typedef PRTimeParameters (PR_CALLBACK_DECL *PRTimeParamFn) + (const PRExplodedTime *gmt); + + +Description +----------- + +The type :ref:`PRTimeParamFn` represents a callback function that, when +given a time instant in GMT, returns the time zone information (offset +from GMT and DST offset) at that time instant. diff --git a/docs/nspr/reference/pruint16.rst b/docs/nspr/reference/pruint16.rst new file mode 100644 index 0000000000..f4e699caed --- /dev/null +++ b/docs/nspr/reference/pruint16.rst @@ -0,0 +1,14 @@ +PRUint16 +======== + +Guaranteed to be an unsigned 16-bit integer on all platforms. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedefdefinition PRUint16; diff --git a/docs/nspr/reference/pruint32.rst b/docs/nspr/reference/pruint32.rst new file mode 100644 index 0000000000..5ea00f9b54 --- /dev/null +++ b/docs/nspr/reference/pruint32.rst @@ -0,0 +1,22 @@ +PRUint32 +======== + +Guaranteed to be an unsigned 32-bit integer on all platforms. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedefdefinition PRUint32; + + +Description +----------- + +May be defined as an unsigned ``int`` or an unsigned ``long``, depending +on the platform. For syntax details for each platform, see +`prtypes.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtypes.h>`__. diff --git a/docs/nspr/reference/pruint64.rst b/docs/nspr/reference/pruint64.rst new file mode 100644 index 0000000000..0bc74917e5 --- /dev/null +++ b/docs/nspr/reference/pruint64.rst @@ -0,0 +1,22 @@ +PRUint64 +======== + +Guaranteed to be an unsigned 64-bit integer on all platforms. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef definition PRUint64; + + +Description +----------- + +May be defined in several different ways, depending on the platform. For +syntax details for each platform, see +`prtypes.h <https://dxr.mozilla.org/mozilla-central/source/nsprpub/pr/include/prtypes.h>`__. diff --git a/docs/nspr/reference/pruint8.rst b/docs/nspr/reference/pruint8.rst new file mode 100644 index 0000000000..2f4224d179 --- /dev/null +++ b/docs/nspr/reference/pruint8.rst @@ -0,0 +1,15 @@ +PRUint8 +======= + +Guaranteed to be an unsigned 8-bit integer on all platforms. There is no +type equivalent to a plain ``char``. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedefdefinition PRUint8; diff --git a/docs/nspr/reference/pruintn.rst b/docs/nspr/reference/pruintn.rst new file mode 100644 index 0000000000..d3aa4a9bb8 --- /dev/null +++ b/docs/nspr/reference/pruintn.rst @@ -0,0 +1,17 @@ +PRUintn +======= + +This (unsigned) type is one of the most appropriate for automatic +variables. It is guaranteed to be at least 16 bits, though various +architectures may define it to be wider (for example, 32 or even 64 +bits). This types is never valid for fields of a structure. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef unsigned int PRUintn; diff --git a/docs/nspr/reference/prunichar.rst b/docs/nspr/reference/prunichar.rst new file mode 100644 index 0000000000..35ebf41562 --- /dev/null +++ b/docs/nspr/reference/prunichar.rst @@ -0,0 +1,18 @@ +PRUnichar +========= + +An unsigned 16-bit type, like ``char`` in Java or the "characters" of a +JavaScript string defined in +`/mozilla/xpcom/base/nscore.h <http://hg.mozilla.org/mozilla-central/file/d35b4d003e9e/xpcom/base/nscore.h>`__. + + +Syntax +------ + +.. code:: + + #if defined(NS_WIN32) + typedef wchar_t PRUnichar; + #else + typedef PRUInt16 PRUnichar; + #endif diff --git a/docs/nspr/reference/pruptrdiff.rst b/docs/nspr/reference/pruptrdiff.rst new file mode 100644 index 0000000000..f58f0a5eb8 --- /dev/null +++ b/docs/nspr/reference/pruptrdiff.rst @@ -0,0 +1,14 @@ +PRUptrdiff +========== + +Unsigned pointer difference type. + + +Syntax +------ + +.. code:: + + #include <prtypes.h> + + typedef unsigned long PRUptrdiff; diff --git a/docs/nspr/reference/random_number_generator.rst b/docs/nspr/reference/random_number_generator.rst new file mode 100644 index 0000000000..0caaf3bbf8 --- /dev/null +++ b/docs/nspr/reference/random_number_generator.rst @@ -0,0 +1,12 @@ +Random Number Generator +======================= + +This chapter describes the NSPR random number generator. + +.. _Random_Number_Generator_Function: + +Random Number Generator Function +-------------------------------- + + - :ref:`PR_GetRandomNoise` - Produces a random value for use as a seed + value for another random number generator. diff --git a/docs/nspr/reference/string_operations.rst b/docs/nspr/reference/string_operations.rst new file mode 100644 index 0000000000..b160f093d2 --- /dev/null +++ b/docs/nspr/reference/string_operations.rst @@ -0,0 +1,11 @@ +This chapter describes some of the key NSPR functions for manipulating +strings. Libraries built on top of NSPR, such as the Netscape security +libraries, use these functions to manipulate strings. If you are copying +or examining strings for use by such libraries or freeing strings that +were allocated by such libraries, you must use these NSPR functions +rather than the libc equivalents. + + - :ref:`PL_strlen` + - :ref:`PL_strcpy` + - :ref:`PL_strdup` + - :ref:`PL_strfree` diff --git a/docs/nspr/reference/thread_pools.rst b/docs/nspr/reference/thread_pools.rst new file mode 100644 index 0000000000..75fc9f75a2 --- /dev/null +++ b/docs/nspr/reference/thread_pools.rst @@ -0,0 +1,41 @@ +This chapter describes the NSPR API Thread Pools. + +.. note:: + + **Note:** This API is a preliminary version in NSPR 4.0 and is + subject to change. + +Thread pools create and manage threads to provide support for scheduling +work (jobs) onto one or more threads. NSPR's thread pool is modeled on +the thread pools described by David R. Butenhof in\ *Programming with +POSIX Threads* (Addison-Wesley, 1997). + +- `Thread Pool Types <#Thread_Pool_Types>`__ +- `Thread Pool Functions <#Thread_Pool_Functions>`__ + +.. _Thread_Pool_Types: + +Thread Pool Types +----------------- + + - :ref:`PRJobIoDesc` + - :ref:`PRJobFn` + - :ref:`PRThreadPool` + - :ref:`PRJob` + +.. _Thread_Pool_Functions: + +Thread Pool Functions +--------------------- + + - :ref:`PR_CreateThreadPool` + - :ref:`PR_QueueJob` + - :ref:`PR_QueueJob_Read` + - :ref:`PR_QueueJob_Write` + - :ref:`PR_QueueJob_Accept` + - :ref:`PR_QueueJob_Connect` + - :ref:`PR_QueueJob_Timer` + - :ref:`PR_CancelJob` + - :ref:`PR_JoinJob` + - :ref:`PR_ShutdownThreadPool` + - :ref:`PR_JoinThreadPool` diff --git a/docs/nspr/reference/thread_synchronization_sample.rst b/docs/nspr/reference/thread_synchronization_sample.rst new file mode 100644 index 0000000000..e1417b130c --- /dev/null +++ b/docs/nspr/reference/thread_synchronization_sample.rst @@ -0,0 +1,2 @@ +This page has no content. Enrich Mozilla Developer Center by +contributing. diff --git a/docs/nspr/reference/threads.rst b/docs/nspr/reference/threads.rst new file mode 100644 index 0000000000..fdcdcc271e --- /dev/null +++ b/docs/nspr/reference/threads.rst @@ -0,0 +1,129 @@ +NSPR provides an execution environment that promotes the use of +lightweight threads. Each thread is an execution entity that is +scheduled independently from other threads in the same process. This +chapter describes the basic NSPR threading API. + +- `Threading Types and Constants <#Threading_Types_and_Constants>`__ +- `Threading Functions <#Threading_Functions>`__ + +A thread has a limited number of resources that it truly owns. These +resources include a stack and the CPU registers (including PC). To an +NSPR client, a thread is represented by a pointer to an opaque structure +of type :ref:`PRThread`. A thread is created by an explicit client request +and remains a valid, independent execution entity until it returns from +its root function or the process abnormally terminates. Threads are +critical resources and therefore require some management. To synchronize +the termination of a thread, you can **join** it with another thread +(see :ref:`PR_JoinThread`). Joining a thread provides definitive proof that +the target thread has terminated and has finished with both the +resources to which the thread has access and the resources of the thread +itself. + +For an overview of the NSPR threading model and sample code that +illustrates its use, see `Introduction to +NSPR <Introduction_to_NSPR>`__. + +For API reference information related to thread synchronization, see +`Locks <Locks>`__ and `Condition Variables <Condition_Variables>`__. + +.. _Threading_Types_and_Constants: + +Threading Types and Constants +----------------------------- + + - :ref:`PRThread` + - :ref:`PRThreadType` + - :ref:`PRThreadScope` + - :ref:`PRThreadState` + - :ref:`PRThreadPriority` + - :ref:`PRThreadPrivateDTOR` + +.. _Threading_Functions: + +Threading Functions +------------------- + +Most of the functions described here accept a pointer to the thread as +an argument. NSPR does not check for the validity of the thread. It is +the caller's responsibility to ensure that the thread is valid. The +effects of these functions on invalid threads are undefined. + +- `Creating, Joining, and Identifying + Threads <#Creating,_Joining,_and_Identifying_Threads>`__ +- `Controlling Thread Priorities <#Controlling_Thread_Priorities>`__ +- `Interrupting and Yielding <#Interrupting_and_Yielding>`__ +- `Setting Global Thread + Concurrency <#Setting_Global_Thread_Concurrency>`__ +- `Getting a Thread's Scope <#Getting_a_Thread's_Scope>`__ + +.. _Creating.2C_Joining.2C_and_Identifying_Threads: + +Creating, Joining, and Identifying Threads +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_CreateThread` creates a new thread. + - :ref:`PR_JoinThread` blocks the calling thread until a specified thread + terminates. + - :ref:`PR_GetCurrentThread` returns the current thread object for the + currently running code. + - :ref:`PR_AttachThread`` associates a :ref:`PRThread` object with an existing + native thread. + - :ref:`PR_DetachThread`` disassociates a :ref:`PRThread` object from a native + thread. + +.. _Controlling_Thread_Priorities: + +Controlling Thread Priorities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For an overview of the way NSPR controls thread priorities, see `Setting +Thread Priorities <Introduction_to_NSPR#Setting_Thread_Priorities.>`__. + +You set a thread's NSPR priority when you create it with +:ref:`PR_CreateThread`. After a thread has been created, you can get and +set its priority with these functions: + + - :ref:`PR_GetThreadPriority` + - :ref:`PR_SetThreadPriority` + +.. _Controlling_Per-Thread_Private_Data: + +Controlling Per-Thread Private Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can use these functions to associate private data with each of the +threads in a process: + + - :ref:`PR_NewThreadPrivateIndex` allocates a unique index. If the call is + successful, every thread in the same process is capable of + associating private data with the new index. + - :ref:`PR_SetThreadPrivate` associates private thread data with an index. + - :ref:`PR_GetThreadPrivate` retrieves data associated with an index. + +.. _Interrupting_and_Yielding: + +Interrupting and Yielding +~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_Interrupt` requests an interrupt of another thread. Once the + target thread has been notified of the request, the request stays + with the thread until the notification either has been delivered + exactly once or is cleared. + - :ref:`PR_ClearInterrupt` clears a previous interrupt request. + - :ref:`PR_Sleep` causes a thread to yield to other threads for a + specified number of ticks. + +.. _Setting_Global_Thread_Concurrency: + +Setting Global Thread Concurrency +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_SetConcurrency` sets the number of global threads used by NSPR + to create local threads. + +.. _Getting_a_Thread.27s_Scope: + +Getting a Thread's Scope +~~~~~~~~~~~~~~~~~~~~~~~~ + + - :ref:`PR_GetThreadScope` gets the scoping of the current thread. diff --git a/docs/nspr/running_nspr_tests.rst b/docs/nspr/running_nspr_tests.rst new file mode 100644 index 0000000000..d877aecf2d --- /dev/null +++ b/docs/nspr/running_nspr_tests.rst @@ -0,0 +1,95 @@ +Running NSPR tests +================== + +NSPR has a test suite in the ``mozilla/nsprpub/pr/tests`` directory. + +By default, we don't build the test programs. Running ``gmake`` in the +top-level directory (``mozilla/nsprpub``) only builds the NSPR +libraries. To build the test programs, you need to change directory to +``mozilla/nsprpub/pr/tests`` and run ``gmake``. Refer to :ref:`NSPR build +instructions` for details. + +To run the test suite, run the shell script +``mozilla/nsprpub/pr/tests/runtests.sh`` in the directory where the test +program binaries reside, for example, + +.. code:: + + cvs -q co -r NSPR_4_6_6_RTM mozilla/nsprpub + mkdir linux.debug + cd linux.debug + ../mozilla/nsprpub/configure + gmake + cd pr/tests + gmake + ../../../mozilla/nsprpub/pr/tests/runtests.sh + +The output of the test suite looks like this: + +.. code:: + + NSPR Test Results - tests + + BEGIN Mon Mar 12 11:44:41 PDT 2007 + NSPR_TEST_LOGFILE /dev/null + + Test Result + + accept Passed + acceptread Passed + acceptreademu Passed + affinity Passed + alarm Passed + anonfm Passed + atomic Passed + attach Passed + bigfile Passed + cleanup Passed + cltsrv Passed + concur Passed + cvar Passed + cvar2 Passed + ... + sprintf FAILED + ... + timetest Passed + tpd Passed + udpsrv Passed + vercheck Passed + version Passed + writev Passed + xnotify Passed + zerolen Passed + END Mon Mar 12 11:55:47 PDT 2007 + +.. _How_to_determine_if_the_test_suite_passed: + +How to determine if the test suite passed +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If all the tests reported **Passed** as the results, the test suite +passed. + +What if some of the tests crashed or reported **FAILED** as the results? +It doesn't necessarily mean the test suite failed because some of the +test programs are known to fail. Until the test failures are fixed, you +should run NSPR tests against **a known good version of NSPR on the same +platform**, and save the test results as the benchmark. Then you can +detect regressions of the new version by comparing its test results with +the benchmark. + +.. _Known_issues: + +Known issues +~~~~~~~~~~~~ + +Other issues with the NSPR test suite are: + +#. Some of the test programs test the accuracy of the timeout of NSPR + functions. Since none of our operating systems is a real-time OS, + such test programs may fail when the test machine is heavily loaded. +#. Some tests, such as ``pipepong`` and ``sockpong``, should not be run + directly. They will be invoked by their companion test programs + (e.g., ``pipeping`` and ``sockping``). This is not an issue if you + run ``runtests.sh`` because ``runtests.sh`` knows not to run such + test programs directly. diff --git a/docs/nspr/using_io_timeouts_and_interrupts_on_nt.rst b/docs/nspr/using_io_timeouts_and_interrupts_on_nt.rst new file mode 100644 index 0000000000..9aaca06a1b --- /dev/null +++ b/docs/nspr/using_io_timeouts_and_interrupts_on_nt.rst @@ -0,0 +1,131 @@ +This technical memo is a cautionary note on using NetScape Portable +Runtime's (NSPR) IO timeout and interrupt on Windows NT 3.51 and 4.0. +Due to a limitation of the present implementation of NSPR IO on NT, +programs must follow the following guideline: + +If a thread calls an NSPR IO function on a file descriptor and the IO +function fails with <tt>PR_IO_TIMEOUT_ERROR</tt> or +<tt>PR_PENDING_INTERRUPT_ERROR</tt>, the file descriptor must be closed +before the thread exits. + +In this memo we explain the problem this guideline is trying to work +around and discuss its limitations. + +.. _NSPR_IO_on_NT: + +NSPR IO on NT +------------- + +The IO model of NSPR 2.0 is synchronous and blocking. A thread calling +an IO function is blocked until the IO operation finishes, either due to +a successful IO completion or an error. If the IO operation cannot +complete before the specified timeout, the IO function returns with +<tt>PR_IO_TIMEOUT_ERROR</tt>. If the thread gets interrupted by another +thread's <tt>PR_Interrupt()</tt> call, the IO function returns with +<tt>PR_PENDING_INTERRUPT_ERROR</tt>. + +On Windows NT, NSPR IO is implemented using NT's *overlapped* (also +called *asynchronous*) *IO*. When a thread calls an IO function, the +thread issues an overlapped IO request using the overlapped buffer in +its <tt>PRThread</tt> structure. Then the thread is put to sleep. In the +meantime, there are dedicated internal threads (called the *idle +threads*) monitoring the IO completion port for completed IO requests. +If a completed IO request appears at the IO completion port, an idle +thread fetches it and wakes up the thread that issued the IO request +earlier. This is the normal way the thread is awakened. + +.. _IO_Timeout_and_Interrupt: + +IO Timeout and Interrupt +------------------------ + +However, NSPR may wake up the thread in two other situations: + +- if the overlapped IO request is not completed before the specified + timeout. (Note that we can't specify timeout on overlapped IO + requests, so the timeouts are all handled at the NSPR level.) In this + case, the error is <tt>PR_IO_TIMEOUT_ERROR</tt>. +- if the thread gets interrupted by another thread's + <tt>PR_Interrupt()</tt> call. In this case, the error is + <tt>PR_PENDING_INTERRUPT_ERROR</tt>. + +These two errors are generated by the NSPR layer, so the OS is oblivious +of what is going on and the overlapped IO request is still in progress. +The OS still has a pointer to the overlapped buffer in the thread's +<tt>PRThread</tt> structure. If the thread subsequently exists and its +<tt>PRThread</tt> structure gets deleted, the pointer to the overlapped +buffer will be pointing to freed memory. This is problematic. + +.. _Canceling_Overlapped_IO_by_Closing_the_File_Descriptor: + +Canceling Overlapped IO by Closing the File Descriptor +------------------------------------------------------ + +Therefore, we need to cancel the outstanding overlapped IO request +before the thread exits. NT's <tt>CancelIo()</tt> function would be +ideal for this purpose. Unfortunately, <tt>CancelIo()</tt> is not +available on NT 3.51. So we can't go this route as long as we are +supporting NT 3.51. The only reliable way to cancel outstanding +overlapped IO request that works on both NT 3.51 and 4.0 is to close the +file descriptor, hence the rule of thumb stated at the beginning of this +memo. + +.. _Limitations: + +Limitations +----------- + +This seemingly harsh way to force the completion of outstanding +overlapped IO request has the following limitations: + +- It is difficult for threads to shared a file descriptor. For example, + suppose thread A and thread B call <tt>PR_Accept()</tt> on the same + socket, and they time out at the same time. Following the rule of + thumb, both threads would close the socket. The first + <tt>PR_Close()</tt> would succeed, but the second <tt>PR_Close()</tt> + would be freeing freed memory. A solution that may work is to use a + lock to ensure only one thread can be using that socket at all times. +- Once there is a timeout or interrupt error, the file descriptor is no + longer usable. Suppose the file descriptor is intended to be used for + the life time of the process, for example, the logging file, this is + really not acceptable. A possible solution is to add a + <tt>PR_DisableInterrupt()</tt> function to turn off interrupts when + accessing such file descriptors. + +.. + + *A related known bug is that timeout and interrupt don't work for + <tt>PR_Connect()</tt> on NT. This bug is due to a different + limitation in our NT implementation.* + +.. _Conclusions: + +Conclusions +----------- + +As long as we need to support NT 3.51, we need to program under the +guideline that after an IO timeout or interrupt error, the thread must +make sure the file descriptor is closed before it exits. Programs should +also take care in sharing file descriptors and using IO timeout or +interrupt on files that need to stay open throughout the process. + +When we stop supporting NT 3.51, we can look into using NT 4's +<tt>CancelIo()</tt> function to cancel outstanding overlapped IO +requests when we get IO timeout or interrupt errors. If +<tt>CancelIo()</tt> really works as advertised, that should +fundamentally solve this problem. + +If these limitations with IO timeout and interrupt are not acceptable to +the needs of your programs, you can consider using the Win95 version of +NSPR. The Win95 version runs without trouble on NT, but you would lose +the better performance provided by NT fibers and asynchronous IO. + +| + +.. _Original_Document_Information: + +Original Document Information +----------------------------- + +- Author: larryh@netscape.com +- Last Updated Date: December 1, 2004 diff --git a/docs/performance/Benchmarking.md b/docs/performance/Benchmarking.md new file mode 100644 index 0000000000..3b429463f7 --- /dev/null +++ b/docs/performance/Benchmarking.md @@ -0,0 +1,98 @@ +# Benchmarking + +## Debug Builds + +Debug builds (\--enable-debug) and non-optimized builds +(\--disable-optimize) are *much* slower. Any performance metrics +gathered by such builds are largely unrelated to what would be found in +a release browser. + +## Rust optimization level + +Local optimized builds are [compiled with rust optimization level 1 by +default](https://groups.google.com/forum/#!topic/mozilla.dev.platform/pN9O5EB_1q4), +unlike Nightly builds, which use rust optimization level 2. This setting +reduces build times significantly but comes with a serious hit to +runtime performance for any rust code ([for example stylo and +webrender](https://groups.google.com/d/msg/mozilla.dev.platform/pN9O5EB_1q4/ooXNuqMECAAJ)). +Add the following to your [mozconfig] in order to build with level 2: + +``` +ac_add_options RUSTC_OPT_LEVEL=2 +``` + +## Profile Guided Optimization (PGO) +[Profile Guided +Optimization](/build/buildsystem/pgo.rst#profile-guided-optimization) is +disabled by default and may improve runtime by up to 20%. However, it takes a +long time to build. To enable, add the following to your [mozconfig]: +``` +ac_add_options MOZ_PGO=1 +``` + +## GC Poisoning + +Many Firefox builds have a diagnostic tool that causes crashes to happen +sooner and produce much more actionable information, but also slow down +regular usage substantially. In particular, \"GC poisoning\" is used in +all debug builds, and in optimized Nightly builds (but not opt Developer +Edition or Beta builds). The poisoning can be disabled by setting the +environment variable + +``` + JSGC_DISABLE_POISONING=1 +``` + +before starting the browser. + +## Async Stacks + +Async stacks no longer impact performance since **Firefox 78**, as +{{bug(1601179)}} limits async stack capturing to when DevTools is +opened. + +Another option that is on by default in non-release builds is the +preference javascript.options.asyncstack, which provides better +debugging information to developers. Set it to false to match a release +build. (This may be disabled for many situations in the future. See +{{bug(1280819)}}. + +## Accelerated Graphics + +Especially on Linux, accelerated graphics can sometimes lead to severe +performance problems even if things look ok visually. Normally you would +want to leave acceleration enabled while profiling, but on Linux you may +wish to disable accelerated graphics (Preferences -\> Advanced -\> +General -\> Use hardware acceleration when available). + +## Flash Plugin + +If you are profiling real websites, you should disable the Adobe Flash +plugin so you are testing Firefox code and not Flash jank problems. In +about:addons \> Plugins, set Shockwave Flash to \"Never Activate\". + +## Timer Precision + +Firefox reduces the precision of the Performance APIs and other clock +and timer APIs accessible to Web Content. They are currently reduce to a +multiple of 2ms; which is controlled by the privacy.reduceTimerPrecision +about:config flag. + +The exact value of the precision is controlled by the +privacy.resistFingerprinting.reduceTimerPrecision.microseconds +about:config flag. + +## Profiling tools + +Currently the Gecko Profiler has limitations in the UI for inverted call +stack top function analysis which is very useful for finding heavy +functions that call into a whole bunch of code. Currently such functions +may be easy to miss looking at a profile, so feel free to *also* use +your favorite native profiler. It also lacks features such as +instruction level profiling which can be helpful in low level profiling, +or finding the hot loop inside a large function, etc. Some example tools +include Instruments on OSX (part of XCode), [RotateRight +Zoom](http://www.rotateright.com/) on Linux (uses perf underneath), and +Intel VTune on Windows or Linux. + +[mozconfig]: /setup/configuring_build_options.rst#using-a-mozconfig-configuration-file diff --git a/docs/performance/GPU_performance.md b/docs/performance/GPU_performance.md new file mode 100644 index 0000000000..25085f41c3 --- /dev/null +++ b/docs/performance/GPU_performance.md @@ -0,0 +1,42 @@ +# GPU Performance + +Doing performance work with GPUs is harder than with CPUs because of the +asynchronous and massively parallel architecture. + +## Tools + +[PIX](https://devblogs.microsoft.com/pix/introduction/) - Can do +timing of Direct3D calls. Works reasonably well with Firefox. + +NVIDIA PerfHUD - Last I checked required a special build to be used. + +NVIDIA Parallel Nsight - Haven\'t tried. + +AMD GPU ShaderAnalyzer - Will compile a shader and show the machine code +and give static pipeline estimations. Not that useful for Firefox +because all of our shaders are pretty simple. + +AMD GPU PerfStudio - I had trouble getting this to work, and can\'t +remember whether I actually did or not. + +[Intel Graphics Performance Analyzers](http://software.intel.com/en-us/articles/intel-gpa/ "http://software.intel.com/en-us/articles/intel-gpa/") +- Haven\'t tried. + +[APITrace](https://github.com/apitrace/apitrace "https://github.com/apitrace/apitrace") +- Open source, works OK. + +[PVRTrace](http://www.imgtec.com/powervr/insider/pvrtrace.asp "http://www.imgtec.com/powervr/insider/pvrtrace.asp") +- Doesn\'t seem to emit traces on android/Nexus S. Looks like it\'s +designed for X11-based linux-ARM devices, OMAP3 is mentioned a lot in +the docs \... + +## Guides + +[Accurately Profiling Direct3D API Calls (Direct3D +9)](http://msdn.microsoft.com/en-us/library/bb172234%28v=vs.85%29.aspx "http://msdn.microsoft.com/en-us/library/bb172234(v=vs.85).aspx") +Suggests avoiding normal profilers like xperf and instead measuring the +time to flush the command buffer. + +[OS X - Best Practices for Working with Texture +Data](http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html "http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html") +- Sort of old, but still useful. diff --git a/docs/performance/activity_monitor_and_top.md b/docs/performance/activity_monitor_and_top.md new file mode 100644 index 0000000000..4e687c4dfe --- /dev/null +++ b/docs/performance/activity_monitor_and_top.md @@ -0,0 +1,165 @@ +# Activity Monitor, Battery Status Menu and top + +This article describes the Activity Monitor, Battery Status Menu, and +`top` --- three related tools available on Mac OS X. + +**Note**: The [power profiling overview](power_profiling_overview.md) is +worth reading at this point if you haven't already. It may make parts +of this document easier to understand. + +## Activity Monitor + +This is a [built-in OS X tool](https://support.apple.com/en-au/HT201464) +that shows real-time process measurements. It is well-known and its +"Energy Impact" measure is likely to be consulted by users to compare +the power consumption of different programs. ([Apple support +documentation](https://support.apple.com/en-au/HT202776) specifically +recommends it for troubleshooting battery life problems.) +***Unfortunately "Energy Impact" is not a good measure for either +users or software developers and it should be avoided.*** Activity +Monitor can still be useful, however. + +### Power-related measurements + +Activity Monitor has several tabs. They can all be customized to show +any of the available measurements (by right-clicking on the column +strip) but only the "Energy" tab groups child processes with parent +processes, which is useful, so it's the best one to use. The following +screenshot shows a customized "Energy" tab. + +![](img/ActMon-Energy.png) + +The power-related columns are as follows. + +- **Energy Impact** / **Avg Energy Impact**: See the separate section + below. +- **% CPU**: CPU usage percentage. This can exceed 100% if multiple + cores are being used. +- **Idle wake Ups**: + - In Mac OS 10.9 this measured "package idle exit" wakeups. This + is the same value as + [powermetrics](./powermetrics.md)' + "Pkg idle" measurement (i.e. + `task_power_info::task_platform_idle_wakeups` obtained from the + `task_info` function.) + - In Mac OS 10.10 it appears to have been changed to measure + interrupt-level wakeups (a superset of idle wakeups), which are + less interesting. This is the same value as + [powermetrics](./powermetrics.md)' + "Intr" measurement (i.e. + `task_power_info::task_interrupt_wakeups` obtained from the + `task_info` function.) +- **Requires High Perf GPU**: Many Macs have two GPUs: a low-power, + low-performance integrated GPU, and a high-power, high-performance + external GPU. Using the high-performance GPU can greatly increase + power consumption, and should be avoided whenever possible. This + column indicates which GPU is being used. + +Activity Monitor can be useful for cursory measurements, but for more +precise and detailed measurements other tools such as +[powermetrics](./powermetrics.md) are better. + +### What does "Energy Impact" measure? + +"Energy Impact" is a hybrid proxy measure of power consumption. +[Careful +investigation](https://blog.mozilla.org/nnethercote/2015/08/26/what-does-the-os-x-activity-monitors-energy-impact-actually-measure/) +indicates that on Mac OS 10.10 and 10.11 it is computed with a formula +that is machine model-specific, and includes the following factors: CPU +usage, wakeup frequency, [quality of service +class](https://developer.apple.com/library/prerelease/mac/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/PrioritizeWorkAtTheTaskLevel.html) +usage, and disk, GPU, and network activity. The weightings of each +factor can be found in one of the the files in +`/usr/share/pmenergy/Mac-<id>.plist`, where `<id>` can be determined +with the following command. + + ioreg -l | grep board-id + +In contrast, on Mac OS 10.9 it is computed via a simpler machine +model-independent formula that only factors in CPU usage and wakeup +frequency. + +In both cases "Energy Impact" often correlates poorly with actual +power consumption and should be avoided in favour of direct measurements +that have clear physical meanings. + +### What does "Average Energy Impact" measure? + +When the Energy tab of Activity Monitor is first opened, the "Average +Energy Impact" column is empty and the title bar says "Activity +Monitor (Processing\...)". After 5--10 seconds, the "Average Energy +Impact" column is populated with values and the title bar changes to +"Activity Monitor (Applications in last 8 hours)". If you have `top` +open during those 5--10 seconds you'll see that `systemstats` is +running and using a lot of CPU, and so presumably the measurements are +obtained from it. + +`systemstats` is a program that runs continuously and periodically +measures, among other things, CPU usage and idle wakeups for each +running process. Tests indicate that it is almost certainly using the +same "Energy Impact" formula to compute the "Average Energy Impact", +using measurements from the past 8 hours of wake time (i.e. if a laptop +is closed for several hours and then reopened, those hours are not +included in the calculation.) + +## Battery status menu + +When you click on the battery icon in the OS X menu bar you get a +drop-down menu that includes a list of "Apps Using Significant Energy". +This is crude but prominent, and therefore worth understanding --- even +though it's not much use for profiling applications. + +![Screenshot of the OS X battery statusmenu](img/battery-status-menu.png) + +When you open this menu for the first time in a while it says +"Collecting Power Usage Information" for a few seconds, and if you have +`top` open during that time you'll see that, once again, `systemstats` +is running and using a lot of CPU. Furthermore, if you click on an +application name in the menu Activity Monitor will be opened and that +application's entry will be highlighted. Based on these facts it seems +reasonable to assume that "Energy Impact" is again being used to +determine which applications are "using significant energy". + +Testing shows that once an energy-intensive application is started it +takes less than a minute for it to show up in the battery status menu. +And once the application stops using high amounts of energy it takes a +few minutes to disappear. The exception is when the application is +closed, in which case it disappears immediately. And it appears that a +program with an "Energy Impact" of roughly 20 or more will eventually +show up as significant, and programs that have much higher "Energy +Impact" values tend to show up more quickly. + +All of these battery status menu observations are difficult to make +reliably and so should be treated with caution. It is clear, however, +that the window used by the battery status menu is measured in seconds +or minutes, which is much less than the 8 hour window used for "Average +Energy Impact" in Activity Monitor. + +## `top` + +`top` is similar to Activity Monitor, but is a command-line utility. To +see power-related measurements, invoke it as follows. + +``` +top -stats pid,command,cpu,idlew,power -o power -d +``` + +**Note**: `-a` and `-e` can be used instead of `-d` to get different +counting modes. See the man page for details. + +It will show periodically-updating data like the following. + + PID COMMAND %CPU IDLEW POWER + 50300 firefox 12.9 278 26.6 + 76256 plugin-container 3.4 159 11.3 + 151 coreaudiod 0.9 68 4.3 + 76505 top 1.5 1 1.6 + 76354 Activity Monitor 1.0 0 1.0 + +- The **PID**, **COMMAND** and **%CPU** columns are self-explanatory. +- The **IDLEW** column is the number of "package idle exit" wakeups. +- The **POWER** column's value is computed by the same formula as the + one used for "Energy Impact" by Activity Monitor in Mac OS 10.9, + and should also be avoided. + +`top` is unlikely to be much use for power profiling. diff --git a/docs/performance/automated_performance_testing_and_sheriffing.md b/docs/performance/automated_performance_testing_and_sheriffing.md new file mode 100644 index 0000000000..02469c65de --- /dev/null +++ b/docs/performance/automated_performance_testing_and_sheriffing.md @@ -0,0 +1,24 @@ +# Automated performance testing and sheriffing + +We have several test harnesses that test Firefox for various performance +characteristics (page load time, startup time, etc.). We also generate +some metrics as part of the build process (like installer size) that are +interesting to track over time. Currently we aggregate this information +in the [Perfherder web +application](https://wiki.mozilla.org/Auto-tools/Projects/Perfherder) +where performance sheriffs watch for significant regressions, filing +bugs as appropriate. + +Current list of automated systems we are tracking (at least to some +degree): + +- [Talos](https://wiki.mozilla.org/TestEngineering/Performance/Talos): The main + performance system, run on virtually every check-in to an + integration branch +- [build_metrics](/setup/configuring_build_options.rst): + A grab bag of performance metrics generated by the build system +- [AreWeFastYet](https://arewefastyet.com/): A generic JavaScript and + Web benchmarking system + tool +- [Platform microbenchmarks](platform_microbenchmarks/platform_microbenchmarks.md) +- [Build Metrics](build_metrics/build_metrics.md) diff --git a/docs/performance/bestpractices.md b/docs/performance/bestpractices.md new file mode 100644 index 0000000000..ee176de294 --- /dev/null +++ b/docs/performance/bestpractices.md @@ -0,0 +1,578 @@ +# Performance best practices for Firefox front-end engineers + +This guide will help Firefox developers working on front-end code +produce code which is as performant as possible—not just on its own, but +in terms of its impact on other parts of Firefox. Always keep in mind +the side effects your changes may have, from blocking other tasks, to +interfering with other user interface elements. + +## Avoid the main thread where possible + +The main thread is where we process user events and do painting. It's +also important to note that most of our JavaScript runs on the main +thread, so it's easy for script to cause delays in event processing or +painting. That means that the more code we can get off of the main +thread, the more that thread can respond to user events, paint, and +generally be responsive to the user. + +You might want to consider using a Worker if you need to do some +computation that can be done off of the main thread. If you need more +elevated privileges than a standard worker allows, consider using a +ChromeWorker, which is a Firefox-only API which lets you create +workers with more elevated privileges. + +## Use requestIdleCallback() + +If you simply cannot avoid doing some kind of long job on the main +thread, try to break it up into smaller pieces that you can run when the +browser has a free moment to spare, and the user isn't doing anything. +You can do that using **requestIdleCallback()** and the [Cooperative +Scheduling of Background Tasks API](https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API), +and doing it only when we have a free second where presumably the user +isn’t doing something. + +See also the blog post [Collective scheduling with requestIdleCallback](https://hacks.mozilla.org/2016/11/cooperative-scheduling-with-requestidlecallback/). + +As of [bug 1353206](https://bugzilla.mozilla.org/show_bug.cgi?id=1353206), +you can also schedule idle events in non-DOM contexts by using +**Services.tm.idleDispatchToMainThread**. See the +**nsIThreadManager.idl** file for more details. + +## Hide your panels + +If you’re adding a new XUL *\<xul:popup\>* or *\<xul:panel\>* to a +document, set the **hidden** attribute to **true** by default. By doing +so, you cause the binding applied on demand rather than at load time, +which makes initial construction of the XUL document faster. + +## Get familiar with the pipeline that gets pixels to the screen + +Learn how pixels you draw make their way to the screen. Knowing the path +they will take through the various layers of the browser engine will +help you optimize your code to avoid pitfalls. + +The rendering process goes through the following steps: + +![This is the pipeline that a browser uses to get pixels to the screen](img/rendering.png) + +The above image is used under [Creative Commons Attribution 3.0](https://creativecommons.org/licenses/by/3.0/), +courtesy of [this page](https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing) +from our friends at Google, which itself is well worth the read. + +For a very down-to-earth explanation of the Style, Layout, Paint and +Composite steps of the pipeline, [this Hacks blog post](https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/) +does a great job of explaining it. + +To achieve a 60 FPS frame rate, all of the above has to happen in 16 +milliseconds or less, every frame. + +Note that **requestAnimationFrame()** lets you queue up JavaScript to +**run right before the style flush occurs**. This allows you to put all +of your DOM writes (most importantly, anything that could change the +size or position of things in the DOM) just before the style and layout +steps of the pipeline, combining all the style and layout calculations +into a single batch so it all happens once, in a single frame tick, +instead of across multiple frames. + +See [Detecting and avoiding synchronous reflow](#detecting-and-avoiding-synchronous-reflow) +below for more information. + +This also means that *requestAnimationFrame()* is **not a good place** +to put queries for layout or style information. + +## Detecting and avoiding synchronous style flushes + +### What are style flushes? +When CSS is applied to a document (HTML or XUL, it doesn’t matter), the +browser does calculations to figure out which CSS styles will apply to +each element. This happens the first time the page loads and the CSS is +initially applied, but can happen again if JavaScript modifies the DOM. + +JavaScript code might, for example, change DOM node attributes (either +directly or by adding or removing classes from elements), and can also +add, remove, or delete DOM nodes. Because styles are normally scoped to +the entire document, the cost of doing these style calculations is +proportional to the number of DOM nodes in the document (and the number +of styles being applied). + +It is expected that over time, script will update the DOM, requiring us +to recalculate styles. Normally, the changes to the DOM just result in +the standard style calculation occurring immediately after the +JavaScript has finished running during the 16ms window, inside the +"Style" step. That's the ideal scenario. + +However, it's possible for script to do things that force multiple style +calculations (or **style flushes**) to occur synchronously during the +JavaScript part of the 16 ms window. The more of them there are, the +more likely they'll exceed the 16ms frame budget. If that happens, some +of them will be postponed until the next frame (or possibly multiple +frames, if necessary), this skipping of frames is called **jank**. + +Generally speaking, you force a synchronous style flush any time you +query for style information after the DOM has changed within the same +frame tick. Depending on whether or not [the style information you’re +asking for has something to do with size or position](https://gist.github.com/paulirish/5d52fb081b3570c81e3a) +you may also cause a layout recalculation (also referred to as *layout +flush* or *reflow*), which is also an expensive step see [Detecting +and avoiding synchronous reflow](#detecting-and-avoiding-synchronous-reflow) below. + +To avoid this: avoid reading style information if you can. If you *must* +read style information, do so at the very beginning of the frame, before +any changes have been made to the DOM since the last time a style flush +occurred. + +Historically, there hasn't been an easy way of doing this - however, +[bug 1434376](https://bugzilla.mozilla.org/show_bug.cgi?id=1434376) +has landed some ChromeOnly helpers to the window binding to +make this simpler. + +If you want to queue up some JavaScript to run after the next *natural* +style and layout flush, try: + + + // Suppose we want to get the computed "display" style of some node without + // causing a style flush. We could do it this way: + async function nodeIsDisplayNone(node) { + let display = await window.promiseDocumentFlushed(() => { + // Do _not_ under any circumstances write to the DOM in one of these + // callbacks! + return window.getComputedStyle(node).display; + }); + + return display == "none"; + } + +See [Detecting and avoiding synchronous reflow](#detecting-and-avoiding-synchronous-reflow) +for a more advanced example of getting layout information, and then +setting it safely, without causing flushes. + +bestpractices.html#detecting-and-avoiding-synchronous-reflow + + +*promiseDocumentFlushed* is only available to privileged script, and +should be called on the inner window of a top-level frame. Calling it on +the outer window of a subframe is not supported, and calling it from +within the inner window of a subframe might cause the callback to fire +even though a style and layout flush will still be required. These +gotchas should be fixed by +[bug 1441173](https://bugzilla.mozilla.org/show_bug.cgi?id=1441173). + +For now, it is up to you as the consumer of this API to not accidentally +write to the DOM within the *promiseDocumentFlushed* callback. Doing +so might cause flushes to occur for other *promiseDocumentFlushed* +callbacks that are scheduled to fire in the same tick of the refresh +driver. +[bug 1441168](https://bugzilla.mozilla.org/show_bug.cgi?id=1441168) +tracks work to make it impossible to modify the DOM within a +*promiseDocumentFlushed* callback. + +### Writing tests to ensure you don’t add more synchronous style flushes + +Unlike reflow, there isn’t a “observer” mechanism for style +recalculations. However, as of Firefox 49, the +*nsIDOMWindowUtils.elementsRestyled* attribute records a count of how +many style calculations have occurred for a particular DOM window. + +It should be possible to write a test that gets the +*nsIDOMWindowUtils* for a browser window, records the number of +styleFlushes, then **synchronously calls the function** that you want to +test, and immediately after checks the styleFlushes attribute again. If +the value went up, your code caused synchronous style flushes to occur. + +Note that your test and function *must be called synchronously* in order +for this test to be accurate. If you ever go back to the event loop (by +yielding, waiting for an event, etc), style flushes unrelated to your +code are likely to run, and your test will give you a false positive. + +## Detecting and avoiding synchronous reflow + +This is also sometimes called “sync layout”, "sync layout flushes" or +“sync layout calculations” + +*Sync reflow* is a term bandied about a lot, and has negative +connotations. It's not unusual for an engineer to have only the vaguest +sense of what it is—and to only know to avoid it. This section will +attempt to demystify things. + +The first time a document (XUL or HTML) loads, we parse the markup, and +then apply styles. Once the styles have been calculated, we then need to +calculate where things are going to be placed on the page. This layout +step can be seen in the “16ms” pipeline graphic above, and occurs just +before we paint things to be composited for the user to see. + +It is expected that over time, script will update the DOM, requiring us +to recalculate styles, and then update layout. Normally, however, the +changes to the DOM just result in the standard style calculation that +occurs immediately after the JavaScript has finished running during the +16ms window. + +### Interruptible reflow + +Since [the early days](https://bugzilla.mozilla.org/show_bug.cgi?id=67752), Gecko has +had the notion of interruptible reflow. This is a special type of +**content-only** reflow that checks at particular points whether or not +it should be interrupted (usually to respond to user events). + +Because **interruptible reflows can only be interrupted when laying out +content, and not chrome UI**, the rest of this section is offered only +as context. + +When an interruptible reflow is interrupted, what really happens is that +certain layout operations can be skipped in order to paint and process +user events sooner. + +When an interruptible reflow is interrupted, the best-case scenario is +that all layout is skipped, and the layout operation ends. + +The worst-case scenario is that none of the layout can be skipped +despite being interrupted, and the entire layout calculation occurs. + +Reflows that are triggered "naturally" by the 16ms tick are all +considered interruptible. Despite not actually being interuptible when +laying out chrome UI, striving for interruptible layout is always good +practice because uninterruptible layout has the potential to be much +worse (see next section). + +**To repeat, only interruptible reflows in web content can be +interrupted.** + +### Uninterruptible reflow + +Uninterruptible reflow is what we want to **avoid at all costs**. +Uninterruptible reflow occurs when some DOM node’s styles have changed +such that the size or position of one or more nodes in the document will +need to be updated, and then **JavaScript asks for the size or position +of anything**. Since everything is pending a reflow, the answer isn't +available, so everything stalls until the reflow is complete and the +script can be given an answer. Flushing layout also means that styles +must be flushed to calculate the most up-to-date state of things, so +it's a double-whammy. + +Here’s a simple example, cribbed from [this blog post by Paul +Rouget](http://paulrouget.com/e/fxoshud): + + + div1.style.margin = "200px"; // Line 1 + var height1 = div1.clientHeight; // Line 2 + div2.classList.add("foobar"); // Line 3 + var height2 = div2.clientHeight; // Line 4 + doSomething(height1, height2); // Line 5 + +At line 1, we’re setting some style information on a DOM node that’s +going to result in a reflow - but (at just line 1) it’s okay, because +that reflow will happen after the style calculation. + +Note line 2 though - we’re asking for the height of some DOM node. This +means that Gecko needs to synchronously calculate layout (and styles) +using an uninterruptible reflow in order to answer the question that +JavaScript is asking (“What is the *clientHeight* of *div1*?”). + +It’s possible for our example to avoid this synchronous, uninterruptible +reflow by moving lines 2 and 4 above line 1. Assuming there weren’t any +style changes requiring size or position recalculation above line 1, the +*clientHeight* information should be cached since the last reflow, and +will not result in a new layout calculation. + +If you can avoid querying for the size or position of things in +JavaScript, that’s the safest option—especially because it’s always +possible that something earlier in this tick of JavaScript execution +caused a style change in the DOM without you knowing it. + +Note that given the same changes to the DOM of a chrome UI document, a +single synchronous uninterruptible reflow is no more computationally +expensive than an interruptible reflow triggered by the 16ms tick. It +is, however, advantageous to strive for reflow to only occur in the one +place (the layout step of the 16ms tick) as opposed to multiple times +during the 16ms tick (which has a higher probability of running through +the 16ms budget). + +### How do I avoid triggering uninterruptible reflow? + +Here's a [list of things that JavaScript can ask for that can cause +uninterruptible reflow](https://gist.github.com/paulirish/5d52fb081b3570c81e3a), to +help you think about the problem. Note that some items in the list may +be browser-specific or subject to change, and that an item not occurring +explicitly in the list doesn't mean it doesn't cause reflow. For +instance, at time of writing accessing *event.rangeOffset* [triggers +reflow](https://searchfox.org/mozilla-central/rev/6bfadf95b4a6aaa8bb3b2a166d6c3545983e179a/dom/events/UIEvent.cpp#215-226) +in Gecko, and does not occur in the earlier link. If you're unsure +whether something causes reflow, check! + +Note how abundant the properties in that first list are. This means that +when enumerating properties on DOM objects (e.g. elements/nodes, events, +windows, etc.) **accessing the value of each enumerated property will +almost certainly (accidentally) cause uninterruptible reflow**, because +a lot of DOM objects have one or even several properties that do so. + +If you require size or position information, you have a few options. + +[bug 1434376](https://bugzilla.mozilla.org/show_bug.cgi?id=1434376) +has landed a helper in the window binding to make it easier for +privileged code to queue up JavaScript to run when we know that the DOM +is not dirty, and size, position, and style information is cheap to +query for. + +Here's an example: + + async function matchWidth(elem, otherElem) { + let width = await window.promiseDocumentFlushed(() => { + // Do _not_ under any circumstances write to the DOM in one of these + // callbacks! + return elem.clientWidth; + }); + + requestAnimationFrame(() => { + otherElem.style.width = `${width}px`; + }); + } + +Please see the section on *promiseDocumentFlushed* in [Detecting and +avoiding synchronous style flushes](#detecting-and-avoiding-synchronous-style-flushes) +for more information on how to use the API. + +Note that queries for size and position information are only expensive +if the DOM has been written to. Otherwise, we're doing a cheap look-up +of cached information. If we work hard to move all DOM writes into +*requestAnimationFrame()*, then we can be sure that all size and +position queries are cheap. + +It's also possible (though less infallible than +*promiseDocumentFlushed*) to queue JavaScript to run very soon after +the frame has been painted, where the likelihood is highest that the DOM +has not been written to, and layout and style information queries are +still cheap. This can be done by using a *setTimeout* or dispatching a +runnable inside a *requestAnimationFrame* callback, for example: + + + requestAnimationFrame(() => { + setTimeout(() => { + // This code will be run ASAP after Style and Layout information have + // been calculated and the paint has occurred. Unless something else + // has dirtied the DOM very early, querying for style and layout information + // here should be cheap. + }, 0); + }); + + // Or, if you are running in privileged JavaScript and want to avoid the timer overhead, + // you could also use: + + requestAnimationFrame(() => { + Services.tm.dispatchToMainThread(() => { + // Same-ish as above. + }); + }); + +This also implies that *querying for size and position information* in +*requestAnimationFrame()* has a high probability of causing a +synchronous reflow. + +### Other useful methods + +Below you'll find some suggestions for other methods which may come in +handy when you need to do things without incurring synchronous reflow. +These methods generally return the most-recently-calculated value for +the requested value, which means the value may no longer be current, but +may still be "close enough" for your needs. Unless you need precisely +accurate information, they can be valuable tools in your performance +toolbox. + +#### nsIDOMWindowUtils.getBoundsWithoutFlushing() + +*getBoundsWithoutFlushing()* does exactly what its name suggests: it +allows you to get the bounds rectangle for a DOM node contained in a +window without flushing layout. This means that the information you get +is potentially out-of-date, but allows you to avoid a sync reflow. If +you can make do with information that may not be quite current, this can +be helpful. + +#### nsIDOMWindowUtils.getRootBounds() + +Like *getBoundsWithoutFlushing()*, *getRootBounds()* lets you get +the dimensions of the window without risking a synchronous reflow. + +#### nsIDOMWindowUtils.getScrollXY() + +Returns the window's scroll offsets without taking the chance of causing +a sync reflow. + +### Writing tests to ensure you don’t add more unintentional reflow + +The interface +[nsIReflowObserver](https://dxr.mozilla.org/mozilla-central/source/docshell/base/nsIReflowObserver.idl) +lets us detect both interruptible and uninterruptible reflows. A number +of tests have been written that exercise various functions of the +browser [opening tabs](http://searchfox.org/mozilla-central/rev/78cefe75fb43195e7f5aee1d8042b8d8fc79fc70/browser/base/content/test/general/browser_tabopen_reflows.js), +[opening windows](http://searchfox.org/mozilla-central/source/browser/base/content/test/general/browser_windowopen_reflows.js) +and ensure that we don’t add new uninterruptible reflows accidentally +while those actions occur. + +You should add tests like this for your feature if you happen to be +touching the DOM. + +## Detecting over-painting + +Painting is, in general, cheaper than both style calculation and layout +calculation; still, the more you can avoid, the better. Generally +speaking, the larger an area that needs to be repainted, the longer it +takes. Similarly, the more things that need to be repainted, the longer +it takes. + +If a profile says a lot of time is spent in painting or display-list building, +and you're unsure why, consider talking to our always helpful graphics team in +the [gfx room](https://chat.mozilla.org/#/room/%23gfx:mozilla.org) on +[Matrix](https://wiki.mozilla.org/Matrix), and they can probably advise you. + +Note that a significant number of the graphics team members are in the US +Eastern Time zone (UTC-5 or UTC-4 during Daylight Saving Time), so let that +information guide your timing when you ask questions in the +[gfx room](https://chat.mozilla.org/#/room/%23gfx:mozilla.org). + +## Adding nodes using DocumentFragments + +Sometimes you need to add several DOM nodes as part of an existing DOM +tree. For example, when using XUL *\<xul:menupopup\>s*, you often have +script which dynamically inserts *\<xul:menuitem\>s*. Inserting items +into the DOM has a cost. If you're adding a number of children to a DOM +node in a loop, it's often more efficient to batch them into a single +insertion by creating a *DocumentFragment*, adding the new nodes to +that, then inserting the *DocumentFragment* as a child of the desired +node. + +A *DocumentFragment* is maintained in memory outside the DOM itself, +so changes don't cause reflow. The API is straightforward: + +1. Create the *DocumentFragment* by calling + *Document.createDocumentFragment()*. + +2. Create each child element (by calling *Document.createElement()* + for example), and add each one to the fragment by calling + *DocumentFragment.appendChild()*. + +3. Once the fragment is populated, append the fragment to the DOM by + calling *appendChild()* on the parent element for the new elements. + +This example has been cribbed from [davidwalsh’s blog +post](https://davidwalsh.name/documentfragment): + + + // Create the fragment + + var frag = document.createDocumentFragment(); + + // Create numerous list items, add to fragment + + for(var x = 0; x < 10; x++) { + var li = document.createElement("li"); + li.innerHTML = "List item " + x; + frag.appendChild(li); + } + + // Mass-add the fragment nodes to the list + + listNode.appendChild(frag); + +The above is strictly cheaper than individually adding each node to the +DOM. + +## The Gecko profiler add-on is your friend + +The Gecko profiler is your best friend when diagnosing performance +problems and looking for bottlenecks. There’s plenty of excellent +documentation on MDN about the Gecko profiler: + +- [Basic instructions for gathering and sharing a performance profile](reporting_a_performance_problem.md) + +- [Advanced profile analysis](https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Profiling_with_the_Built-in_Profiler) + +## Don’t guess—measure. + +If you’re working on a performance improvement, this should go without +saying: ensure that what you care about is actually improving by +measuring before and after. + +Landing a speculative performance enhancement is the same thing as +landing speculative bug fixes—these things need to be tested. Even if +that means instrumenting a function with a *Date.now()* recording at +the entrance, and another *Date.now()* at the exit points in order to +measure processing time changes. + +Prove to yourself that you’ve actually improved something by measuring +before and after. + +### Use the performance API + +The [performance +API](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API) +is very useful for taking high-resolution measurements. This is usually +much better than using your own hand-rolled timers to measure how long +things take. You access the API through *Window.performance*. + +Also, the Gecko profiler back-end is in the process of being modified to +expose things like markers (from *window.performance.mark()*). + +### Use the compositor for animations + +Performing animations on the main thread should be treated as +**deprecated**. Avoid doing it. Instead, animate using +*Element.animate()*. See the article [Animating like you just don't +care](https://hacks.mozilla.org/2016/08/animating-like-you-just-dont-care-with-element-animate/) +for more information on how to do this. + +### Explicitly define start and end animation values + +Some optimizations in the animation code of Gecko are based on an +expectation that the *from* (0%) and the *to* (100%) values will be +explicitly defined in the *@keyframes* definition. Even though these +values may be inferred through the use of initial values or the cascade, +the offscreen animation optimizations are dependent on the explicit +definition. See [this comment](https://bugzilla.mozilla.org/show_bug.cgi?id=1419096#c18) +and a few previous comments on that bug for more information. + +## Use IndexedDB for storage + +[AppCache](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/en-US/docs/Web/HTML/Using_the_application_cache) +and +[LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage) +are synchronous storage APIs that will block the main thread when you +use them. Avoid them at all costs! + +[IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) +is preferable, as the API is asynchronous (all disk operations occur off +of the main thread), and can be accessed from web workers. + +IndexedDB is also arguably better than storing and retrieving JSON from +a file—particularly if the JSON encoding or decoding is occurring on the +main thread. IndexedDB will do JavaScript object serialization and +deserialization for you using the [structured clone +algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) +meaning that you can stash [things like maps, sets, dates, blobs, and +more](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#Supported_types) +without having to do conversions for JSON compatibility. + +A Promise-based wrapper for IndexedDB, +[IndexedDB.sys.mjs](http://searchfox.org/mozilla-central/source/toolkit/modules/IndexedDB.sys.mjs) +is available for chrome code. + +## Test on weak hardware + +For the folks paid to work on Firefox, we tend to have pretty powerful +hardware for development. This is great, because it reduces build times, +and means we can do our work faster. + +We should remind ourselves that the majority of our user base is +unlikely to have similar hardware. Look at the [Firefox Hardware +Report](https://data.firefox.com/dashboard/hardware) to get +a sense of what our users are working with. Test on slower machines to +make it more obvious to yourself if what you’ve written impacts the +performance of the browser. + +## Consider loading scripts with the subscript loader asynchronously + +If you've ever used the subscript loader, you might not know that it can +load scripts asynchronously, and return a Promise once they're loaded. +For example: + + + Services.scriptloader.loadSubScriptWithOptions(myScriptURL, { async: true }).then(() => { + console.log("Script at " + myScriptURL + " loaded asynchronously!"); + }); diff --git a/docs/performance/build_metrics/build_metrics.md b/docs/performance/build_metrics/build_metrics.md new file mode 100644 index 0000000000..cb27a42be7 --- /dev/null +++ b/docs/performance/build_metrics/build_metrics.md @@ -0,0 +1,31 @@ +# Build Metrics + +**Build Metrics** is a catch-all term for performance measures that are +generated by the Firefox build system and tracked by Perfherder. + +## num_constructors + +Number of static constructors found by the compiler in the Firefox C++ +codebase. Lower is better. Static constructors are undesirable because +their initialization imposes an unavoidable time penalty every time +Firefox is started. + +## installer size + +Size in bytes of the Firefox installer. Lower is better here, especially +on space-restricted platforms like Android. + +## build times + +Amount of time it takes to build Firefox in automation on a specific +platform / configuration. Lower is better. + +## compiler warnings + +Number of compiler warnings detected during a build. Lower is better. + +Due to the way the build system works, compiler warnings are not +consistently detected. So the value may fluctuate from build to build +even if the number of compiler warnings didn\'t actually change. Since +Perfherder alerts are calculated based on the mean value of a range, a +regression may be reported as a fractional value. diff --git a/docs/performance/dtrace.md b/docs/performance/dtrace.md new file mode 100644 index 0000000000..68e5114297 --- /dev/null +++ b/docs/performance/dtrace.md @@ -0,0 +1,49 @@ +# dtrace + +`dtrace` is a powerful Mac OS X kernel instrumentation system that can +be used to profile wakeups. This article provides a light introduction +to it. + +::: +**Note**: The [power profiling overview](power_profiling_overview.md) is +worth reading at this point if you haven't already. It may make parts +of this document easier to understand. +::: + +## Invocation + +`dtrace` must be invoked as the super-user. A good starting command for +profiling wakeups is the following. + +``` +sudo dtrace -n 'mach_kernel::wakeup { @[ustack()] = count(); }' -p $FIREFOX_PID > $OUTPUT_FILE +``` + +Let's break that down further. + +- The` -n` option combined with the `mach_kernel::wakeup` selects a + *probe point*. `mach_kernel` is the *module name* and `wakeup` is + the *probe name*. You can see a complete list of probes by running + `sudo dtrace -l`. +- The code between the braces is run when the probe point is hit. The + above code counts unique stack traces when wakeups occur; `ustack` + is short for \"user stack\", i.e. the stack of the userspace program + executing. + +Run that command for a few seconds and then hit [Ctrl]{.kbd} + [C]{.kbd} +to interrupt it. `dtrace` will then print to the output file a number of +stack traces, along with a wakeup count for each one. The ordering of +the stack traces can be non-obvious, so look at them carefully. + +Sometimes the stack trace has less information than one would like. +It's unclear how to improve upon this. + +## See also + +dtrace is *very* powerful, and you can learn more about it by consulting +the following resources: + +- [The DTrace one-liner + tutorial](https://wiki.freebsd.org/DTrace/Tutorial) from FreeBSD. +- [DTrace tools](http://www.brendangregg.com/dtrace.html), by Brendan + Gregg. diff --git a/docs/performance/img/ActMon-Energy.png b/docs/performance/img/ActMon-Energy.png new file mode 100644 index 0000000000..1133ca314b Binary files /dev/null and b/docs/performance/img/ActMon-Energy.png differ diff --git a/docs/performance/img/EJCrt4N.png b/docs/performance/img/EJCrt4N.png new file mode 100644 index 0000000000..5397386f18 Binary files /dev/null and b/docs/performance/img/EJCrt4N.png differ diff --git a/docs/performance/img/PerfDotHTMLRedLines.png b/docs/performance/img/PerfDotHTMLRedLines.png new file mode 100644 index 0000000000..fbedc92b4e Binary files /dev/null and b/docs/performance/img/PerfDotHTMLRedLines.png differ diff --git a/docs/performance/img/annotation.png b/docs/performance/img/annotation.png new file mode 100644 index 0000000000..23655e0594 Binary files /dev/null and b/docs/performance/img/annotation.png differ diff --git a/docs/performance/img/battery-status-menu.png b/docs/performance/img/battery-status-menu.png new file mode 100644 index 0000000000..f8468387b7 Binary files /dev/null and b/docs/performance/img/battery-status-menu.png differ diff --git a/docs/performance/img/dominators-1.png b/docs/performance/img/dominators-1.png new file mode 100644 index 0000000000..163a80016c Binary files /dev/null and b/docs/performance/img/dominators-1.png differ diff --git a/docs/performance/img/dominators-10.png b/docs/performance/img/dominators-10.png new file mode 100644 index 0000000000..e6688060af Binary files /dev/null and b/docs/performance/img/dominators-10.png differ diff --git a/docs/performance/img/dominators-2.png b/docs/performance/img/dominators-2.png new file mode 100644 index 0000000000..99b7db7b09 Binary files /dev/null and b/docs/performance/img/dominators-2.png differ diff --git a/docs/performance/img/dominators-3.png b/docs/performance/img/dominators-3.png new file mode 100644 index 0000000000..2d380f6e21 Binary files /dev/null and b/docs/performance/img/dominators-3.png differ diff --git a/docs/performance/img/dominators-4.png b/docs/performance/img/dominators-4.png new file mode 100644 index 0000000000..d3d5eef59c Binary files /dev/null and b/docs/performance/img/dominators-4.png differ diff --git a/docs/performance/img/dominators-5.png b/docs/performance/img/dominators-5.png new file mode 100644 index 0000000000..41a03488e9 Binary files /dev/null and b/docs/performance/img/dominators-5.png differ diff --git a/docs/performance/img/dominators-6.png b/docs/performance/img/dominators-6.png new file mode 100644 index 0000000000..a3d3026eb2 Binary files /dev/null and b/docs/performance/img/dominators-6.png differ diff --git a/docs/performance/img/dominators-7.png b/docs/performance/img/dominators-7.png new file mode 100644 index 0000000000..160f205391 Binary files /dev/null and b/docs/performance/img/dominators-7.png differ diff --git a/docs/performance/img/dominators-8.png b/docs/performance/img/dominators-8.png new file mode 100644 index 0000000000..e9512b9b05 Binary files /dev/null and b/docs/performance/img/dominators-8.png differ diff --git a/docs/performance/img/dominators-9.png b/docs/performance/img/dominators-9.png new file mode 100644 index 0000000000..af396abc21 Binary files /dev/null and b/docs/performance/img/dominators-9.png differ diff --git a/docs/performance/img/memory-1-small.png b/docs/performance/img/memory-1-small.png new file mode 100644 index 0000000000..a2076330b8 Binary files /dev/null and b/docs/performance/img/memory-1-small.png differ diff --git a/docs/performance/img/memory-2-small.png b/docs/performance/img/memory-2-small.png new file mode 100644 index 0000000000..569b0d9d66 Binary files /dev/null and b/docs/performance/img/memory-2-small.png differ diff --git a/docs/performance/img/memory-3-small.png b/docs/performance/img/memory-3-small.png new file mode 100644 index 0000000000..5d77bd7f60 Binary files /dev/null and b/docs/performance/img/memory-3-small.png differ diff --git a/docs/performance/img/memory-4-small.png b/docs/performance/img/memory-4-small.png new file mode 100644 index 0000000000..9a1e18da6f Binary files /dev/null and b/docs/performance/img/memory-4-small.png differ diff --git a/docs/performance/img/memory-5-small.png b/docs/performance/img/memory-5-small.png new file mode 100644 index 0000000000..e3277186dc Binary files /dev/null and b/docs/performance/img/memory-5-small.png differ diff --git a/docs/performance/img/memory-6-small.png b/docs/performance/img/memory-6-small.png new file mode 100644 index 0000000000..da69b93e51 Binary files /dev/null and b/docs/performance/img/memory-6-small.png differ diff --git a/docs/performance/img/memory-7-small.png b/docs/performance/img/memory-7-small.png new file mode 100644 index 0000000000..844565a8b4 Binary files /dev/null and b/docs/performance/img/memory-7-small.png differ diff --git a/docs/performance/img/memory-graph-dominator-multiple-references.svg b/docs/performance/img/memory-graph-dominator-multiple-references.svg new file mode 100644 index 0000000000..0aaa0546ef --- /dev/null +++ b/docs/performance/img/memory-graph-dominator-multiple-references.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="114 20 158 212" width="158pt" height="212pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" href="#a" gradientTransform="matrix(0 38 -38 0 183 191.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="g" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0H0m0-3l8 3-8 3" fill="none" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="183" cy="210.5" r="19" fill="url(#f)"/><circle cx="183" cy="210.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 201.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="5.016" y="15" textLength="10.368">A</tspan></text><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M148.158 174.206l14.828 15.446"/><text transform="translate(169 26.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".096" y="15" textLength="10.368">A</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="9.28" y="15" textLength="4.448">’</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.544" y="15" textLength="85.36">s dominator</tspan></text><path marker-end="url(#g)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4,4" d="M210.905 50.5l-15.546 32.87"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M217.414 174.275l-14.509 15.272"/></g></svg> diff --git a/docs/performance/img/memory-graph-dominators.svg b/docs/performance/img/memory-graph-dominators.svg new file mode 100644 index 0000000000..0525d0cb5a --- /dev/null +++ b/docs/performance/img/memory-graph-dominators.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="60 57 353 232" width="353pt" height="232pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><linearGradient id="g" href="#a" gradientTransform="rotate(90 41 238.5) scale(38)"/><linearGradient id="h" href="#a" gradientTransform="rotate(90 -8.5 240) scale(38)"/><linearGradient id="i" href="#a" gradientTransform="matrix(0 38 -38 0 327 248.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="j" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0H0m0-3l8 3-8 3" fill="none" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/><circle cx="279.5" cy="216.5" r="19" fill="url(#g)"/><circle cx="279.5" cy="216.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="231.5" cy="267.5" r="19" fill="url(#h)"/><circle cx="231.5" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="327" cy="267.5" r="19" fill="url(#i)"/><circle cx="327" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(316.8 258.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="5.016" y="15" textLength="10.368">A</tspan></text><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M243.012 174.799l17.457 19.951m31.981 35.654l14.853 15.948m-40.825-16.016l-15.171 16.119"/><text transform="translate(301.5 63)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".096" y="15" textLength="10.368">A</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="9.28" y="15" textLength="4.448">’</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.544" y="15" textLength="93.36">s dominators</tspan></text><path marker-end="url(#j)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4,4" d="M296.5 84.682l-85.265 18.644M333.483 87l-79.457 56.709M346.715 87l-53.899 103.845"/></g></svg> diff --git a/docs/performance/img/memory-graph-immediate-dominator.svg b/docs/performance/img/memory-graph-immediate-dominator.svg new file mode 100644 index 0000000000..f88b482820 --- /dev/null +++ b/docs/performance/img/memory-graph-immediate-dominator.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="60 57 350 232" width="350pt" height="232pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><linearGradient id="g" href="#a" gradientTransform="rotate(90 41 238.5) scale(38)"/><linearGradient id="h" href="#a" gradientTransform="rotate(90 -8.5 240) scale(38)"/><linearGradient id="i" href="#a" gradientTransform="matrix(0 38 -38 0 327 248.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="j" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0H0m0-3l8 3-8 3" fill="none" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/><circle cx="279.5" cy="216.5" r="19" fill="url(#g)"/><circle cx="279.5" cy="216.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="231.5" cy="267.5" r="19" fill="url(#h)"/><circle cx="231.5" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="327" cy="267.5" r="19" fill="url(#i)"/><circle cx="327" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(316.8 258.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="5.016" y="15" textLength="10.368">A</tspan></text><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M243.012 174.799l17.457 19.951m31.981 35.654l14.853 15.948m-40.825-16.016l-15.171 16.119"/><text transform="translate(304.5 62)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".2" y="15" textLength="10.368">A</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="9.384" y="15" textLength="4.448">’</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.648" y="15" textLength="87.152">s immediate</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="13.544" y="33" textLength="72.912">dominator</tspan></text><path marker-end="url(#j)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4,4" d="M341.863 103l-48.444 88.167"/></g></svg> diff --git a/docs/performance/img/memory-graph-unreachable.svg b/docs/performance/img/memory-graph-unreachable.svg new file mode 100644 index 0000000000..5bc29d6163 --- /dev/null +++ b/docs/performance/img/memory-graph-unreachable.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="60 88 287 200" width="287pt" height="200pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="c" href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="d" href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="e" href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient x1="0" x2="1" id="b" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f29a8b"/><stop offset="1" stop-color="#f23d1c"/></linearGradient><linearGradient id="f" href="#b" gradientTransform="rotate(90 41 237.5) scale(38)"/><linearGradient id="g" href="#b" gradientTransform="rotate(90 -8.5 239) scale(38)"/><linearGradient id="h" href="#b" gradientTransform="matrix(0 38 -38 0 326 247.5)"/><linearGradient id="j" href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="i" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#c)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#d)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#e)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="278.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="278.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="266.5" r="19" fill="url(#g)"/><circle cx="230.5" cy="266.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="326" cy="266.5" r="19" fill="url(#h)"/><circle cx="326" cy="266.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948m54.675 89.984l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#j)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/></g></svg> diff --git a/docs/performance/img/memory-graph.svg b/docs/performance/img/memory-graph.svg new file mode 100644 index 0000000000..e39168c11c --- /dev/null +++ b/docs/performance/img/memory-graph.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="60 88 288 201" width="384" height="268"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><linearGradient id="g" href="#a" gradientTransform="rotate(90 41 238.5) scale(38)"/><linearGradient id="h" href="#a" gradientTransform="rotate(90 -8.5 240) scale(38)"/><linearGradient id="i" href="#a" gradientTransform="matrix(0 38 -38 0 327 248.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/><circle cx="279.5" cy="216.5" r="19" fill="url(#g)"/><circle cx="279.5" cy="216.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="231.5" cy="267.5" r="19" fill="url(#h)"/><circle cx="231.5" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="327" cy="267.5" r="19" fill="url(#i)"/><circle cx="327" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M243.012 174.799l17.457 19.951m31.981 35.654l14.853 15.948m-40.825-16.016l-15.171 16.119"/></g></svg> diff --git a/docs/performance/img/memory-tool-aggregate-view.png b/docs/performance/img/memory-tool-aggregate-view.png new file mode 100644 index 0000000000..653710979f Binary files /dev/null and b/docs/performance/img/memory-tool-aggregate-view.png differ diff --git a/docs/performance/img/memory-tool-call-stack-expanded.png b/docs/performance/img/memory-tool-call-stack-expanded.png new file mode 100644 index 0000000000..fe2364da58 Binary files /dev/null and b/docs/performance/img/memory-tool-call-stack-expanded.png differ diff --git a/docs/performance/img/memory-tool-call-stack.png b/docs/performance/img/memory-tool-call-stack.png new file mode 100644 index 0000000000..52a96015da Binary files /dev/null and b/docs/performance/img/memory-tool-call-stack.png differ diff --git a/docs/performance/img/memory-tool-in-group-icon.png b/docs/performance/img/memory-tool-in-group-icon.png new file mode 100644 index 0000000000..6354a3d377 Binary files /dev/null and b/docs/performance/img/memory-tool-in-group-icon.png differ diff --git a/docs/performance/img/memory-tool-in-group-retaining-paths.png b/docs/performance/img/memory-tool-in-group-retaining-paths.png new file mode 100644 index 0000000000..191115f041 Binary files /dev/null and b/docs/performance/img/memory-tool-in-group-retaining-paths.png differ diff --git a/docs/performance/img/memory-tool-in-group.png b/docs/performance/img/memory-tool-in-group.png new file mode 100644 index 0000000000..88aac55e9e Binary files /dev/null and b/docs/performance/img/memory-tool-in-group.png differ diff --git a/docs/performance/img/memory-tool-inverted-call-stack.png b/docs/performance/img/memory-tool-inverted-call-stack.png new file mode 100644 index 0000000000..5a951c2e8c Binary files /dev/null and b/docs/performance/img/memory-tool-inverted-call-stack.png differ diff --git a/docs/performance/img/memory-tool-switch-view.png b/docs/performance/img/memory-tool-switch-view.png new file mode 100644 index 0000000000..bb3cb0cdb3 Binary files /dev/null and b/docs/performance/img/memory-tool-switch-view.png differ diff --git a/docs/performance/img/monsters.svg b/docs/performance/img/monsters.svg new file mode 100644 index 0000000000..2f12ef43e8 --- /dev/null +++ b/docs/performance/img/monsters.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="62 78 464 484" width="464pt" height="484pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 103.25 304)"/><linearGradient id="c" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 231.25 136)"/><linearGradient id="d" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 136)"/><linearGradient id="e" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 80)"/><linearGradient id="f" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 192)"/><linearGradient id="g" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 81)"/><linearGradient id="h" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 136)"/><linearGradient id="j" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 231.25 304)"/><linearGradient id="k" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 304)"/><linearGradient id="l" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 248)"/><linearGradient id="m" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 360)"/><linearGradient id="n" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 249)"/><linearGradient id="o" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 304)"/><linearGradient id="p" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 231.25 472)"/><linearGradient id="q" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 472)"/><linearGradient id="r" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 416)"/><linearGradient id="s" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 528)"/><linearGradient id="t" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 417)"/><linearGradient id="u" href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 472)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="i" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker></defs><g fill="none"><path fill="url(#b)" d="M64.5 304H142v31.5H64.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M64.5 304H142v31.5H64.5z"/><text transform="translate(69.5 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="10.038" y="15" textLength="47.424">Object</tspan></text><path fill="url(#c)" d="M192.5 136H270v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M192.5 136H270v31.5h-77.5z"/><text transform="translate(197.5 142.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="14.942" y="15" textLength="37.616">Array</tspan></text><path fill="url(#d)" d="M320.5 136H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 136H398v31.5h-77.5z"/><text transform="translate(325.5 142.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#e)" d="M320.5 80H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 80H398v31.5h-77.5z"/><text transform="translate(325.5 86.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#f)" d="M320.5 192H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 192H398v31.5h-77.5z"/><text transform="translate(325.5 198.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="25.75" y="15" textLength="16">…</tspan></text><path fill="url(#g)" d="M446 81h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 81h77.5v31.5H446z"/><text transform="translate(451 87.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path fill="url(#h)" d="M446 136h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 136h77.5v31.5H446z"/><text transform="translate(451 142.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path d="M103.25 304V151.75h79.35m112.65 0h15.35m-15.35 0v-56h15.35m-40.6 56h25.25v56h15.35m87.4-112l38.101.439M398 151.75h38.1" marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path fill="url(#j)" d="M192.5 304H270v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M192.5 304H270v31.5h-77.5z"/><text transform="translate(197.5 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="14.942" y="15" textLength="37.616">Array</tspan></text><path fill="url(#k)" d="M320.5 304H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 304H398v31.5h-77.5z"/><text transform="translate(325.5 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#l)" d="M320.5 248H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 248H398v31.5h-77.5z"/><text transform="translate(325.5 254.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#m)" d="M320.5 360H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 360H398v31.5h-77.5z"/><text transform="translate(325.5 366.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="25.75" y="15" textLength="16">…</tspan></text><path fill="url(#n)" d="M446 249h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 249h77.5v31.5H446z"/><text transform="translate(451 255.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path fill="url(#o)" d="M446 304h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 304h77.5v31.5H446z"/><text transform="translate(451 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path d="M142 319.75h40.6m112.65 0h15.35m-15.35 0v-56h15.35m-40.6 56h25.25v56h15.35m87.4-112l38.101.439M398 319.75h38.1" marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path fill="url(#p)" d="M192.5 472H270v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M192.5 472H270v31.5h-77.5z"/><text transform="translate(197.5 478.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="14.942" y="15" textLength="37.616">Array</tspan></text><path fill="url(#q)" d="M320.5 472H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 472H398v31.5h-77.5z"/><text transform="translate(325.5 478.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#r)" d="M320.5 416H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 416H398v31.5h-77.5z"/><text transform="translate(325.5 422.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#s)" d="M320.5 528H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 528H398v31.5h-77.5z"/><text transform="translate(325.5 534.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="25.75" y="15" textLength="16">…</tspan></text><path fill="url(#t)" d="M446 417h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 417h77.5v31.5H446z"/><text transform="translate(451 423.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path fill="url(#u)" d="M446 472h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 472h77.5v31.5H446z"/><text transform="translate(451 478.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path d="M103.25 335.5v152.25h79.35m112.65 0h15.35m-15.35 0v-56h15.35m-40.6 56h25.25v56h15.35m87.4-112l38.101.439M398 487.75h38.1" marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/></g></svg> diff --git a/docs/performance/img/pid.png b/docs/performance/img/pid.png new file mode 100644 index 0000000000..bdad5d2cb8 Binary files /dev/null and b/docs/performance/img/pid.png differ diff --git a/docs/performance/img/power-planes.jpg b/docs/performance/img/power-planes.jpg new file mode 100644 index 0000000000..a564fae248 Binary files /dev/null and b/docs/performance/img/power-planes.jpg differ diff --git a/docs/performance/img/rendering.png b/docs/performance/img/rendering.png new file mode 100644 index 0000000000..c4995dbef8 Binary files /dev/null and b/docs/performance/img/rendering.png differ diff --git a/docs/performance/img/reportingperf1.png b/docs/performance/img/reportingperf1.png new file mode 100644 index 0000000000..e2285280af Binary files /dev/null and b/docs/performance/img/reportingperf1.png differ diff --git a/docs/performance/img/reportingperf2.png b/docs/performance/img/reportingperf2.png new file mode 100644 index 0000000000..c43eba2342 Binary files /dev/null and b/docs/performance/img/reportingperf2.png differ diff --git a/docs/performance/img/reportingperf3.png b/docs/performance/img/reportingperf3.png new file mode 100644 index 0000000000..5eb3b58fb7 Binary files /dev/null and b/docs/performance/img/reportingperf3.png differ diff --git a/docs/performance/img/treemap-bbc.png b/docs/performance/img/treemap-bbc.png new file mode 100644 index 0000000000..55552b8382 Binary files /dev/null and b/docs/performance/img/treemap-bbc.png differ diff --git a/docs/performance/img/treemap-domnodes.png b/docs/performance/img/treemap-domnodes.png new file mode 100644 index 0000000000..1192e390da Binary files /dev/null and b/docs/performance/img/treemap-domnodes.png differ diff --git a/docs/performance/img/treemap-monsters.png b/docs/performance/img/treemap-monsters.png new file mode 100644 index 0000000000..513adab923 Binary files /dev/null and b/docs/performance/img/treemap-monsters.png differ diff --git a/docs/performance/index.md b/docs/performance/index.md new file mode 100644 index 0000000000..70e57c89e9 --- /dev/null +++ b/docs/performance/index.md @@ -0,0 +1,53 @@ +# Performance + +This page explains how to optimize the performance of the Firefox code base. + +The [test documentation](/testing/perfdocs/index.rst) +explains how to test for performance in Firefox. +The [profiler documentation](/tools/profiler/index.rst) +explains how to use the Gecko profiler. + +## General Performance references +* Tips on generating valid performance metrics by [benchmarking](Benchmarking.md) +* [GPU Performance](GPU_performance.md) Tips for reducing impacts on browser performance in front-end code. +* [Automated Performance testing and Sheriffing](automated_performance_testing_and_sheriffing.md) Information on automated performance testing and sheriffing at Mozilla. +* [Performance best practices for Firefox front-end engineers](bestpractices.md) Tips for reducing impacts on browser performance in front-end code. +* [Reporting a performance problem](reporting_a_performance_problem.md) A user friendly guide to reporting a performance problem. A development environment is not required. +* [Scroll Linked Effects](scroll-linked_effects.md) Information on scroll-linked effects, their effect on performance, related tools, and possible mitigation techniques. + +## Memory profiling and leak detection tools +* The [Developer Tools Memory panel](memory/memory.md) supports taking heap snapshots, diffing them, computing dominator trees to surface "heavy retainers", and recording allocation stacks. +* [About:memory](memory/about_colon_memory.md) about:memory is the easiest-to-use tool for measuring memory usage in Mozilla code, and is the best place to start. It also lets you do other memory-related operations like trigger GC and CC, dump GC & CC logs, and dump DMD reports. about:memory is built on top of Firefox's memory reporting infrastructure. +* [DMD](memory/dmd.md) is a tool that identifies shortcomings in about:memory's measurements, and can also do multiple kinds of general heap profiling. +* [AWSY](memory/awsy.md) (are we slim yet?) is a memory usage and regression tracker. +* [Bloatview](memory/bloatview.md) prints per-class statistics on allocations and refcounts, and provides gross numbers on the amount of memory being leaked broken down by class. It is used as part of Mozilla's continuous integration testing. +* [Refcount Tracing and Balancing](memory/refcount_tracing_and_balancing.md) are ways to track down leaks caused by incorrect uses of reference counting. They are slow and not particular easy to use, and thus most suitable for use by expert developers. +* [GC and CC Logs](memory/gc_and_cc_logs.md) +* [Leak Gauge](memory/leak_gauge.md) can be generated and analyzed to in various ways. In particular, they can help you understand why a particular object is being kept alive. +* [LogAlloc](https://searchfox.org/mozilla-central/source/memory/replace/logalloc/README) is a tool that dumps a log of memory allocations in Gecko. That log can then be replayed against Firefox's default memory allocator independently or through another replace-malloc library, allowing the testing of other allocators under the exact same workload. +* [See also the documentation on Leak-hunting strategies and tips.](memory/leak_hunting_strategies_and_tips.md) + +## Profiling and performance tools + +* [JIT Profiling with perf](jit_profiling_with_perf.md) Using perf to collect JIT profiles. +* [Profiling with Instruments](profiling_with_instruments.md) How to use Apple's Instruments tool to profile Mozilla code. +* [Profiling with xperf](profiling_with_xperf.md) How to use Microsoft's Xperf tool to profile Mozilla code. +* [Profiling with Concurrency Visualizer](profiling_with_concurrency_visualizer.md) How to use Visual Studio's Concurrency Visualizer tool to profile Mozilla code. +* [Profiling with Zoom](profiling_with_zoom.md) Zoom is a profiler for Linux done by the people who made Shark. +* [Adding a new telemetry probe](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/start/adding-a-new-probe.html) Information on how to add a new measurement to the Telemetry performance-reporting system + +## Power Profiling + +* [An overview of power profiling](power_profiling_overview.md). It includes details about hardware, what can be measured, and recommended approaches. It should be the starting point for anybody new to power profiling. +* **(Mac, Linux)** [tools/power/rapl](tools_power_rapl.md) is a command-line utility in the Mozilla codebase that uses the Intel RAPL interface to gather direct power estimates for the package, cores, GPU and memory. +* **(Mac-only)** [powermetrics](powermetrics.md) is a command-line utility that gathers and displays a wide range of global and per-process measurements, including CPU usage, GPU usage, and various wakeups frequencies. +* **(All-platforms)** [TimerFirings](timerfirings_logging.md) logging is a built-in logging mechanism that prints data on every time fired. +* **(Mac-only)** [Activity Monitor and top](activity_monitor_and_top.md) The battery status menu, Activity Monitor and top are three related Mac tools that have major flaws but often consulted by users, and so are worth understanding. +* **(Windows, Mac and Linux)** [Intel Power Gadget](intel_power_gadget.md) Intel Power Gadget provides real-time graphs for package and processor RAPL estimates. It also provides an API through which those estimates can be obtained. +* **(Linux only)** [perf](perf.md) perf is a powerful command-line utility that can measure many different things, including energy estimates and high-context measurements of things such as wakeups. +* **(Linux-only)** [turbostat](turbostat.md) is a command-line utility that gathers and displays various power-related measurements, with a focus on per-CPU measurements such as frequencies and C-states. +* **(Linux-only)** [powertop](https://01.org/powertop) is an interactive command-line utility that gathers and displays various power-related measurements. + +## Performance Metrics + +* [PerfStats](perfstats.md) - A framework for low-overhead collection of internal performance metrics. diff --git a/docs/performance/intel_power_gadget.md b/docs/performance/intel_power_gadget.md new file mode 100644 index 0000000000..74f7801cff --- /dev/null +++ b/docs/performance/intel_power_gadget.md @@ -0,0 +1,56 @@ +# Intel Power Gadget + +[Intel Power Gadget](https://software.intel.com/en-us/articles/intel-power-gadget/) +provides real-time graphs of various power-related measures and +estimates, all taken from the Intel RAPL MSRs. This article provides a +basic introduction. + +**Note**: The [power profiling +overview](power_profiling_overview.md) is +worth reading at this point if you haven\'t already. It may make parts +of this document easier to understand. + +The main strengths of this tool are (a) it works on Windows, unlike most +other power-related tools, and (b) it shows this data in graph form, +which is occasionally useful. On Mac and Linux, `tools/power/rapl` +[](tools_power_rapl.md) is probably a better tool +to use. + +## Understanding the Power Gadget output + +The following screenshot (from the Mac version) demonstrates the +available measurements. + +![](https://mdn.mozillademos.org/files/11365/Intel-Power-Gadget.png) + +The three panes display the following information: + +- **Power**: Shows power estimates for the package and the cores + (\"IA\"). These are reasonably useful for power profiling purposes, + but Mozilla\'s `rapl` utility provides these along with GPU and RAM + estimates, and in a command-line format that is often easier to use. +- **Frequency**: Shows operating frequency measurements for the cores + (\"IA\") and the GPU (\"GT\"). These measurements aren\'t + particularly useful for power profiling purposes. +- **Temperature**: Shows the package temperature. This is interesting, + but again not useful for power profiling purposes. Specifically, + the temperature is a proxy measurement that is *affected by* + processor power consumption, rather than one that *affects* it, + which makes it even less useful than most proxy measurements. + +Intel Power Gadget can also log these results to a file. This feature +has been used in [energia](https://github.com/mozilla/energia), Roberto +Vitillo\'s tool for systematically measuring differential power usage +between different browsers. (An energia dashboard can be seen +[here](http://people.mozilla.org/~rvitillo/dashboard/); please note that +the data has not been updated since early 2014.) + +Version 3.0 (available on Mac and Windows, but not on Linux) also +exposes an API from which the same measurements can be extracted +programmatically. At one point the Gecko Profiler [used this +API](https://benoitgirard.wordpress.com/2012/06/29/correlating-power-usage-with-performance-data-using-the-gecko-profiler-and-intel-sandy-bridge/) +on Windows to implement experimental package power estimates. +Unfortunately, the Gecko profiler takes 1000 samples per second on +desktop and is CPU intensive and so is likely to skew the RAPL estimates +significantly, so the API integration was removed. The API is otherwise +unlikely to be of interest to Mozilla developers. diff --git a/docs/performance/jit_profiling_with_perf.md b/docs/performance/jit_profiling_with_perf.md new file mode 100644 index 0000000000..81feac2733 --- /dev/null +++ b/docs/performance/jit_profiling_with_perf.md @@ -0,0 +1,119 @@ +# JIT Profiling with perf + +perf is a performance profiling tool available on Linux that is capable of measuring performance events such as cycles, instructions executed, cache misses, etc and providing assembly and source code annotation. +It is possible to collect performance profiles of the SpiderMonkey JIT using perf on Linux and also annotate the generated assembly with the IR opcodes that were used during compilation as shown below. + +![](img/annotation.png) + +## Build setup + +To enable JIT profiling with perf jitdump, you must build Firefox or the JS shell with the following flag: + +``` +ac_add_options --enable-perf +``` + +## Environment Variables + +Environment variables that must be defined for perf JIT profiling: + +`PERF_SPEW_DIR`: Location of jitdump output files. Making this directory a tmpfs filesystem could help reduce overhead.\ +`IONPERF`: Valid options include: `func`, `src`, `ir`, `ir-ops`. + +`IONPERF=func` will disable all annotation and only function names will be available. It is the fastest option.\ +`IONPERF=ir` will enable IR annotation.\ +`IONPERF=ir-ops` will enable IR annotation with operand support. **Requires --enable-jitspew** and adds additional overhead to "ir".\ +`IONPERF=src` will enable source code annotation **only if** perf can read the source file locally. Only really works well in the JS shell. + +## Profiling the JS shell + +Profiling the JS shell requires the following commands but is very straight forward. + +Begin by removing any pre-existing jitdump files: + +`rm -rf output` or `rm -f jitted-*.so jit.data perf.data jit-*.dump jitdump-*.txt` + +Next define environment variables: +``` +export IONPERF=ir +export PERF_SPEW_DIR=output +``` + +Run your test case with perf attached: +``` +perf record -g -k 1 /home/denis/src/mozilla-central/obj-js/dist/bin/js test.js +``` + +Inject the jitdump files into your perf.data file: +``` +perf inject -j -i perf.data -o jit.data +``` + +View the profile: +``` +perf report --no-children --call-graph=graph,0 -i jit.data +``` + +All of the above commands can be put into a single shell script. + +## Profiling the Browser + +Profiling the browser is less straight forward than the shell, but the only main difference is that perf must attach to the content process while it is running. + +Begin by removing any pre-existing jitdump files: + +`rm -rf output` or `rm -f jitted-*.so jit.data perf.data jit-*.dump jitdump-*.txt` + +Next define environment variables: +``` +export IONPERF=ir +export PERF_SPEW_DIR=output +export MOZ_DISABLE_CONTENT_SANDBOX=1 +``` + +Run the Firefox browser +``` +~/mozilla-central/obj-opt64/dist/bin/firefox -no-remote -profile ~/mozilla-central/obj-opt64/tmp/profile-default & +``` + +Navigate to the test case, but do not start it yet. Then hover over the tab to get the content process PID. + +![](img/pid.png) + +Attach perf to begin profiling: +``` +perf record -g -k 1 -p <pid> +``` + +Close the browser when finished benchmarking. + +Inject the jitdump files into your perf.data file: +``` +perf inject -j -i perf.data -o jit.data +``` + +View the profile (--call-graph=graph,0 shows all call stacks instead of the default threshold of >= 0.5%): +``` +perf report --no-children --call-graph=graph,0 -i jit.data +``` + +## Additional Information + +Some Linux distributions offer a "libc6-prof" package that includes frame pointers. This can help resolve symbols and call stacks that involve libc calls. + +On Ubuntu, you can install this with: +``` +sudo apt-get install libc6-prof +``` + +libc6-prof can be used with `LD_LIBRARY_PATH=/lib/libc6-prof/x86_64-linux-gnu` + +It may also be useful to have access to kernel addresses during profiling. These can be exposed with: +``` +sudo sh -c "echo 0 > /proc/sys/kernel/kptr_restrict" +``` + +The max stack depth is 127 by default. This is often too few. It can be increased with: +``` +sudo sh -c "echo 4000 > /proc/sys/kernel/perf_event_max_stack" +``` diff --git a/docs/performance/memory/DOM_allocation_example.md b/docs/performance/memory/DOM_allocation_example.md new file mode 100644 index 0000000000..db9a1f2c71 --- /dev/null +++ b/docs/performance/memory/DOM_allocation_example.md @@ -0,0 +1,57 @@ +# DOM allocation example + +This article describes a very simple web page that we\'ll use to +illustrate some features of the Memory tool. + +You can try out the site at +<https://mdn.github.io/performance-scenarios/dom-allocs/alloc.html>. + +It just contains a script that creates a large number of DOM nodes: + +```js +var toolbarButtonCount = 20; +var toolbarCount = 200; + +function getRandomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function createToolbarButton() { + var toolbarButton = document.createElement("span"); + toolbarButton.classList.add("toolbarbutton"); + // stop Spidermonkey from sharing instances + toolbarButton[getRandomInt(0,5000)] = "foo"; + return toolbarButton; +} + +function createToolbar() { + var toolbar = document.createElement("div"); + // stop Spidermonkey from sharing instances + toolbar[getRandomInt(0,5000)] = "foo"; + for (var i = 0; i < toolbarButtonCount; i++) { + var toolbarButton = createToolbarButton(); + toolbar.appendChild(toolbarButton); + } + return toolbar; +} + +function createToolbars() { + var container = document.getElementById("container"); + for (var i = 0; i < toolbarCount; i++) { + var toolbar = createToolbar(); + container.appendChild(toolbar); + } +} + +createToolbars(); +``` + +A simple pseudocode representation of how this code operates looks like +this: + + createToolbars() + -> createToolbar() // called 200 times, creates 1 DIV element each time + -> createToolbarButton() // called 20 times per toolbar, creates 1 SPAN element each time + +In total, then, it creates 200 `HTMLDivElement` objects, and 4000 +`HTMLSpanElement` objects. diff --git a/docs/performance/memory/about_colon_memory.md b/docs/performance/memory/about_colon_memory.md new file mode 100644 index 0000000000..ab9dc81062 --- /dev/null +++ b/docs/performance/memory/about_colon_memory.md @@ -0,0 +1,274 @@ +# about:memory + +about:memory is a special page within Firefox that lets you view, save, +load, and diff detailed measurements of Firefox's memory usage. It also +lets you do other memory-related operations like trigger GC and CC, dump +GC & CC logs, and dump DMD reports. It is present in all builds and does +not require any preparation to be used. + +## How to generate memory reports + +Let's assume that you want to measure Firefox's memory usage. Perhaps +you want to investigate it yourself, or perhaps someone has asked you to +use about:memory to generate "memory reports" so they can investigate +a problem you are having. Follow these steps. + +- At the moment of interest (e.g. once Firefox's memory usage has + gotten high) open a new tab and type "about:memory" into the + address bar and hit "Enter". +- If you are using a communication channel where files can be sent, + such as Bugzilla or email, click on the "Measure and save..." + button. This will open a file dialog that lets you save the memory + reports to a file of your choosing. (The filename will have a + `.json.gz` suffix.) You can then attach or upload the file + appropriately. The recipients will be able to view the contents of + this file within about:memory in their own Firefox instance. +- If you are using a communication channel where only text can be + sent, such as a comment thread on a website, click on the + "Measure..." button. This will cause a tree-like structure to be + generated text within about:memory. This structure is just text, so + you can copy and paste some or all of this text into any kind of + text buffer. (You don't need to take a screenshot.) This text + contains fewer measurements than a memory reports file, but is often + good enough to diagnose problems. Don't click "Measure..." + repeatedly, because that will cause the memory usage of about:memory + itself to rise, due to it discarding and regenerating large numbers + of DOM nodes. + +Note that in both cases the generated data contains privacy-sensitive +details such as the full list of the web pages you have open in other +tabs. If you do not wish to share this information, you can select the +"anonymize" checkbox before clicking on "Measure and save..." or +"Measure...". This will cause the privacy-sensitive data to be +stripped out, but it may also make it harder for others to investigate +the memory usage. + +## Loading memory reports from file + +The easiest way to load memory reports from file is to use the +"Load..." button. You can also use the "Load and diff..." button +to get the difference between two memory report files. + +Single memory report files can also be loaded automatically when +about:memory is loaded by appending a `file` query string, for example: + + about:memory?file=/home/username/reports.json.gz + +This is most useful when loading memory reports files obtained from a +Firefox OS device. + +Memory reports are saved to file as gzipped JSON. These files can be +loaded as is, but they can also be loaded after unzipping. + +## Interpreting memory reports + +Almost everything you see in about:memory has an explanatory tool-tip. +Hover over any button to see a description of what it does. Hover over +any measurement to see a description of what it means. + +### [Measurement basics] + +Most measurements use bytes as their unit, but some are counts or +percentages. + +Most measurements are presented within trees. For example: + + 585 (100.0%) -- preference-service + └──585 (100.0%) -- referent + ├──493 (84.27%) ── strong + └───92 (15.73%) -- weak + ├──92 (15.73%) ── alive + └───0 (00.00%) ── dead + +Leaf nodes represent actual measurements; the value of each internal +node is the sum of all its children. + +The use of trees allows measurements to be broken down into further +categories, sub-categories, sub-sub-categories, etc., to arbitrary +depth, as needed. All the measurements within a single tree are +non-overlapping. + +Tree paths can be written using \'/\' as a separator. For example, +`preference/referent/weak/dead` represents the path to the final leaf +node in the example tree above. + +Sub-trees can be collapsed or expanded by clicking on them. If you find +any particular tree overwhelming, it can be helpful to collapse all the +sub-trees immediately below the root, and then gradually expand the +sub-trees of interest. + +### [Sections] + +Memory reports are displayed on a per-process basis, with one process +per section. Within each process's measurements, there are the +following subsections. + +#### Explicit Allocations + +This section contains a single tree, called "explicit", that measures +all the memory allocated via explicit calls to heap allocation functions +(such as `malloc` and `new`) and to non-heap allocations functions (such +as `mmap` and `VirtualAlloc`). + +Here is an example for a browser session where tabs were open to +cnn.com, techcrunch.com, and arstechnica.com. Various sub-trees have +been expanded and others collapsed for the sake of presentation. + + 191.89 MB (100.0%) -- explicit + ├───63.15 MB (32.91%) -- window-objects + │ ├──24.57 MB (12.80%) -- top(http://edition.cnn.com/, id=8) + │ │ ├──20.18 MB (10.52%) -- active + │ │ │ ├──10.57 MB (05.51%) -- window(http://edition.cnn.com/) + │ │ │ │ ├───4.55 MB (02.37%) ++ js-compartment(http://edition.cnn.com/) + │ │ │ │ ├───2.60 MB (01.36%) ++ layout + │ │ │ │ ├───1.94 MB (01.01%) ── style-sheets + │ │ │ │ └───1.48 MB (00.77%) -- (2 tiny) + │ │ │ │ ├──1.43 MB (00.75%) ++ dom + │ │ │ │ └──0.05 MB (00.02%) ── property-tables + │ │ │ └───9.61 MB (05.01%) ++ (18 tiny) + │ │ └───4.39 MB (02.29%) -- js-zone(0x7f69425b5800) + │ ├──15.75 MB (08.21%) ++ top(http://techcrunch.com/, id=20) + │ ├──12.85 MB (06.69%) ++ top(http://arstechnica.com/, id=14) + │ ├───6.40 MB (03.33%) ++ top(chrome://browser/content/browser.xul, id=3) + │ └───3.59 MB (01.87%) ++ (4 tiny) + ├───45.74 MB (23.84%) ++ js-non-window + ├───33.73 MB (17.58%) ── heap-unclassified + ├───22.51 MB (11.73%) ++ heap-overhead + ├────6.62 MB (03.45%) ++ images + ├────5.82 MB (03.03%) ++ workers/workers(chrome) + ├────5.36 MB (02.80%) ++ (16 tiny) + ├────4.07 MB (02.12%) ++ storage + ├────2.74 MB (01.43%) ++ startup-cache + └────2.16 MB (01.12%) ++ xpconnect + +Some expertise is required to understand the full details here, but +there are various things worth pointing out. + +- This "explicit" value at the root of the tree represents all the + memory allocated via explicit calls to allocation functions. +- The "window-objects" sub-tree represents all JavaScript `window` + objects, which includes the browser tabs and UI windows. For + example, the "top(http://edition.cnn.com/, id=8)" sub-tree + represents the tab open to cnn.com, and + "top(chrome://browser/content/browser.xul, id=3)" represents the + main browser UI window. +- Within each window's measurements are sub-trees for JavaScript + ("js-compartment(...)" and "js-zone(...)"), layout, + style-sheets, the DOM, and other things. +- It's clear that the cnn.com tab is using more memory than the + techcrunch.com tab, which is using more than the arstechnica.com + tab. +- Sub-trees with names like "(2 tiny)" are artificial nodes inserted + to allow insignificant sub-trees to be collapsed by default. If you + select the "verbose" checkbox before measuring, all trees will be + shown fully expanded and no artificial nodes will be inserted. +- The "js-non-window" sub-tree represents JavaScript memory usage + that doesn't come from windows, but from the browser core. +- The "heap-unclassified" value represents heap-allocated memory + that is not measured by any memory reporter. This is typically + 10--20% of "explicit". If it gets higher, it indicates that + additional memory reporters should be added. + [DMD](./dmd.md) + can be used to determine where these memory reporters should be + added. +- There are measurements for other content such as images and workers, + and for browser subsystems such as the startup cache and XPConnect. + +Some add-on memory usage is identified, as the following example shows. + + ├───40,214,384 B (04.17%) -- add-ons + │ ├──21,184,320 B (02.20%) ++ {d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}/js-non-window/zones/zone(0x100496800)/compartment([System Principal], jar:file:///Users/njn/Library/Application%20Support/Firefox/Profiles/puna0zr8.new/extensions/%7Bd10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d%7D.xpi!/bootstrap.js (from: resource://gre/modules/addons/XPIProvider.jsm:4307)) + │ ├──11,583,312 B (01.20%) ++ jid1-xUfzOsOFlzSOXg@jetpack/js-non-window/zones/zone(0x100496800) + │ ├───5,574,608 B (00.58%) -- {59c81df5-4b7a-477b-912d-4e0fdf64e5f2} + │ │ ├──5,529,280 B (00.57%) -- window-objects + │ │ │ ├──4,175,584 B (00.43%) ++ top(chrome://chatzilla/content/chatzilla.xul, id=4293) + │ │ │ └──1,353,696 B (00.14%) ++ top(chrome://chatzilla/content/output-window.html, id=4298) + │ │ └─────45,328 B (00.00%) ++ js-non-window/zones/zone(0x100496800)/compartment([System Principal], file:///Users/njn/Library/Application%20Support/Firefox/Profiles/puna0zr8.new/extensions/%7B59c81df5-4b7a-477b-912d-4e0fdf64e5f2%7D/components/chatzilla-service.js) + │ └───1,872,144 B (00.19%) ++ treestyletab@piro.sakura.ne.jp/js-non-window/zones/zone(0x100496800) + +More things worth pointing out are as follows. + +- Some add-ons are identified by a name, such as Tree Style Tab. + Others are identified only by a hexadecimal identifier. You can look + in about:support to see which add-on a particular identifier belongs + to. For example, `59c81df5-4b7a-477b-912d-4e0fdf64e5f2` is + Chatzilla. +- All JavaScript memory usage for an add-on is measured separately and + shown in this sub-tree. +- For add-ons that use separate windows, such as Chatzilla, the memory + usage of those windows will show up in this sub-tree. +- For add-ons that use XUL overlays, such as AdBlock Plus, the memory + usage of those overlays will not show up in this sub-tree; it will + instead be in the non-add-on sub-trees and won't be identifiable as + being caused by the add-on. + +#### Other Measurements + +This section contains multiple trees, includes many that cross-cut the +measurements in the "explicit" tree. For example, in the "explicit" +tree all DOM and layout measurements are broken down by window by +window, but in "Other Measurements" those measurements are aggregated +into totals for the whole browser, as the following example shows. + + 26.77 MB (100.0%) -- window-objects + ├──14.59 MB (54.52%) -- layout + │ ├───6.22 MB (23.24%) ── style-sets + │ ├───4.00 MB (14.95%) ── pres-shell + │ ├───1.79 MB (06.68%) ── frames + │ ├───0.89 MB (03.33%) ── style-contexts + │ ├───0.62 MB (02.33%) ── rule-nodes + │ ├───0.56 MB (02.10%) ── pres-contexts + │ ├───0.47 MB (01.75%) ── line-boxes + │ └───0.04 MB (00.14%) ── text-runs + ├───6.53 MB (24.39%) ── style-sheets + ├───5.59 MB (20.89%) -- dom + │ ├──3.39 MB (12.66%) ── element-nodes + │ ├──1.56 MB (05.84%) ── text-nodes + │ ├──0.54 MB (02.03%) ── other + │ └──0.10 MB (00.36%) ++ (4 tiny) + └───0.06 MB (00.21%) ── property-tables + +Some of the trees in this section measure things that do not cross-cut +the measurements in the "explicit" tree, such as those in the +"preference-service" example above. + +Finally, at the end of this section are individual measurements, as the +following example shows. + + 0.00 MB ── canvas-2d-pixels + 5.38 MB ── gfx-surface-xlib + 0.00 MB ── gfx-textures + 0.00 MB ── gfx-tiles-waste + 0 ── ghost-windows + 109.22 MB ── heap-allocated + 164 ── heap-chunks + 1.00 MB ── heap-chunksize + 114.51 MB ── heap-committed + 164.00 MB ── heap-mapped + 4.84% ── heap-overhead-ratio + 1 ── host-object-urls + 0.00 MB ── imagelib-surface-cache + 5.27 MB ── js-main-runtime-temporary-peak + 0 ── page-faults-hard + 203,349 ── page-faults-soft + 274.99 MB ── resident + 251.47 MB ── resident-unique + 1,103.64 MB ── vsize + +Some measurements of note are as follows. + +- "resident". Physical memory usage. If you want a single + measurement to summarize memory usage, this is probably the best + one. +- "vsize". Virtual memory usage. This is often much higher than any + other measurement (particularly on Mac). It only really matters on + 32-bit platforms such as Win32. There is also + "vsize-max-contiguous" (not measured on all platforms, and not + shown in this example), which indicates the largest single chunk of + available virtual address space. If this number is low, it's likely + that memory allocations will fail due to lack of virtual address + space quite soon. +- Various graphics-related measurements ("gfx-*"). The measurements + taken vary between platforms. Graphics is often a source of high + memory usage, and so these measurements can be helpful for detecting + such cases. diff --git a/docs/performance/memory/aggregate_view.md b/docs/performance/memory/aggregate_view.md new file mode 100644 index 0000000000..9a4f01e01e --- /dev/null +++ b/docs/performance/memory/aggregate_view.md @@ -0,0 +1,198 @@ +# Aggregate view + +Before Firefox 48, this was the default view of a heap snapshot. After +Firefox 48, the default view is the [Tree map +view](tree_map_view.md), and you can switch to the +Aggregate view using the dropdown labeled \"View:\": + +![](../img/memory-tool-switch-view.png) + +The Aggregate view looks something like this: + +![](../img/memory-tool-aggregate-view.png) + +It presents a breakdown of the heap\'s contents, as a table. There are +three main ways to group the data: + +- Type +- Call Stack +- Inverted Call Stack + +You can switch between them using the dropdown menu labeled \"Group +by:\" located at the top of the panel: + +There\'s also a box labeled \"Filter\" at the top-right of the pane. You +can use this to filter the contents of the snapshot that are displayed, +so you can quickly see, for example, how many objects of a specific +class were allocated. + +## Type + +This is the default view, which looks something like this: + +![](../img/memory-tool-aggregate-view.png) + +It groups the things on the heap into types, including: + +- **JavaScript objects:** such as `Function` or `Array` +- **DOM elements:** such as `HTMLSpanElement` or `Window` +- **Strings:** listed as `"strings"` +- **JavaScript sources:** listed as \"`JSScript"` +- **Internal objects:** such as \"`js::Shape`\". These are prefixed + with `"js::"`. + +Each type gets a row in the table, and rows are ordered by the amount of +memory occupied by objects of that type. For example, in the screenshot +above you can see that JavaScript `Object`s account for most memory, +followed by strings. + +- The \"Total Count\" column shows you the number of objects of each + category that are currently allocated. +- The \"Total Bytes\" column shows you the number of bytes occupied by + objects in each category, and that number as a percentage of the + whole heap size for that tab. + +The screenshots in this section are taken from a snapshot of the +[monster example page](monster_example.md). + +For example, in the screenshot above, you can see that: + +- there are four `Array` objects +- that account for 15% of the total heap. + +Next to the type\'s name, there\'s an icon that contains three stars +arranged in a triangle: + +![](../img/memory-tool-in-group-icon.png) + +Click this to see every instance of that type. For example, the entry +for `Array` tells us that there are four `Array` objects in the +snapshot. If we click the star-triangle, we\'ll see all four `Array` +instances: + +![](../img/memory-tool-in-group.png) + +For each instance, you can see the [retained size and shallow +size](dominators.md#shallow_and_retained_size) of +that instance. In this case, you can see that the first three arrays +have a fairly large shallow size (5% of the total heap usage) and a much +larger retained size (26% of the total). + +On the right-hand side is a pane that just says \"Select an item to view +its retaining paths\". If you select an item, you\'ll see the [Retaining +paths +panel](dominators_view.md#retaining_paths_panel) +for that item: + +![](../img/memory-tool-in-group-retaining-paths.png) + +<iframe width="595" height="325" src="https://www.youtube.com/embed/uLjzrvx_VCg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + + +## Call Stack + +The Call Stack shows you exactly where in your code you are making heap +allocations. + +Because tracing allocations has a runtime cost, it must be explicitly +enabled by checking \"Record call stacks\" *before* you allocate the +memory in the snapshot. + +You\'ll then see a list of all the functions that allocated objects, +ordered by the size of the allocations they made: + +![](../img/memory-tool-call-stack.png) +\ +The first entry says that: + +- 4,832,592 bytes, comprising 93% of the total heap usage, were + allocated in a function at line 35 of \"alloc.js\", **or in + functions called by that function** + +We can use the disclosure triangle to drill down the call tree, to find +the exact place your code made those allocations. + +It\'s easier to explain this with reference to a simple example. For +this we\'ll use the [DOM allocation +example](DOM_allocation_example.md). This page +runs a script that creates a large number of DOM nodes (200 +`HTMLDivElement` objects and 4000 `HTMLSpanElement` objects). + +Let\'s get an allocation trace: + +1. open the Memory tool +2. check \"Record call stacks\" +3. load + <https://mdn.github.io/performance-scenarios/dom-allocs/alloc.html> +4. take a snapshot +5. select \"View/Aggregate\" +6. select \"Group by/Call Stack\" + +<iframe width="595" height="325" src="https://www.youtube.com/embed/DyLulu9eoKY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + +You should see something like this: + +![](../img/memory-tool-call-stack.png) + +This is telling us that 93% of the total heap snapshot was allocated in +functions called from \"alloc.js\", line 35 (our initial +`createToolbars()` call). + +We can use the disclosure arrow to expand the tree to find out exactly +where we\'re allocating memory: + +![](../img/memory-tool-call-stack-expanded.png) + +This is where the \"Bytes\" and \"Count\" columns are useful: they show +allocation size and number of allocations at that exact point. + +So in the example above, we can see that we made 4002 allocations, +accounting for 89% of the total heap, in `createToolbarButton()`, at +[alloc.js line 9, position +23](https://github.com/mdn/performance-scenarios/blob/gh-pages/dom-allocs/scripts/alloc.js#L9): +that is, the exact point where we create the span +elements. + +The file name and line number is a link: if we click it, we go directly +to that line in the debugger: + +<iframe width="595" height="325" src="https://www.youtube.com/embed/zlnJcr1IFyY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + + +## Inverted Call Stack + +The Call Stack view is top-down: it shows allocations that happen at +that point **or points deeper in the call tree**. So it\'s good for +getting an overview of where your program is memory-hungry. However, +this view means you have to drill a long way down to find the exact +place where the allocations are happening. + +The \"Inverted Call Stack\" view helps with that. It gives you the +bottom-up view of the program showing the exact places where allocations +are happening, ranked by the size of allocation at each place. The +disclosure arrow then walks you back up the call tree towards the top +level. + +Let\'s see what the example looks like when we select \"Inverted Call +Stack\": + +![](../img/memory-tool-inverted-call-stack.png) + +Now at the top we can immediately see the `createToolbarButton()` call +accounting for 89% of the heap usage in our page. + +## no stack available + +In the example above you\'ll note that 7% of the heap is marked \"(no +stack available)\". This is because not all heap usage results from your +JavaScript. + +For example: + +- any scripts the page loads occupy heap space +- sometimes an object is allocated when there is no JavaScript on the + stack. For example, DOM Event objects are allocated + before the JavaScript is run and event handlers are called. + +Many real-world pages will have a much higher \"(no stack available)\" +share than 7%. diff --git a/docs/performance/memory/awsy.md b/docs/performance/memory/awsy.md new file mode 100644 index 0000000000..5026f055aa --- /dev/null +++ b/docs/performance/memory/awsy.md @@ -0,0 +1,22 @@ +# Are We Slim Yet (AWSY) + +The Are We Slim Yet project (commonly known as AWSY) for several years +tracked memory usage across builds on the (now defunct) website. +It used the same +infrastructure as +[about:memory](about_colon_memory.md) to measure +memory usage on a predefined snapshot of Alexa top 100 pages known as +tp5. + +Since Firefox transitioned to using multiple processes by default, we +[moved AWSY into the +TaskCluster](https://bugzilla.mozilla.org/show_bug.cgi?id=1272113) +infrastructure. This allowed us to run measurements on all branches and +platforms. The results are posted to +[perfherder](https://treeherder.mozilla.org/perf.html) where we can +track regressions automatically. + +As new processes are added to Firefox we want to make sure their memory +usage is also tracked by AWSY. To this end we request that memory +reporting be integrated into any new process before it is enabled on +Nightly. diff --git a/docs/performance/memory/basic_operations.md b/docs/performance/memory/basic_operations.md new file mode 100644 index 0000000000..276c38bc2e --- /dev/null +++ b/docs/performance/memory/basic_operations.md @@ -0,0 +1,82 @@ +# Basic operations + +## Opening the Memory tool + +Before Firefox 50, the Memory tool is not enabled by default. To enable +it, open the developer tool settings, and check the "Memory" box under +"Default Firefox Developer Tools": + +<iframe width="595" height="325" src="https://www.youtube.com/embed/qi-0CoCOXw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + +From Firefox 50 onwards, the Memory tool is enabled by default. + +## Taking a heap snapshot + +To take a snapshot of the heap, click the "Take snapshot" button, or +the camera icon on the left: + +![memoryimage1](../img/memory-1-small.png) + +The snapshot will occupy the large pane on the right-hand side. On the +left, you'll see an entry for the new snapshot, including its +timestamp, size, and controls to save or clear this snapshot: + +![memoryimage2](../img/memory-2-small.png) + +## Clearing a snapshot + +To remove a snapshot, click the "X" icon: + +![memoryimage3](../img/memory-3-small.png) + +## Saving and loading snapshots + +If you close the Memory tool, all unsaved snapshots will be discarded. +To save a snapshot click "Save": + +![memoryimage4](../img/memory-4-small.png) + +You'll be prompted for a name and location, and the file will be saved +with an `.fxsnapshot` extension. + +To load a snapshot from an existing `.fxsnapshot` file, click the import +button, which looks like a rectangle with an arrow rising from it +(before Firefox 49, this button was labeled with the text +"Import\...\"): + +![memoryimage5](../img/memory-5-small.png) + +You'll be prompted to find a snapshot file on disk. + +## Comparing snapshots + +Starting in Firefox 45, you can diff two heap snapshots. The diff shows +you where memory was allocated or freed between the two snapshots. + +To create a diff, click the button that looks like a Venn diagram next +to the camera icon (before Firefox 47, this looked like a \"+/-\" icon): + +![memoryimage6](../img/memory-6-small.png) + +You'll be prompted to select the snapshot to use as a baseline, then +the snapshot to compare. The tool then shows you the differences between +the two snapshots: + +<iframe width="595" height="325" src="https://www.youtube.com/embed/3Ow-mdK6b2M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + + +::: {.note} +When you're looking at a comparison, you can't use the Dominators view +or the Tree Map view. +::: + +## Recording call stacks + +The Memory tool can tell you exactly where in your code you are +allocating memory. However, recording this information has a run-time +cost, so you must ask the tool to record memory calls *before* the +memory is allocated, if you want to see memory call sites in the +snapshot. To do this, check "Record call stacks" (before Firefox 49 +this was labeled "Record allocation stacks"): + +![memoryimage7](../img/memory-7-small.png) diff --git a/docs/performance/memory/bloatview.md b/docs/performance/memory/bloatview.md new file mode 100644 index 0000000000..9e290011b1 --- /dev/null +++ b/docs/performance/memory/bloatview.md @@ -0,0 +1,245 @@ +# Bloatview + +BloatView is a tool that shows information about cumulative memory usage +and leaks. If it finds leaks, you can use [refcount tracing and balancing](refcount_tracing_and_balancing.md) +to discover the root cause. + +## How to build with BloatView + +Build with `--enable-debug` or `--enable-logrefcnt`. + +## How to run with BloatView + +The are two environment variables that can be used. + + XPCOM_MEM_BLOAT_LOG + +If set, this causes a *bloat log* to be printed on program exit, and +each time `nsTraceRefcnt::DumpStatistics` is called. This log contains +data on leaks and bloat (a.k.a. usage). + + XPCOM_MEM_LEAK_LOG + +This is similar to `XPCOM_MEM_BLOAT_LOG`, but restricts the log to only +show data on leaks. + +You can set these environment variables to any of the following values. + +- **1** - log to stdout. +- **2** - log to stderr. +- ***filename*** - write log to a file. + +## Reading individual bloat logs + +Full BloatView output contains per-class statistics on allocations and +refcounts, and provides gross numbers on the amount of memory being +leaked broken down by class. Here's a sample of the BloatView output. + + == BloatView: ALL (cumulative) LEAK AND BLOAT STATISTICS, tab process 1862 + |<----------------Class--------------->|<-----Bytes------>|<----Objects---->| + | | Per-Inst Leaked| Total Rem| + 0 |TOTAL | 17 2484|253953338 38| + 17 |AsyncTransactionTrackersHolder | 40 40| 10594 1| + 78 |CompositorChild | 472 472| 1 1| + 79 |CondVar | 24 48| 3086 2| + 279 |MessagePump | 8 8| 30 1| + 285 |Mutex | 20 60| 89987 3| + 302 |PCompositorChild | 412 412| 1 1| + 308 |PImageBridgeChild | 416 416| 1 1| + +The first line tells you the pid of the leaking process, along with the +type of process. + +Here's how you interpret the columns. + +- The first, numerical column [is the index](https://searchfox.org/mozilla-central/source/xpcom/base/nsTraceRefcnt.cpp#365) + of the leaking class. +- **Class** - The name of the class in question (truncated to 20 + characters). +- **Bytes Per-Inst** - The number of bytes returned if you were to + write `sizeof(Class)`. Note that this number does not reflect any + memory held onto by the class, such as internal buffers, etc. (E.g. + for `nsString` you'll see the size of the header struct, not the + size of the string contents!) +- **Bytes Leaked** - The number of bytes per instance times the number + of objects leaked: (Bytes Per-Inst) x (Objects Rem). Use this number + to look for the worst offenders. (Should be zero!) +- **Objects Total** - The total count of objects allocated of a given + class. +- **Objects Rem** - The number of objects allocated of a given class + that weren't deleted. (Should be zero!) + +Interesting things to look for: + +- **Are your classes in the list?** - Look! If they aren't, then + you're not using the `NS_IMPL_ADDREF` and `NS_IMPL_RELEASE` (or + `NS_IMPL_ISUPPORTS` which calls them) for xpcom objects, or + `MOZ_COUNT_CTOR` and `MOZ_COUNT_DTOR` for non-xpcom objects. Not + having your classes in the list is *not* ok. That means no one is + looking at them, and we won't be able to tell if someone introduces + a leak. (See + [below](#how-to-instrument-your-objects-for-bloatview) + for how to fix this.) +- **The Bytes Leaked for your classes should be zero!** - Need I say + more? If it isn't, you should use the other tools to fix it. +- **The number of objects remaining might not be equal to the total + number of objects.** This could indicate a hand-written Release + method (that doesn't use the `NS_LOG_RELEASE` macro from + nsTraceRefcnt.h), or perhaps you're just not freeing any of the + instances you've allocated. These sorts of leaks are easy to fix. +- **The total number of objects might be 1.** This might indicate a + global variable or service. Usually this will have a large number of + refcounts. + +If you find leaks, you can use [refcount tracing and balancing](refcount_tracing_and_balancing.md) +to discover the root cause. + +## Combining and sorting bloat logs + +You can view one or more bloat logs in your browser by running the +following program. + + perl tools/bloatview/bloattable.pl *log1* *log2* \... *logn* > + *htmlfile* + +This will produce an HTML file that contains a table similar to the +following (but with added JavaScript so you can sort the data by +column). + + Byte Bloats + + ---------- ---------------- -------------------------- + Name File Date + blank `blank.txt` Tue Aug 29 14:17:40 2000 + mozilla `mozilla.txt` Tue Aug 29 14:18:42 2000 + yahoo `yahoo.txt` Tue Aug 29 14:19:32 2000 + netscape `netscape.txt` Tue Aug 29 14:20:14 2000 + ---------- ---------------- -------------------------- + +The numbers do not include malloc'd data such as string contents. + +Click on a column heading to sort by that column. Click on a class name +to see details for that class. + + -------------------- --------------- ----------------- --------- --------- ---------- ---------- ------------------------------- --------- -------- ---------- --------- + Class Name Instance Size Bytes allocated Bytes allocated but not freed + blank mozilla yahoo netscape Total blank mozilla yahoo netscape Total + TOTAL 1754408 432556 179828 404184 2770976 + nsStr 20 6261600 3781900 1120920 1791340 12955760 222760 48760 13280 76160 360960 + nsHashKey 8 610568 1842400 2457872 1134592 6045432 32000 536 568 1216 34320 + nsTextTransformer 548 8220 469088 1414936 1532756 3425000 0 0 0 0 0 + nsStyleContextData 736 259808 325312 489440 338560 1413120 141312 220800 -11040 94944 446016 + nsLineLayout 1100 2200 225500 402600 562100 1192400 0 0 0 0 0 + nsLocalFile 424 558832 19928 1696 1272 581728 72080 1272 424 -424 73352 + -------------------- --------------- ----------------- --------- --------- ---------- ---------- ------------------------------- --------- -------- ---------- --------- + +The first set of columns, **Bytes allocated**, shows the amount of +memory allocated for the first log file (`blank.txt`), the difference +between the first log file and the second (`mozilla.txt`), the +difference between the second log file and the third (`yahoo.txt`), the +difference between the third log file and the fourth (`netscape.txt`), +and the total amount of memory allocated in the fourth log file. These +columns provide an idea of how hard the memory allocator has to work, +but they do not indicate the size of the working set. + +The second set of columns, **Bytes allocated but not freed**, shows the +net memory gain or loss by subtracting the amount of memory freed from +the amount allocated. + +The **Show Objects** and **Show References** buttons show the same +statistics but counting objects or `AddRef`'d references rather than +bytes. + +## Comparing Bloat Logs + +You can also compare any two bloat logs (either those produced when the +program shuts down, or written to the bloatlogs directory) by running +the following program. + + `perl tools/bloatview/bloatdiff.pl` <previous-log> <current-log> + +This will give you output of the form: + + Bloat/Leak Delta Report + Current file: dist/win32_D.OBJ/bin/bloatlogs/all-1999-10-22-133450.txt + Previous file: dist/win32_D.OBJ/bin/bloatlogs/all-1999-10-16-010302.txt + -------------------------------------------------------------------------- + CLASS LEAKS delta BLOAT delta + -------------------------------------------------------------------------- + TOTAL 6113530 2.79% 67064808 9.18% + StyleContextImpl 265440 81.19% 283584 -26.99% + CToken 236500 17.32% 306676 20.64% + nsStr 217760 14.94% 5817060 7.63% + nsXULAttribute 113048 -70.92% 113568 -71.16% + LiteralImpl 53280 26.62% 75840 19.40% + nsXULElement 51648 0.00% 51648 0.00% + nsProfile 51224 0.00% 51224 0.00% + nsFrame 47568 -26.15% 48096 -50.49% + CSSDeclarationImpl 42984 0.67% 43488 0.67% + +This "delta report" shows the leak offenders, sorted from most leaks +to fewest. The delta numbers show the percentage change between runs for +the amount of leaks and amount of bloat (negative numbers are better!). +The bloat number is a metric determined by multiplying the total number +of objects allocated of a given class by the class size. Note that +although this isn't necessarily the amount of memory consumed at any +given time, it does give an indication of how much memory we're +consuming. The more memory in general, the worse the performance and +footprint. The percentage 99999.99% will show up indicating an +"infinite" amount of leakage. This happens when something that didn't +leak before is now leaking. + +## BloatView and continuous integration + +BloatView runs on debug builds for many of the test suites Mozilla has +running under continuous integration. If a new leak occurs, it will +trigger a test job failure. + +BloatView's output file can also show you where the leaked objects are +allocated. To do so, the `XPCOM_MEM_LOG_CLASSES` environment variable +should be set to the name of the class from the BloatView table: + + XPCOM_MEM_LOG_CLASSES=MyClass mach mochitest [options] + +Multiple class names can be specified by setting `XPCOM_MEM_LOG_CLASSES` +to a comma-separated list of names: + + XPCOM_MEM_LOG_CLASSES=MyClass,MyOtherClass,DeliberatelyLeakedClass mach mochitest [options] + +Test harness scripts typically accept a `--setenv` option for specifying +environment variables, which may be more convenient in some cases: + + mach mochitest --setenv=XPCOM_MEM_LOG_CLASSES=MyClass [options] + +For getting allocation stacks in automation, you can add the appropriate +`--setenv` options to the test configurations for the platforms you're +interested in. Those configurations are located in +`testing/mozharness/configs/`. The most likely configs you'll want to +modify are listed below: + +- Linux: `unittests/linux_unittest.py` +- Mac: `unittests/mac_unittest.py` +- Windows: `unittests/win_unittest.py` +- Android: `android/androidarm.py` + +## How to instrument your objects for BloatView + +First, if your object is an xpcom object and you use the +`NS_IMPL_ADDREF` and `NS_IMPL_RELEASE` (or a variation thereof) macro to +implement your `AddRef` and `Release` methods, then there is nothing you +need do. By default, those macros support refcnt logging directly. + +If your object is not an xpcom object then some manual editing is in +order. The following sample code shows what must be done: + + MyType::MyType() + { + MOZ_COUNT_CTOR(MyType); + ... + } + + MyType::~MyType() + { + MOZ_COUNT_DTOR(MyType); + ... + } diff --git a/docs/performance/memory/dmd.md b/docs/performance/memory/dmd.md new file mode 100644 index 0000000000..ebd6b5a2f8 --- /dev/null +++ b/docs/performance/memory/dmd.md @@ -0,0 +1,489 @@ +# Dark Matter Detector (DMD) + +DMD (short for "dark matter detector") is a heap profiler within +Firefox. It has four modes. + +- "Dark Matter" mode. In this mode, DMD tracks the contents of the + heap, including which heap blocks have been reported by memory + reporters. It helps us reduce the "heap-unclassified" value in + Firefox's about:memory page, and also detects if any heap blocks + are reported twice. Originally, this was the only mode that DMD had, + which explains DMD's name. This is the default mode. +- "Live" mode. In this mode, DMD tracks the current contents of the + heap. You can dump that information to file, giving a profile of the + live heap blocks at that point in time. This is good for + understanding how memory is used at an interesting point in time, + such as peak memory usage. +- "Cumulative" mode. In this mode, DMD tracks both the past and + current contents of the heap. You can dump that information to file, + giving a profile of the heap usage for the entire session. This is + good for finding parts of the code that cause high heap churn, e.g. + by allocating many short-lived allocations. +- "Heap scanning" mode. This mode is like live mode, but it also + records the contents of every live block in the log. This can be + used to investigate leaks by figuring out which objects might be + holding references to other objects. + +## Building and Running + +### Nightly Firefox + +The easiest way to use DMD is with the normal Nightly Firefox build, +which has DMD already enabled in the build. To have DMD active while +running it, you just need to set the environment variable `DMD=1` when +running. For instance, on OSX, you can run something like: + + DMD=1 /Applications/Firefox\ Nightly.app/Contents/MacOS/firefox + +You can tell it is working by going to `about:memory` and looking for +"Save DMD Output". If DMD has been properly enabled, the "Save" +button won't be grayed out. Look at the "Trigger" section below to +see the full list of ways to get a DMD report once you have it +activated. Note that the stack information you get will likely be less +detailed, due to being unable to symbolicate. You will be able to get +function names, but not line numbers. + +### Desktop Firefox + +#### Build + +Build Firefox with this option added to your mozconfig: + + ac_add_options --enable-dmd + +If building via try server, modify +`browser/config/mozconfigs/linux64/common-opt` or a similar file before +pushing. + +#### Launch + +Use `mach run --dmd`; use `--mode` to choose the mode. + +On a Windows build done by the try server, [these +instructions](https://bugzilla.mozilla.org/show_bug.cgi?id=936784#c69) from +2013 may or may not be useful. + +#### Trigger + +There are a few ways to trigger a DMD snapshot. Most of these will also +first get a memory report. When DMD is working on writing its output, it +will print logging like this: + + DMD[5222] opened /tmp/dmd-1414556492-5222.json.gz for writing + DMD[5222] Dump 1 { + DMD[5222] Constructing the heap block list... + DMD[5222] Constructing the stack trace table... + DMD[5222] Constructing the stack frame table... + DMD[5222] } + +You'll see separate output for each process. This step can take 10 or +more seconds and may make Firefox freeze temporarily. + +If you see the "opened" line, it tells you where the file was saved. +It's always in a temp directory, and the filenames are always of the +form dmd-<pid>. + +The ways to trigger a DMD snapshot are: + +1. Visit about:memory and click the "Save" button under "Save DMD output". + The button won't be present in non-DMD builds, and will be grayed out + in DMD builds if DMD isn't enabled at start-up. + +2. If you wish to trigger DMD dumps from within C++ or JavaScript code, + you can use `nsIMemoryInfoDumper.dumpMemoryInfoToTempDir`. For example, + from JavaScript code you can do the following. + + const Cc = Components.classes; + let mydumper = Cc["@mozilla.org/memory-info-dumper;1"] + .getService(Ci.nsIMemoryInfoDumper); + mydumper.dumpMemoryInfoToTempDir(identifier, anonymize, minimize); + + This will dump memory reports and DMD output to the temporary + directory. `identifier` is a string that will be used for part of + the filename (or a timestamp will be used if it is an empty string); + `anonymize` is a boolean that indicates if the memory reports should + be anonymized; and `minimize` is a boolean that indicates if memory + usage should be minimized first. + +3. On Linux, you can send signal 34 to the firefox process, e.g. + with the following command. + + $ killall -34 firefox + +4. The `MOZ_DMD_SHUTDOWN_LOG` environment variable, if set, triggers a DMD + run at shutdown; its value must be a directory where the logs will be + placed. This is mostly useful for debugging leaks. Which processes get + logged is controlled by the `MOZ_DMD_LOG_PROCESS` environment variable. + If this is not set, it will log all processes. It can be set to any valid + value of `XRE_GetProcessTypeString()` and will log only those processes. + For instance, if set to `default` it will only log the parent process. If + set to `tab`, it will log content processes only. + + For example, if you have + + MOZ_DMD_SHUTDOWN_LOG=~/dmdlogs/ MOZ_DMD_LOG_PROCESS=tab + + then DMD will create logs at shutdown for content processes and save them to + `~/dmdlogs/`. + +**NOTE:** + +- To dump DMD data from content processes, you'll need to disable the + sandbox with `MOZ_DISABLE_CONTENT_SANDBOX=1`. +- MOZ_DMD_SHUTDOWN_LOG must (currently) include the trailing separator + (\'\'/\") + + +### Fennec + +**NOTE:** + +You'll note from the name of this section being "Fennec" that these instructions +are very old. Hopefully they'll be more useful than not having them. + +**NOTE:** + +In order to use DMD on Fennec you will need root access on the Android +device. Instructions on how to root your device is outside the scope of +this document. + + +#### Build + +Build with these options: + + ac_add_options --enable-dmd + +#### Prep + +In order to prepare your device for running Fennec with DMD enabled, you +will need to do a few things. First, you will need to push the libdmd.so +library to the device so that it can by dynamically loaded by Fennec. +You can do this by running: + + adb push $OBJDIR/dist/bin/libdmd.so /sdcard/ + +Second, you will need to make an executable wrapper for Fennec which +sets an environment variable before launching it. (If you are familiar +with the recommended "--es env0" method for setting environment +variables when launching Fennec, note that you cannot use this method +here because those are processed too late in the startup process. If you +are not familiar with that method, you can ignore this parenthetical +note.) First make the executable wrapper on your host machine using the +editor of your choice. Name the file dmd_fennec and enter this as the +contents: + + #!/system/bin/sh + export MOZ_REPLACE_MALLOC_LIB=/sdcard/libdmd.so + exec "$@" + +If you want to use other DMD options, you can enter additional +environment variables above. You will need to push this to the device +and make it executable. Since you cannot mark files in /sdcard/ as +executable, we will use /data/local/tmp for this purpose: + + adb push dmd_fennec /data/local/tmp + adb shell + cd /data/local/tmp + chmod 755 dmd_fennec + +The final step is to make Android use the above wrapper script while +launching Fennec, so that the environment variable is present when +Fennec starts up. Assuming you have done a local build, the app +identifier will be `org.mozilla.fennec_$USERNAME` (`$USERNAME` is your +username on the host machine) and so we do this as shown below. If you +are using a DMD-enabled try build, or build from other source, adjust +the app identifier as necessary. + + adb shell + su # You need root access for the setprop command to take effect + setprop wrap.org.mozilla.fennec_$USERNAME "/data/local/tmp/dmd_fennec" + +Once this is set up, starting the `org.mozilla.fennec_$USERNAME` app +will use the wrapper script. + +#### Launch + +Launch Fennec either by tapping on the icon as usual, or from the +command line (as before, be sure to replace +`org.mozilla.fennec_$USERNAME` with the app identifier as appropriate). + + adb shell am start -n org.mozilla.fennec_$USERNAME/.App + +#### Trigger + +Use the existing memory-report dumping hook: + + adb shell am broadcast -a org.mozilla.gecko.MEMORY_DUMP + +In logcat, you should see output similar to this: + + I/DMD (20731): opened /storage/emulated/0/Download/memory-reports/dmd-default-20731.json.gz for writing + ... + I/GeckoConsole(20731): nsIMemoryInfoDumper dumped reports to /storage/emulated/0/Download/memory-reports/unified-memory-report-default-20731.json.gz + +The path is where the memory reports and DMD reports get dumped to. You +can pull them like so: + + adb pull /sdcard/Download/memory-reports/dmd-default-20731.json.gz + adb pull /sdcard/Download/memory-reports/unified-memory-report-default-20731.json.gz + +## Processing the output + +DMD outputs one gzipped JSON file per process that contains a +description of that process's heap. You can analyze these files (either +gzipped or not) using `dmd.py`. On Nightly Firefox, `dmd.py` is included +in the distribution. For instance on OS X, it is located in the +directory `/Applications/Firefox Nightly.app/Contents/Resources/`. For +Nightly, symbolication will fail, but you can at least get some +information. In a local build, `dmd.py` will be located in the directory +`$OBJDIR/dist/bin/`. + +Some platforms (Linux, Mac, Android) require stack fixing, which adds +missing filenames, function names and line number information. This will +occur automatically the first time you run `dmd.py` on the output file. +This can take 10s of seconds or more to complete. (This will fail if +your build does not contain symbols. However, if you have crash reporter +symbols for your build -- as tryserver builds do -- you can use [this +script](https://github.com/mstange/analyze-tryserver-profiles/blob/master/resymbolicate_dmd.py) +instead: clone the whole repo, edit the paths at the top of +`resymbolicate_dmd.py` and run it.) The simplest way to do this is to +just run the `dmd.py` script on your DMD report while your working +directory is `$OBJDIR/dist/bin`. This will allow the local libraries to +be found and used. + +If you invoke `dmd.py` without arguments you will get output appropriate +for the mode in which DMD was invoked. + +### "Dark matter" mode output + +For "dark matter" mode, `dmd.py`'s output describes how the live heap +blocks are covered by memory reports. This output is broken into +multiple sections. + +1. "Invocation". This tells you how DMD was invoked, i.e. what + options were used. +2. "Twice-reported stack trace records". This tells you which heap + blocks were reported twice or more. The presence of any such records + indicates bugs in one or more memory reporters. +3. "Unreported stack trace records". This tells you which heap blocks + were not reported, which indicate where additional memory reporters + would be most helpful. +4. "Once-reported stack trace records": like the "Unreported stack + trace records" section, but for blocks reported once. +5. "Summary": gives measurements of the total heap, and the + unreported/once-reported/twice-reported portions of it. + +The "Twice-reported stack trace records" and "Unreported stack trace +records" sections are the most important, because they indicate ways in +which the memory reporters can be improved. + +Here's an example stack trace record from the "Unreported stack trace +records" section. + + Unreported { + 150 blocks in heap block record 283 of 5,495 + 21,600 bytes (20,400 requested / 1,200 slop) + Individual block sizes: 144 x 150 + 0.00% of the heap (16.85% cumulative) + 0.02% of unreported (94.68% cumulative) + Allocated at { + #01: replace_malloc (/home/njn/moz/mi5/go64dmd/memory/replace/dmd/../../../../memory/replace/dmd/DMD.cpp:1286) + #02: malloc (/home/njn/moz/mi5/go64dmd/memory/build/../../../memory/build/replace_malloc.c:153) + #03: moz_xmalloc (/home/njn/moz/mi5/memory/mozalloc/mozalloc.cpp:84) + #04: nsCycleCollectingAutoRefCnt::incr(void*, nsCycleCollectionParticipant*) (/home/njn/moz/mi5/go64dmd/dom/xul/../../dist/include/nsISupportsImpl.h:250) + #05: nsXULElement::Create(nsXULPrototypeElement*, nsIDocument*, bool, bool,mozilla::dom::Element**) (/home/njn/moz/mi5/dom/xul/nsXULElement.cpp:287) + #06: nsXBLContentSink::CreateElement(char16_t const**, unsigned int, mozilla::dom::NodeInfo*, unsigned int, nsIContent**, bool*, mozilla::dom::FromParser) (/home/njn/moz/mi5/dom/xbl/nsXBLContentSink.cpp:874) + #07: nsCOMPtr<nsIContent>::StartAssignment() (/home/njn/moz/mi5/go64dmd/dom/xml/../../dist/include/nsCOMPtr.h:753) + #08: nsXMLContentSink::HandleStartElement(char16_t const*, char16_t const**, unsigned int, unsigned int, bool) (/home/njn/moz/mi5/dom/xml/nsXMLContentSink.cpp:1007) + } + } + +It tells you that there were 150 heap blocks that were allocated from +the program point indicated by the "Allocated at" stack trace, that +these blocks took up 21,600 bytes, that all 150 blocks had a size of 144 +bytes, and that 1,200 of those bytes were "slop" (wasted space caused +by the heap allocator rounding up request sizes). It also indicates what +percentage of the total heap size and the unreported portion of the heap +these blocks represent. + +Within each section, records are listed from largest to smallest. + +Once-reported and twice-reported stack trace records also have stack +traces for the report point(s). For example: + + Reported at { + #01: mozilla::dmd::Report(void const*) (/home/njn/moz/mi2/memory/replace/dmd/DMD.cpp:1740) 0x7f68652581ca + #02: CycleCollectorMallocSizeOf(void const*) (/home/njn/moz/mi2/xpcom/base/nsCycleCollector.cpp:3008) 0x7f6860fdfe02 + #03: nsPurpleBuffer::SizeOfExcludingThis(unsigned long (*)(void const*)) const (/home/njn/moz/mi2/xpcom/base/nsCycleCollector.cpp:933) 0x7f6860fdb7af + #04: nsCycleCollector::SizeOfIncludingThis(unsigned long (*)(void const*), unsigned long*, unsigned long*, unsigned long*, unsigned long*, unsigned long*) const (/home/njn/moz/mi2/xpcom/base/nsCycleCollector.cpp:3029) 0x7f6860fdb6b1 + #05: CycleCollectorMultiReporter::CollectReports(nsIMemoryMultiReporterCallback*, nsISupports*) (/home/njn/moz/mi2/xpcom/base/nsCycleCollector.cpp:3075) 0x7f6860fde432 + #06: nsMemoryInfoDumper::DumpMemoryReportsToFileImpl(nsAString_internal const&) (/home/njn/moz/mi2/xpcom/base/nsMemoryInfoDumper.cpp:626) 0x7f6860fece79 + #07: nsMemoryInfoDumper::DumpMemoryReportsToFile(nsAString_internal const&, bool, bool) (/home/njn/moz/mi2/xpcom/base/nsMemoryInfoDumper.cpp:344) 0x7f6860febaf9 + #08: mozilla::(anonymous namespace)::DumpMemoryReportsRunnable::Run() (/home/njn/moz/mi2/xpcom/base/nsMemoryInfoDumper.cpp:58) 0x7f6860fefe03 + } + +You can tell which memory reporter made the report by the name of the +`MallocSizeOf` function near the top of the stack trace. In this case it +was the cycle collector's reporter. + +By default, DMD does not record an allocation stack trace for most +blocks, to make it run faster. The decision on whether to record is done +probabilistically, and larger blocks are more likely to have an +allocation stack trace recorded. All unreported blocks that lack an +allocation stack trace will end up in a single record. For example: + + Unreported { + 420,010 blocks in heap block record 2 of 5,495 + 29,203,408 bytes (27,777,288 requested / 1,426,120 slop) + Individual block sizes: 2,048 x 3; 1,024 x 103; 512 x 147; 496 x 7; 480 x 31; 464 x 6; 448 x 50; 432 x 41; 416 x 28; 400 x 53; 384 x 43; 368 x 216; 352 x 141; 336 x 58; 320 x 104; 304 x 5,130; 288 x 150; 272 x 591; 256 x 6,017; 240 x 1,372; 224 x 93; 208 x 488; 192 x 1,919; 176 x 18,903; 160 x 1,754; 144 x 5,041; 128 x 36,709; 112 x 5,571; 96 x 6,280; 80 x 40,738; 64 x 37,925; 48 x 78,392; 32 x 136,199; 16 x 31,001; 8 x 4,706 + 3.78% of the heap (10.24% cumulative) + 21.24% of unreported (57.53% cumulative) + Allocated at { + #01: (no stack trace recorded due to --stacks=partial) + } + } + +In contrast, stack traces are always recorded when a block is reported, +which means you can end up with records like this where the allocation +point is unknown but the reporting point *is* known: + + Once-reported { + 104,491 blocks in heap block record 13 of 4,689 + 10,392,000 bytes (10,392,000 requested / 0 slop) + Individual block sizes: 512 x 124; 256 x 242; 192 x 813; 128 x 54,664; 64 x 48,648 + 1.35% of the heap (48.65% cumulative) + 1.64% of once-reported (59.18% cumulative) + Allocated at { + #01: (no stack trace recorded due to --stacks=partial) + } + Reported at { + #01: mozilla::dmd::DMDFuncs::Report(void const*) (/home/njn/moz/mi5/go64dmd/memory/replace/dmd/../../../../memory/replace/dmd/DMD.cpp:1646) + #02: WindowsMallocSizeOf(void const*) (/home/njn/moz/mi5/dom/base/nsWindowMemoryReporter.cpp:189) + #03: nsAttrAndChildArray::SizeOfExcludingThis(unsigned long (*)(void const*)) const (/home/njn/moz/mi5/dom/base/nsAttrAndChildArray.cpp:880) + #04: mozilla::dom::FragmentOrElement::SizeOfExcludingThis(unsigned long (*)(void const*)) const (/home/njn/moz/mi5/dom/base/FragmentOrElement.cpp:2337) + #05: nsINode::SizeOfIncludingThis(unsigned long (*)(void const*)) const (/home/njn/moz/mi5/go64dmd/parser/html/../../../dom/base/nsINode.h:307) + #06: mozilla::dom::NodeInfo::NodeType() const (/home/njn/moz/mi5/go64dmd/dom/base/../../dist/include/mozilla/dom/NodeInfo.h:127) + #07: nsHTMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes*) const (/home/njn/moz/mi5/dom/html/nsHTMLDocument.cpp:3710) + #08: nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes*) const (/home/njn/moz/mi5/dom/base/nsDocument.cpp:12820) + } + } + +The choice of whether to record an allocation stack trace for all blocks +is controlled by an option (see below). + +### "Live" mode output + + +For "live" mode, dmd.py's output describes what live heap blocks are +present. This output is broken into multiple sections. + +1. "Invocation". This tells you how DMD was invoked, i.e. what + options were used. +2. "Live stack trace records". This tells you which heap blocks were + present. +3. "Summary": gives measurements of the total heap. + +The individual records are similar to those output in "dark matter" +mode. + +### "Cumulative" mode output + +For "cumulative" mode, dmd.py's output describes how the live heap +blocks are covered by memory reports. This output is broken into +multiple sections. + +1. "Invocation". This tells you how DMD was invoked, i.e. what + options were used. +2. "Cumulative stack trace records". This tells you which heap blocks + were allocated during the session. +3. "Summary": gives measurements of the total (cumulative) heap. + +The individual records are similar to those output in "dark matter" +mode. + +### "Scan" mode output + +For "scan" mode, the output of `dmd.py` is the same as "live" mode. +A separate script, `block_analyzer.py`, can be used to find out +information about which blocks refer to a particular block. +`dmd.py --clamp-contents` needs to be run on the log first. See [this +other page](heap_scan_mode.md) for an +overview of how to use heap scan mode to fix a leak involving refcounted +objects. + +## Options + +### Runtime + +When you run `mach run --dmd` you can specify additional options to +control how DMD runs. Run `mach help run` for documentation on these. + +The most interesting one is `--mode`. Acceptable values are +`dark-matter` (the default), `live`, `cumulative`, and `scan`. + +Another interesting one is `--stacks`. Acceptable values are `partial` +(the default) and `full`. In the former case most blocks will not have +an allocation stack trace recorded. However, because larger blocks are +more likely to have one recorded, most allocated bytes should have an +allocation stack trace even though most allocated blocks do not. Use +`--stacks=full` if you want complete information, but note that DMD will +run substantially slower in that case. + +The options may also be put in the environment variable DMD, or set DMD +to 1 to enable DMD with default options (dark-matter and partial +stacks). + +### Post-processing + +`dmd.py` also takes options that control how it works. Run `dmd.py -h` +for documentation. The following options are the most interesting ones. + +- `-f` / `--max-frames`. By default, records show up to 8 stack + frames. You can choose a smaller number, in which case more + allocations will be aggregated into each record, but you'll have + less context. Or you can choose a larger number, in which cases + allocations will be split across more records, but you will have + more context. There is no single best value, but values in the range + 2..10 are often good. The maximum is 24. + +- `-a` / `--ignore-alloc-fns`. Many allocation stack traces start + with multiple frames that mention allocation wrapper functions, e.g. + `js_calloc()` calls `replace_calloc()`. This option filters these + out. It often helps improve the quality of the output when using a + small `--max-frames` value. + +- `-s` / `--sort-by`. This controls how records are sorted. Acceptable + values are `usable` (the default), `req`, `slop` and `num-blocks`. + +- `--clamp-contents`. For a heap scan log, this performs a + conservative pointer analysis on the contents of each block, + changing any value that is a pointer into the middle of a live block + into a pointer to the start of that block. All other values are + changes to null. In addition, all trailing nulls are removed from + the block contents. + +As an example that combines multiple options, if you apply the following +command to a profile obtained in "live" mode: + + dmd.py -r -f 2 -a -s slop + +it will give you a good idea of where the major sources of slop are. + +`dmd.py` can also compute the difference between two DMD output files, +so long as those files were produced in the same mode. Simply pass it +two filenames instead of one to get the difference. + +## Which heap blocks are reported? + +At this stage you might wonder how DMD knows, in "dark matter" mode, +which allocations have been reported and which haven't. DMD only knows +about heap blocks that are measured via a function created with one of +the following two macros: + + MOZ_DEFINE_MALLOC_SIZE_OF + MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC + +Fortunately, most of the existing memory reporters do this. See +[Performance/Memory_Reporting](https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Memory_reporting "Platform/Memory Reporting") +for more details about how memory reporters are written. diff --git a/docs/performance/memory/dominators.md b/docs/performance/memory/dominators.md new file mode 100644 index 0000000000..e64c465e62 --- /dev/null +++ b/docs/performance/memory/dominators.md @@ -0,0 +1,90 @@ +# Dominators + +This article provides an introduction to the concepts of *Reachability*, +*Shallow* versus *Retained* size, and *Dominators*, as they apply in +garbage-collected languages like JavaScript. + +These concepts matter in memory analysis, because often an object may +itself be small, but may hold references to other much larger objects, +and by doing this will prevent the garbage collector from freeing that +extra memory. + +You can see the dominators in a page using the [Dominators +view](dominators_view.md) in the Memory tool. + +With a garbage-collected language, like JavaScript, the programmer +doesn\'t generally have to worry about deallocating memory. They can +just create and use objects, and when the objects are no longer needed, +the runtime takes care of cleaning up, and frees the memory the objects +occupied. + +## Reachability + +In modern JavaScript implementations, the runtime decides whether an +object is no longer needed based on *reachability*. In this system the +heap is represented as one or more graphs. Each node in the graph +represents an object, and each connection between nodes (edge) +represents a reference from one object to another. The graph starts at a +root node, indicated in these diagrams with \"R\". + +![](../img/memory-graph.svg) + +During garbage collection, the runtime traverses the graph, starting at +the root, and marks every object it finds. Any objects it doesn\'t find +are unreachable, and can be deallocated. + +So when an object becomes unreachable (for example, because it is only +referenced by a single local variable which goes out of scope) then any +objects it references also become unreachable, as long as no other +objects reference them: + +![](../img/memory-graph-unreachable.svg) + +Conversely, this means that objects are kept alive as long as some other +reachable object is holding a reference to them. + +## Shallow and retained size + +This gives rise to a distinction between two ways to look at the size of +an object: + +- *shallow size*: the size of the object itself +- *retained size*: the size of the object itself, plus the size of + other objects that are kept alive by this object + +Often, objects will have a small shallow size but a much larger retained +size, through the references they contain to other objects. Retained +size is an important concept in analyzing memory usage, because it +answers the question \"if this object ceases to exist, what\'s the total +amount of memory freed?\". + +## Dominators + +A related concept is that of the *dominator*. Node B is said to dominate +node A if every path from the root to A passes through B: + +![](../img/memory-graph-dominators.svg) + +If any of node A\'s dominators are freed, then node A itself becomes +eligible for garbage collection. + +[If node B dominates node A, but does not dominate any of A\'s other +dominators, then B is the *immediate dominator* of +A:] + +![](../img/memory-graph-immediate-dominator.svg) + +[One slight subtlety here is that if an object A is referenced by two +other objects B and C, then neither object is its +dominator], because you could remove either B or C from +the graph, and A would still be retained by its other referrer. Instead, +the immediate dominator of A would be its first common ancestor:\ +![](../img/memory-graph-dominator-multiple-references.svg) + +## See also + +[Dominators in graph +theory](https://en.wikipedia.org/wiki/Dominator_%28graph_theory%29). + +[Tracing garbage +collection](https://en.wikipedia.org/wiki/Tracing_garbage_collection). diff --git a/docs/performance/memory/dominators_view.md b/docs/performance/memory/dominators_view.md new file mode 100644 index 0000000000..05de01fa4e --- /dev/null +++ b/docs/performance/memory/dominators_view.md @@ -0,0 +1,221 @@ +# Dominators view + +The Dominators view is new in Firefox 46. + +Starting in Firefox 46, the Memory tool includes a new view called the +Dominators view. This is useful for understanding the \"retained size\" +of objects allocated by your site: that is, the size of the objects +themselves plus the size of the objects that they keep alive through +references. + +If you already know what shallow size, retained size, and dominators +are, skip to the Dominators UI section. Otherwise, you might want to +review the article on [Dominators +concepts](dominators.md). + +## Dominators UI + +To see the Dominators view for a snapshot, select \"Dominators\" in the +\"View\" drop-down list. It looks something like this: + +![](../img/dominators-1.png) + +The Dominators view consists of two panels: + +- the [Dominators Tree + panel](#dominators-tree-panel) + shows you which nodes in the snapshot are retaining the most memory +- the [Retaining Paths + panel](#retaining-paths-panel) + (new in Firefox 47) shows the 5 shortest retaining paths for a + single node. + +![](../img/dominators-2.png) + +### Dominators Tree panel + +The Dominators Tree tells you which objects in the snapshot are +retaining the most memory. + +In the main part of the UI, the first row is labeled \"GC Roots\". +Immediately underneath that is an entry for: + +- Every GC root node. In Gecko, there is more than one memory graph, + and therefore more than one root. There may be many (often + temporary) roots. For example: variables allocated on the stack need + to be rooted, or internal caches may need to root their elements. +- Any other node that\'s referenced from two different roots (since in + this case, neither root dominates it). + +Each entry displays: + +- the retained size of the node, as bytes and as a percentage of the + total +- the shallow size of the node, as bytes and as a percentage of the + total +- the nodes\'s name and address in memory. + +Entries are ordered by the amount of memory that they retain. For +example: + +![](../img/dominators-3.png) + +In this screenshot we can see five entries under \"GC Roots\". The first +two are Call and Window objects, and retain about 21% and 8% of the +total size of the memory snapshot, respectively. You can also see that +these objects have a relatively tiny \"Shallow Size\", so almost all of +the retained size is in the objects that they dominate. + +Immediately under each GC root, you\'ll see all the nodes for which this +root is the [immediate +dominator](/dominators.html#immediate_dominator). +These nodes are also ordered by their retained size. + +For example, if we click on the first Window object: + +![](../img/dominators-4.png) + +We can see that this Window dominates a CSS2Properties object, whose +retained size is 2% of the total snapshot size. Again the shallow size +is very small: almost all of its retained size is in the nodes that it +dominates. By clicking on the disclosure arrow next to the Function, we +can see those nodes. + +In this way you can quickly get a sense of which objects retain the most +memory in the snapshot. + +You can use [Alt]{.kbd} + click to expand the whole graph under a node. + +#### Call Stack {#Call_Stack} + +In the toolbar at the top of the tool is a dropdown called \"Label by\": + +![](../img/dominators-5.png) + +By default, this is set to \"Type\". However, you can set it instead to +\"Call Stack\" to see exactly where in your code the objects are being +allocated. + +::: {.note} +This option is called \"Allocation Stack\" in Firefox 46. +::: + +To enable this, you must check the box labeled \"Record call stacks\" +*before* you run the code that allocates the objects. Then take a +snapshot, then select \"Call Stack\" in the \"Label by\" drop-down. + +Now the node\'s name will contain the name of the function that +allocated it, and the file, line number and character position of the +exact spot where the function allocated it. Clicking the file name will +take you to that spot in the Debugger. + +<iframe width="595" height="325" src="https://www.youtube.com/embed/qTF5wCSD124" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + +::: +Sometimes you\'ll see \"(no stack available)\" here. In particular, +allocation stacks are currently only recorded for objects, not for +arrays, strings, or internal structures. +::: + +### Retaining Paths panel + +::: {.geckoVersionNote} +The Retaining Paths panel is new in Firefox 47. +::: + +The Retaining Paths panel shows you, for a given node, the 5 shortest +paths back from this node to a GC root. This enables you to see all the +nodes that are keeping the given node from being garbage-collected. If +you suspect that an object is being leaked, this will show you exactly +which objects are holding a reference to it. + +To see the retaining paths for a node, you have to select the node in +the Dominators Tree panel: + +![](../img/dominators-6.png) + +Here, we\'ve selected an object, and can see a single path back to a GC +root. + +The `Window` GC root holds a reference to an `HTMLDivElement` object, +and that holds a reference to an `Object`, and so on. If you look in the +Dominators Tree panel, you can trace the same path there. If either of +these references were removed, the items below them could be +garbage-collected. + +Each connection in the graph is labeled with the variable name for the +referenced object. + +Sometimes there\'s more than one retaining path back from a node: + +![](../img/dominators-7.png) + +Here there are three paths back from the `DocumentPrototype` node to a +GC root. If one were removed, then the `DocumentPrototype` would still +not be garbage-collected, because it\'s still retained by the other two +path. + +## Example {#Example} + +Let\'s see how some simple code is reflected in the Dominators view. + +We\'ll use the [monster allocation +example](monster_example.md), which creates three +arrays, each containing 5000 monsters, each monster having a +randomly-generated name. + +### Taking a snapshot + +To see what it looks like in the Dominators view: + +- load the page +- enable the Memory tool in the + [Settings](https://developer.mozilla.org/en-US/docs/Tools/Tools_Toolbox#settings), if you + haven\'t already +- open the Memory tool +- check \"Record call stacks\" +- press the button labeled \"Make monsters!\" +- take a snapshot +- switch to the \"Dominators\" view + +<iframe width="595" height="325" src="https://www.youtube.com/embed/HiWnfMoMs2c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + +### Analyzing the Dominators Tree + +You\'ll see the three arrays as the top three GC roots, each retaining +about 23% of the total memory usage: + +![](../img/dominators-8.png) + +If you expand an array, you\'ll see the objects (monsters) it contains. +Each monster has a relatively small shallow size of 160 bytes. This +includes the integer eye- and tentacle-counts. Each monster has a bigger +retained size, which is accounted for by the string used for the +monster\'s name: + +![](../img/dominators-9.png) + +All this maps closely to the [memory graph we were expecting to +see](/monster_example.html#allocation-graph). One +thing you might be wondering, though, is: where\'s the top-level object +that retains all three arrays? If we look at the Retaining Paths panel +for one of the arrays, we\'ll see it: + +![](../img/dominators-10.png) + +Here we can see the retaining object, and even that this particular +array is the array of `fierce` monsters. But the array is also rooted +directly, so if the object were to stop referencing the array, it would +still not be eligible for garbage collection. + +This means that the object does not dominate the array, and is therefore +not shown in the Dominators Tree view. [See the relevant section of the +Dominators concepts +article](dominators.html#multiple-paths). + +### Using the Call Stack view {#Using_the_Call_Stack_view} + +Finally, you can switch to the Call Stack view, see where the objects +are being allocated, and jump to that point in the Debugger: + +<iframe width="595" height="325" src="https://www.youtube.com/embed/qTF5wCSD124" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> diff --git a/docs/performance/memory/gc_and_cc_logs.md b/docs/performance/memory/gc_and_cc_logs.md new file mode 100644 index 0000000000..62e151dff4 --- /dev/null +++ b/docs/performance/memory/gc_and_cc_logs.md @@ -0,0 +1,109 @@ +# GC and CC logs + +Garbage collector (GC) and cycle collector (CC) logs give information +about why various JS and C++ objects are alive in the heap. Garbage +collector logs and cycle collector logs can be analyzed in various ways. +In particular, CC logs can be used to understand why the cycle collector +is keeping an object alive. These logs can either be manually or +automatically generated, and they can be generated in both debug and +non-debug builds. + +This logs the contents of the Javascript heap to a file named +`gc-edges-NNNN.log`. It also creates a file named `cc-edges-NNNN.log` to +which it dumps the parts of the heap visible to the cycle collector, +which includes native C++ objects that participate in cycle collection, +as well as JS objects being held alive by those C++ objects. + +## Generating logs + +### From within Firefox + +To manually generate GC and CC logs, navigate to `about:memory` and use +the buttons under \"Save GC & CC logs.\" \"Save concise\" will generate +a smaller CC log, \"Save verbose\" will provide a more detailed CC log. +(The GC log will be the same size in either case.) + +With multiprocess Firefox, you can't record logs from the content +process, due to sandboxing. You'll need to disable sandboxing by +setting `MOZ_DISABLE_CONTENT_SANDBOX=t` when you run Firefox. + +### From the commandline + +TLDR: if you just want shutdown GC/CC logs to debug leaks that happen in +our automated tests, you probably want something along the lines of: + + MOZ_DISABLE_CONTENT_SANDBOX=t MOZ_CC_LOG_DIRECTORY=/full/path/to/log/directory/ MOZ_CC_LOG_SHUTDOWN=1 MOZ_CC_ALL_TRACES=shutdown ./mach ... + +As noted in the previous section, with multiprocess Firefox, you can't +record logs from the content process, due to sandboxing. You'll need to +disable sandboxing by setting `MOZ_DISABLE_CONTENT_SANDBOX=t` when you +run Firefox. + +On desktop Firefox you can override the default location of the log +files by setting the `MOZ_CC_LOG_DIRECTORY` environment variable. By +default, they go to a temporary directory which differs per OS - it's +`/tmp/` on Linux/BSD, `$LOCALAPPDATA\Temp\` on Windows, and somewhere in +`/var/folders/` on Mac (whatever the directory service returns for +`TmpD`/`NS_OS_TEMP_DIR`). Note that just `MOZ_CC_LOG_DIRECTORY=.` won't +work - you need to specify a full path. On Firefox for Android you can +use the cc-dump.xpi +extension to save the files to `/sdcard`. By default, the file is +created in some temp directory, and the path to the file is printed to +the Error Console. + +To log every cycle collection, set the `MOZ_CC_LOG_ALL` environment +variable. To log only shutdown collections, set `MOZ_CC_LOG_SHUTDOWN`. +To make all CCs verbose, set `MOZ_CC_ALL_TRACES to "all`\", or to +\"`shutdown`\" to make only shutdown CCs verbose. + +Live GC logging can be enabled with the pref +`javascript.options.mem.log`. Output to a file can be controlled with +the MOZ_GCTIMER environment variable. See the [Statistics +API](https://developer.mozilla.org/en-US/docs/Tools/Tools_Toolbox#settings/en-US/docs/SpiderMonkey/Internals/GC/Statistics_API) page for +details on values. + +Set the environment variable `MOZ_CC_LOG_THREAD` to `main` to only log +main thread CCs, or to `worker` to only log worker CCs. The default +value is `all`, which will log all CCs. + +To get cycle collector logs on Try server, set `MOZ_CC_LOG_DIRECTORY` to +`MOZ_UPLOAD_DIR`, then set the other variables appropriately to generate +CC logs. The way to set environment variables depends on the test +harness, or you can modify the code in nsCycleCollector to set that +directly. To find the CC logs once the try run has finished, click on +the particular job, then click on \"Job Details\" in the bottom pane in +TreeHerder, and you should see download links. + +To set the environment variable, find the `buildBrowserEnv` method in +the Python file for the test suite you are interested in, and add +something like this code to the file: + + browserEnv["MOZ_CC_LOG_DIRECTORY"] = os.environ["MOZ_UPLOAD_DIR"] + browserEnv["MOZ_CC_LOG_SHUTDOWN"] = "1" + +## Analyzing GC and CC logs + +There are numerous scripts that analyze GC and CC logs on +[GitHub](https://github.com/amccreight/heapgraph/) + + +To find out why an object is being kept alive, you should use `find_roots.py` +in the root of the github repository. Calling `find_roots.py` on a CC log +with a specific object or kind of object will produce paths from rooting +objects to the specified objects. Most big leaks include an `nsGlobalWindow`, +so that's a good class to try if you don't have any better idea. + +To fix a leak, the next step is to figure out why the rooting object is +alive. For a C++ object, you need to figure out where the missing +references are from. For a JS object, you need to figure out why the JS +object is reachable from a JS root. For the latter, you can use the +corresponding [`find_roots.py` for +JS](https://github.com/amccreight/heapgraph/tree/master/g) +on the GC log. + +## Alternatives + +There are two add-ons that can be used to create and analyze CC graphs. + +- [about:cc](https://bugzilla.mozilla.org/show_bug.cgi?id=726346) + is simple, ugly, but rather powerful. diff --git a/docs/performance/memory/heap_scan_mode.md b/docs/performance/memory/heap_scan_mode.md new file mode 100644 index 0000000000..ea5a45016a --- /dev/null +++ b/docs/performance/memory/heap_scan_mode.md @@ -0,0 +1,313 @@ +# DMD heap scan mode + +Firefox's DMD heap scan mode tracks the set of all live blocks of +malloc-allocated memory and their allocation stacks, and allows you to +log these blocks, and the values stored in them, to a file. When +combined with cycle collector logging, this can be used to investigate +leaks of refcounted cycle collected objects, by figuring out what holds +a strong reference to a leaked object. + +**When should you use this?** DMD heap scan mode is intended to be used +to investigate leaks of cycle collected (CCed) objects. DMD heap scan +mode is a "tool of last resort" that should only be used when all +other avenues have been tried and failed, except possibly [ref count +logging](refcount_tracing_and_balancing.md). +It is particularly useful if you have no idea what is causing the leak. +If you have a patch that introduces a leak, you are probably better off +auditing all of the strong references that your patch creates before +trying this. + +The particular steps given below are intended for the case where the +leaked object is alive all the way through shutdown. You could modify +these steps for leaks that go away in shutdown by collecting a CC and +DMD log prior to shutdown. However, in that case it may be easier to use +refcount logging, or rr with a conditional breakpoint set on calls to +`Release()` for the leaking object, to see what object actually does the +release that causes the leaked object to go away. + +## Prerequisites + +- A debug DMD build of Firefox. [This + page](dmd.md) + describes how to do that. This should probably be an optimized + build. Non-optimized DMD builds will generate better stack traces, + but they can be so slow as to be useless. +- The build is going to be very slow, so you may need to disable some + shutdown checks. First, in + `toolkit/components/terminator/nsTerminator.cpp`, delete everything + in `RunWatchDog` but the call to `NS_SetCurrentThreadName`. This + will keep the watch dog from killing the browser when shut down + takes multiple minutes. Secondly, you may need to comment out the + call to `MOZ_CRASH("NSS_Shutdown failed");` in + `xpcom/build/XPCOMInit.cpp`, as this also seems to trigger when + shutdown is extremely slow. +- You need the cycle collector analysis script `find_roots.py`, which + can be downloaded as part of [this repo on + Github](https://github.com/amccreight/heapgraph). + +## Generating Logs + +The next step is to generate a number of log files. You need to get a +shutdown CC log and a DMD log, for a single run. + +**Definitions** I'll write `$objdir` for the object directory for your +Firefox DMD build, `$srcdir` for the top level of the Firefox source +directory, and `$heapgraph` for the location of the heapgraph repo, and +`$logdir` for the location you want logs to go to. `$logdir` should end +in a path separator. For instance, `~/logs/leak/`. + +The command you need to run Firefox will look something like this: + + XPCOM_MEM_BLOAT_LOG=1 MOZ_CC_LOG_SHUTDOWN=1 MOZ_DISABLE_CONTENT_SANDBOX=t MOZ_CC_LOG_DIRECTORY=$logdir + MOZ_CC_LOG_PROCESS=content MOZ_CC_LOG_THREAD=main MOZ_DMD_SHUTDOWN_LOG=$logdir MOZ_DMD_LOG_PROCESS=tab ./mach run --dmd --mode=scan + +Breaking this down: + +- `XPCOM_MEM_BLOAT_LOG=1`: This reports a list of the counts of every + object created and destroyed and tracked by the XPCOM leak tracking + system. From this chart, you can see how many objects of a + particular type were leaked through shutdown. This can come in handy + during the manual analysis phase later, to get evidence to support + your hunches. For instance, if you think that an `nsFoo` object + might be holding your leaking object alive, you can use this to + easily see if we leaked an `nsFoo` object. +- `MOZ_CC_LOG_SHUTDOWN=1`: This generates a cycle collector log during + shutdown. Creating this log during shutdown is nice because there + are less things unrelated to the leak in the log, and various cycle + collector optimizations are disabled. A garbage collector log will + also be created, which you may not need. +- `MOZ_DISABLE_CONTENT_SANDBOX=t`: This disables the content process + sandbox, which is needed because the DMD and CC log files are + created directly by the child processes. +- `MOZ_CC_LOG_DIRECTORY=$logdir`: This selects the location for cycle + collector logs to be saved. +- `MOZ_CC_LOG_PROCESS=content MOZ_CC_LOG_THREAD=main`: These options + specify that we only want CC logs for the main thread of content + processes, to make shutdown less slow. If your leak is happening in + a different process or thread, change the options, which are listed + in `xpcom/base/nsCycleCollector.cpp`. +- `MOZ_DMD_SHUTDOWN_LOG=$logdir`: This option specifies that we want a + DMD log to be taken very late in XPCOM shutdown, and the location + for that log to be saved. Like with the CC log, we want this log + very late to avoid as many non-leaking things as possible. +- `MOZ_DMD_LOG_PROCESS=tab`: As with the CC, this means that we only + want these logs in content processes, in order to make shutdown + faster. The allowed values here are the same as those returned by + `XRE_GetProcessType()`, so adjust as needed. +- Finally, the `--dmd` option need to be passed in so that DMD will be + run. `--mode=scan` is needed so that when we get a DMD log the + entire contents of each block of memory is saved for later analysis. + +With that command line in hand, you can start Firefox. Be aware that +this may take multiple minutes if you have optimization disabled. + +Once it has started, go through the steps you need to reproduce your +leak. If your leak is a ghost window, it can be handy to get an +`about:memory` report and write down the PID of the leaking process. You +may want to wait 10 or so seconds after this to make sure as much as +possible is cleaned up. + +Next, exit the browser. This will cause a lot of logs to be written out, +so it can take a while. + +## Analyzing the Logs + +### Getting the PID and address of the leaking object + +The first step is to figure out the **PID** of the leaking process. The +second step is to figure out **the address of the leaking object**, +usually a window. Conveniently, you can usually do both at once using +the cycle collector log. If you are investigating a leak of +`www.example.com`, then from `$logdir` you can do +`"grep nsGlobalWindow cc-edges* | grep example.com"`. This looks through +all of the windows in all of the CC logs (which may leaked, this late in +shutdown), and then filters out windows where the URL contains +`example.com`. + +The result of that grep will contain output that looks something like +this: + + cc-edges.15873.log:0x7f0897082c00 [rc=1285] nsGlobalWindowInner # 2147483662 inner https://www.example.com/ + +cc-edges.15873.log: The first part is the file name where it was +found. `15873` is the PID of the process that leaked. You'll want to +write down the name of the file and the PID. Let's call the file +`$cclog` and the pid `$pid`. + +0x7f0897082c00: This is the address of the leaking window. You'll +also want to write that down. Let's call this `$winaddr`. + +If there are multiple files, you'll end up with one that looks like +`cc-edges.$pid.log` and one or more that look like +`cc-edges.$pid-$n.log` for various values of `$n`. You want the one with +the largest `$n`, as this was recorded the latest, and so it will +contain the least non-garbage. + +### Identifying the root in the cycle collector log + +The next step is to figure out why the cycle collector could not collect +the window, using the `find_roots.py` script from the heapgraph +repository. The command to invoke this looks like this: + + python $heapgraph/find_roots.py $cclog $winaddr + +This may take a few seconds. It will eventually produce some output. +You'll want to save a copy of this output for later. + +The output will look something like this, after a message about loading +progress: + + 0x7f0882fe3230 [FragmentOrElement (xhtml) script https://www.example.com] + --[[via hash] mListenerManager]--> 0x7f0899b4e550 [EventListenerManager] + --[mListeners event=onload listenerType=3 [i]]--> 0x7f0882ff8f80 [CallbackObject] + --[mIncumbentGlobal]--> 0x7f0897082c00 [nsGlobalWindowInner # 2147483662 inner https://www.example.com] + +Root 0x7f0882fe3230 is a ref counted object with 1 unknown edge(s). + known edges: + 0x7f08975a24c0 [FragmentOrElement (xhtml) head https://www.example.com] --[mAttrsAndChildren[i]]--> 0x7f0882fe3230 + 0x7f08967e7b20 [JS Object (HTMLScriptElement)] --[UnwrapDOMObject(obj)]--> 0x7f0882fe3230 + +The first two lines mean that the script element `0x7f0882fe3230` +contains a strong reference to the EventListenerManager +`0x7f0899b4e550`. "[via hash] mListenerManager" is a description of +that strong reference. Together, these lines show a chain of strong +references from an object the cycle collector thinks needs to be kept +alive, `0x7f0899b4e550`, to the object` 0x7f0897082c00` that you asked +about. Most of the time, the actual chain is not important, because the +cycle collector can only tell us about what went right. Let us call the +address of the leaking object (`0x7f0882fe3230` in this case) +`$leakaddr`. + +Besides `$leakaddr`, the other interesting part is the chunk at the +bottom. It tells us that there is 1 unknown edge, and 2 known edges. +What this means is that the leaking object has a refcount of 3, but the +cycle collector was only told about these two references. In this case, +a head element and a JS object (the JS reflector of the script element). +We need to figure out what the unknown reference is from, as that is +where our leak really is. + +### Figure out what is holding the leaking object alive. + +Now we need to use the DMD heap scan logs. These contain the contents of +every live block of memory. + +The first step to using the DMD heap scan logs is to do some +pre-processing for the DMD log. Stacks need to be symbolicated, and we +need to clamp the values contained in the heap. Clamping is the same +kind of analysis that a conservative GC does: if a word-aligned value in +a heap block points to somewhere within another heap block, replace that +value with the address of the block. + +Both kinds of preprocessing are done by the `dmd.py` script, which can +be invoked like this: + + $objdir/dist/bin/dmd.py --clamp-contents dmd-$pid.log.gz + +This can take a few minutes due to symbolification, but you only need to +run it once on a log file. + +You can also locally symbolicate stacks from DMD logs generated on TreeHerder, +but it will [take a few extra steps](/contributing/debugging/local_symbols.rst) +that you need to do before running `dmd.py`. + +After that is done, we can finally find out which objects (possibly) +point to other objects, using the block_analyzer script: + + python $srcdir/memory/replace/dmd/block_analyzer.py dmd-$pid.log.gz $leakaddr + +This will look through every block of memory in the log, and give some +basic information about any block of memory that (possibly) contains a +pointer to that object. You can pass some additional options to affect +how the results are displayed. "-sfl 10000 -a" is useful. The -sfl 10000 +tells it to not truncate stack frames, and -a tells it to not display +generic frames related to the allocator. + +Caveat: I think block_analyzer.py does not attempt to clamp the address +you pass into it, so if it is an offset from the start of the block, it +won't find it. + + block_analyzer.py` will return a series of entries that look like this + with the [...] indicating where I have removed things): + 0x7f089306b000 size = 4096 bytes at byte offset 2168 + nsAttrAndChildArray::GrowBy[...] + nsAttrAndChildArray::InsertChildAt[...] + [...] + +`0x7f089306b000` is the address of the block that contains `$leakaddr`. +144 bytes is the size of that block. That can be useful for confirming +your guess about what class the block actually is. The byte offset tells +you were in the block the pointer is. This is mostly useful for larger +objects, and you can potentially combine this with debugging information +to figure out exactly what field this is. The rest of the entry is the +stack trace for the allocation of the block, which is the most useful +piece of information. + +What you need to do now is to go through every one of these entries and +place it into three categories: strong reference known to the cycle +collector, weak reference, or something else! The goal is to eventually +shrink down the "something else" category until there are only as many +things in it as there are unknown references to the leaking object, and +then you have your leaker. + +To place an entry into one of the categories, you must look at the code +locations given in the stack trace, and see if you can tell what the +object is based on that, then compare that to what `find_roots.py` told +you. + +For instance, one of the strong references in the CC log is from a head +element to its child via `mAttrsAndChildren`, and that sounds a lot like +this, so we can mark it as being a strong known reference. + +This is an iterative process, where you first go through and mark off +the things that are easily categorizable, and repeat until you have a +small list of things to analyze. + +### Example analysis of block_analyzer.py results + +In one debugging session where I was investigating the leak from bug +1451985, I eventually reduced the list of entries until this was the +most suspicious looking entry: + + 0x7f0892f29630 size = 392 bytes at byte offset 56 + mozilla::dom::ScriptLoader::ProcessExternalScript[...] + [...] + +I went to that line of `ScriptLoader::ProcessExternalScript()`, and it +contained a call to ScriptLoader::CreateLoadRequest(). Fortunately, this +method mostly just contains two calls to `new`, one for +`ScriptLoadRequest` and one for `ModuleLoadRequest`. (This is where an +unoptimized build comes in handy, as it would have pointed out the exact +line. Unfortunately, in this particular case, the unoptimized build was +so slow I wasn't getting any logs.) I then looked through the list of +leaked objects generated by `XPCOM_MEM_BLOAT_LOG` and saw that we were +leaking a `ScriptLoadRequest`, so I went and looked at its class +definition, where I noticed that `ScriptLoadRequest` had a strong +reference to an element that it wasn't telling the cycle collector +about, which seemed suspicious. + +The first thing I did to try to confirm that this was the source of the +leak was pass the address of this object into the cycle collector +analysis log, `find_roots.py`, that we used at an earlier step. That +gave a result that contained this: + + 0x7f0882fe3230 [FragmentOrElement (xhtml) script [...] + --[mNodeInfo]--> 0x7f0897431f00 [NodeInfo (xhtml) script] + [...] + --[mLoadingAsyncRequests]--> 0x7f0892f29630 [ScriptLoadRequest] + +This confirms that this block is actually a ScriptLoadRequest. Secondly, +notice that the load request is being held alive by the very same script +element that is causing the window leak! This strongly suggests that +there is a cycle of strong references between the script element and the +load request. I then added the missing field to the traverse and unlink +methods of ScriptLoadRequest, and confirmed that I couldn't reproduce +the leak. + +Keep in mind that you may need to run `block_analyzer.py` multiple +times. For instance, if the script element was being held alive by some +container being held alive by a runnable, we'd first need to figure out +that the container was holding the element. If it isn't possible to +figure out what is holding that alive, you'd have to run block_analyzer +again. This isn't too bad, because unlike ref count logging, we have the +full state of memory in our existing log, so we don't need to run the +browser again. diff --git a/docs/performance/memory/leak_gauge.md b/docs/performance/memory/leak_gauge.md new file mode 100644 index 0000000000..153303549e --- /dev/null +++ b/docs/performance/memory/leak_gauge.md @@ -0,0 +1,45 @@ +# Leak Gauge + +Leak Gauge is a tool that can be used to detect certain kinds of leaks +in Gecko, including those involving documents, window objects, and +docshells. It has two parts: instrumentation in Gecko that produces a +log file, and a script to post-process the log file. + +## Getting a log file + +To get a log file, run the browser with these settings: + + NSPR_LOG_MODULES=DOMLeak:5,DocumentLeak:5,nsDocShellLeak:5,NodeInfoManagerLeak:5 + NSPR_LOG_FILE=nspr.log # or any other filename of your choice + +This overwrites any existing file named `nspr.log`. The browser runs +with a negligible slowdown. For reliable results, exit the browser +before post-processing the log file. + +## Post-processing the log file + +Post-process the log file with +[tools/leak-gauge/leak-gauge.pl](https://searchfox.org/mozilla-central/source/tools/leak-gauge/leak-gauge.html) + +If there are no leaks, the output looks like this: + + Results of processing log leak.log : + Summary: + Leaked 0 out of 11 DOM Windows + Leaked 0 out of 44 documents + Leaked 0 out of 3 docshells + Leaked content nodes in 0 out of 0 documents + +If there are leaks, the output looks like this: + + Results of processing log leak2.log : + Leaked outer window 2c6e410 at address 2c6e410. + Leaked outer window 2c6ead0 at address 2c6ead0. + Leaked inner window 2c6ec80 (outer 2c6ead0) at address 2c6ec80. + Summary: + Leaked 13 out of 15 DOM Windows + Leaked 35 out of 46 documents + Leaked 4 out of 4 docshells + Leaked content nodes in 42 out of 53 documents + +If you find leaks, please file a bug report. diff --git a/docs/performance/memory/leak_hunting_strategies_and_tips.md b/docs/performance/memory/leak_hunting_strategies_and_tips.md new file mode 100644 index 0000000000..a5689223ea --- /dev/null +++ b/docs/performance/memory/leak_hunting_strategies_and_tips.md @@ -0,0 +1,219 @@ +# Leak hunting strategies and tips + +This document is old and some of the information is out-of-date. Use +with caution. + +## Strategy for finding leaks + +When trying to make a particular testcase not leak, I recommend focusing +first on the largest object graphs (since these entrain many smaller +objects), then on smaller reference-counted object graphs, and then on +any remaining individual objects or small object graphs that don't +entrain other objects. + +Because (1) large graphs of leaked objects tend to include some objects +pointed to by global variables that confuse GC-based leak detectors, +which can make leaks look smaller (as in [bug +99180](https://bugzilla.mozilla.org/show_bug.cgi?id=99180){.external +.text}) or hide them completely and (2) large graphs of leaked objects +tend to hide smaller ones, it's much better to go after the large +graphs of leaks first. + +A good general pattern for finding and fixing leaks is to start with a +task that you want not to leak (for example, reading email). Start +finding and fixing leaks by running part of the task under nsTraceRefcnt +logging, gradually building up from as little as possible to the +complete task, and fixing most of the leaks in the first steps before +adding additional steps. (By most of the leaks, I mean the leaks of +large numbers of different types of objects or leaks of objects that are +known to entrain many non-logged objects such as JS objects. Seeing a +leaked `GlobalWindowImpl`, `nsXULPDGlobalObject`, +`nsXBLDocGlobalObject`, or `nsXPCWrappedJS` is a sign that there could +be significant numbers of JS objects leaked.) + +For example, start with bringing up the mail window and closing the +window without doing anything. Then go on to selecting a folder, then +selecting a message, and then other activities one does while reading +mail. + +Once you've done this, and it doesn't leak much, then try the action +under trace-malloc or LSAN or Valgrind to find the leaks of smaller +graphs of objects. (When I refer to the size of a graph of objects, I'm +referring to the number of objects, not the size in bytes. Leaking many +copies of a string could be a very large leak, but the object graphs are +small and easy to identify using GC-based leak detection.) + +## What leak tools do we have? + +| Tool | Finds | Platforms | Requires | +|------------------------------------------|------------------------------------------------------|---------------------|--------------| +| Leak tools for large object graphs | | | | +| [Leak Gauge](leak_gauge.md) | Windows, documents, and docshells only | All platforms | Any build | +| [GC and CC logs](gc_and_cc_logs.md) | JS objects, DOM objects, many other kinds of objects | All platforms | Any build | +| Leak tools for medium-size object graphs | | | | +| [BloatView](bloatview.md), [refcount tracing and balancing](refcount_tracing_and_balancing.md) | Objects that implement `nsISupports` or use `MOZ_COUNT_{CTOR,DTOR}` | All tier 1 platforms | Debug build (or build opt with `--enable-logrefcnt`)| +| Leak tools for debugging memory growth that is cleaned up on shutdown | | | + +## Common leak patterns + +When trying to find a leak of reference-counted objects, there are a +number of patterns that could cause the leak: + +1. Ownership cycles. The most common source of hard-to-fix leaks is + ownership cycles. If you can avoid creating cycles in the first + place, please do, since it's often hard to be sure to break the + cycle in every last case. Sometimes these cycles extend through JS + objects (discussed further below), and since JS is + garbage-collected, every pointer acts like an owning pointer and the + potential for fan-out is larger. See [bug + 106860](https://bugzilla.mozilla.org/show_bug.cgi?id=106860){.external + .text} and [bug + 84136](https://bugzilla.mozilla.org/show_bug.cgi?id=84136){.external + .text} for examples. (Is this advice still accurate now that we have + a cycle collector? \--Jesse) +2. Dropping a reference on the floor by: + 1. Forgetting to release (because you weren't using `nsCOMPtr` + when you should have been): See [bug + 99180](https://bugzilla.mozilla.org/show_bug.cgi?id=99180){.external + .text} or [bug + 93087](https://bugzilla.mozilla.org/show_bug.cgi?id=93087){.external + .text} for an example or [bug + 28555](https://bugzilla.mozilla.org/show_bug.cgi?id=28555){.external + .text} for a slightly more interesting one. This is also a + frequent problem around early returns when not using `nsCOMPtr`. + 2. Double-AddRef: This happens most often when assigning the result + of a function that returns an AddRefed pointer (bad!) into an + `nsCOMPtr` without using `dont_AddRef()`. See [bug + 76091](https://bugzilla.mozilla.org/show_bug.cgi?id=76091){.external + .text} or [bug + 49648](https://bugzilla.mozilla.org/show_bug.cgi?id=49648){.external + .text} for an example. + 3. \[Obscure\] Double-assignment into the same variable: If you + release a member variable and then assign into it by calling + another function that does the same thing, you can leak the + object assigned into the variable by the inner function. (This + can happen equally with or without `nsCOMPtr`.) See [bug + 38586](https://bugzilla.mozilla.org/show_bug.cgi?id=38586){.external + .text} and [bug + 287847](https://bugzilla.mozilla.org/show_bug.cgi?id=287847){.external + .text} for examples. +3. Dropping a non-refcounted object on the floor (especially one that + owns references to reference counted objects). See [bug + 109671](https://bugzilla.mozilla.org/show_bug.cgi?id=109671){.external + .text} for an example. +4. Destructors that should have been virtual: If you expect to override + an object's destructor (which includes giving a derived class of it + an `nsCOMPtr` member variable) and delete that object through a + pointer to the base class using delete, its destructor better be + virtual. (But we have many virtual destructors in the codebase that + don't need to be -- don't do that.) + +## Debugging leaks that go through XPConnect + +Many large object graphs that leak go through +[XPConnect](http://www.mozilla.org/scriptable/){.external .text}. This +can mean there will be XPConnect wrapper objects showing up as owning +the leaked objects, but it doesn't mean it's XPConnect's fault +(although that [has been known to +happen](https://bugzilla.mozilla.org/show_bug.cgi?id=76102){.external +.text}, it's rare). Debugging leaks that go through XPConnect requires +a basic understanding of what XPConnect does. XPConnect allows an XPCOM +object to be exposed to JavaScript, and it allows certain JavaScript +objects to be exposed to C++ code as normal XPCOM objects. + +When a C++ object is exposed to JavaScript (the more common of the two), +an XPCWrappedNative object is created. This wrapper owns a reference to +the native object until the corresponding JavaScript object is +garbage-collected. This means that if there are leaked GC roots from +which the wrapper is reachable, the wrapper will never release its +reference on the native object. While this can be debugged in detail, +the quickest way to solve these problems is often to simply debug the +leaked JS roots. These roots are printed on shutdown in DEBUG builds, +and the name of the root should give the type of object it is associated +with. + +One of the most common ways one could leak a JS root is by leaking an +`nsXPCWrappedJS` object. This is the wrapper object in the reverse +direction \-- when a JS object is used to implement an XPCOM interface +and be used transparently by native code. The `nsXPCWrappedJS` object +creates a GC root that exists as long as the wrapper does. The wrapper +itself is just a normal reference-counted object, so a leaked +`nsXPCWrappedJS` can be debugged using the normal refcount-balancer +tools. + +If you really need to debug leaks that involve JS objects closely, you +can get detailed printouts of the paths JS uses to mark objects when it +is determining the set of live objects by using the functions added in +[bug +378261](https://bugzilla.mozilla.org/show_bug.cgi?id=378261){.external +.text} and [bug +378255](https://bugzilla.mozilla.org/show_bug.cgi?id=378255){.external +.text}. (More documentation of this replacement for GC_MARK_DEBUG, the +old way of doing it, would be useful. It may just involve setting the +`XPC_SHUTDOWN_HEAP_DUMP` environment variable to a file name, but I +haven't tested that.) + +## Post-processing of stack traces + +On Mac and Linux, the stack traces generated by our internal debugging +tools don't have very good symbol information (since they just show the +results of `dladdr`). The stacks can be significantly improved (better +symbols, and file name / line number information) by post-processing. +Stacks can be piped through the script `tools/rb/fix_stacks.py` to do +this. These scripts are designed to be run on balance trees in addition +to raw stacks; since they are rather slow, it is often **much faster** +to generate balance trees (e.g., using `make-tree.pl` for the refcount +balancer or `diffbloatdump.pl --use-address` for trace-malloc) and*then* +run the balance trees (which are much smaller) through the +post-processing. + +## Getting symbol information for system libraries + +### Windows + +Setting the environment variable `_NT_SYMBOL_PATH` to something like +`symsrv*symsrv.dll*f:\localsymbols*http://msdl.microsoft.com/download/symbols` +as described in [Microsoft's +article](http://support.microsoft.com/kb/311503){.external .text}. This +needs to be done when running, since we do the address to symbol mapping +at runtime. + +### Linux + +Many Linux distros provide packages containing external debugging +symbols for system libraries. `fix_stacks.py` uses this debugging +information (although it does not verify that they match the library +versions on the system). + +For example, on Fedora, these are in \*-debuginfo RPMs (which are +available in yum repositories that are disabled by default, but easily +enabled by editing the system configuration). + +## Tips + +### Disabling Arena Allocation + +With many lower-level leak tools (particularly trace-malloc based ones, +like leaksoup) it can be helpful to disable arena allocation of objects +that you're interested in, when possible, so that each object is +allocated with a separate call to malloc. Some places you can do this +are: + +layout engine +: Define `DEBUG_TRACEMALLOC_FRAMEARENA` where it is commented out in + `layout/base/nsPresShell.cpp` + +glib +: Set the environment variable `G_SLICE=always-malloc` + +## Other References + +- [Performance + tools](https://wiki.mozilla.org/Performance:Tools "Performance:Tools") +- [Leak Debugging Screencasts](https://dbaron.org/mozilla/leak-screencasts/){.external + .text} +- [LeakingPages](https://wiki.mozilla.org/LeakingPages "LeakingPages") - + a list of pages known to leak +- [mdc:Performance](https://developer.mozilla.org/en/Performance "mdc:Performance"){.extiw} - + contains documentation for all of our memory profiling and leak + detection tools diff --git a/docs/performance/memory/memory.md b/docs/performance/memory/memory.md new file mode 100644 index 0000000000..d571fb6b9c --- /dev/null +++ b/docs/performance/memory/memory.md @@ -0,0 +1,64 @@ +# Memory Tools + +The Memory tool lets you take a snapshot of the current tab's memory +[heap](https://en.wikipedia.org/wiki/Memory_management#HEAP). +It then provides a number of views of the heap that can +show you which objects account for memory usage and exactly where in +your code you are allocating memory. + +<iframe width="595" height="325" src="https://www.youtube.com/embed/DJLoq5E5ww0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe> + +------------------------------------------------------------------------ + +## The basics +- Opening [the memory + tool](basic_operations.md#opening-the-memory-tool) +- [Taking a heap + snapshot](basic_operations.md#saving-and-loading-snapshots) +- [Comparing two + snapshots](basic_operations.md#comparing-snapshots) +- [Deleting + snapshots](basic_operations.md#clearing-a-snapshot) +- [Saving and loading + snapshots](basic_operations.md#saving-and-loading-snapshots) +- [Recording call + stacks](basic_operations.md#recording-call-stacks) + +------------------------------------------------------------------------ + +## Analyzing snapshots + +The Tree map view is new in Firefox 48, and the Dominators view is new +in Firefox 46. + +Once you've taken a snapshot, there are three main views the Memory +tool provides: + +- [the Tree map view](tree_map_view.md) shows + memory usage as a + [treemap](https://en.wikipedia.org/wiki/Treemapping). +- [the Aggregate view](aggregate_view.md) shows + memory usage as a table of allocated types. +- [the Dominators view](dominators_view.md) + shows the "retained size" of objects: that is, the size of objects + plus the size of other objects that they keep alive through + references. + +If you've opted to record allocation stacks for the snapshot, the +Aggregate and Dominators views can show you exactly where in your code +allocations are happening. + +------------------------------------------------------------------------ + +## Concepts + +- What are [Dominators](dominators.md)? + +------------------------------------------------------------------------ + +## Example pages + +Examples used in the Memory tool documentation. + +- The [Monster example](monster_example.md) +- The [DOM allocation example](DOM_allocation_example.md) diff --git a/docs/performance/memory/monster_example.md b/docs/performance/memory/monster_example.md new file mode 100644 index 0000000000..d351803a8d --- /dev/null +++ b/docs/performance/memory/monster_example.md @@ -0,0 +1,79 @@ +# Monster example slug + +This article describes a very simple web page that we'll use to +illustrate some features of the Memory tool. + +You can try the site at +<https://mdn.github.io/performance-scenarios/js-allocs/alloc.html>. +Heres the code: + +```js +var MONSTER_COUNT = 5000; +var MIN_NAME_LENGTH = 2; +var MAX_NAME_LENGTH = 48; + +function Monster() { + + function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + function randomName() { + var chars = "abcdefghijklmnopqrstuvwxyz"; + var nameLength = randomInt(MIN_NAME_LENGTH, MAX_NAME_LENGTH); + var name = ""; + for (var j = 0; j < nameLength; j++) { + name += chars[randomInt(0, chars.length-1)]; + } + return name; + } + + this.name = randomName(); + this.eyeCount = randomInt(0, 25); + this.tentacleCount = randomInt(0, 250); +} + +function makeMonsters() { + var monsters = { + "friendly": [], + "fierce": [], + "undecided": [] + }; + + for (var i = 0; i < MONSTER_COUNT; i++) { + monsters.friendly.push(new Monster()); + } + + for (var i = 0; i < MONSTER_COUNT; i++) { + monsters.fierce.push(new Monster()); + } + + for (var i = 0; i < MONSTER_COUNT; i++) { + monsters.undecided.push(new Monster()); + } + + console.log(monsters); +} + +var makeMonstersButton = document.getElementById("make-monsters"); +makeMonstersButton.addEventListener("click", makeMonsters); +``` + +The page contains a button: when you push the button, the code creates +some monsters. Specifically: + +- the code creates an object with three properties, each an array: + - one for fierce monsters + - one for friendly monsters + - one for monsters who haven't decided yet. +- for each array, the code creates and appends 5000 + randomly-initialized monsters. Each monster has: + - a string, for the monster's name + - a number representing the number of eyes it has + - a number representing the number of tentacles it has. + +So the structure of the memory allocated on the JavaScript heap is an +object containing three arrays, each containing 5000 objects (monsters), +each object containing a string and two integers: + +[![](../img/monsters.svg)] diff --git a/docs/performance/memory/refcount_tracing_and_balancing.md b/docs/performance/memory/refcount_tracing_and_balancing.md new file mode 100644 index 0000000000..fe3e3c7ae4 --- /dev/null +++ b/docs/performance/memory/refcount_tracing_and_balancing.md @@ -0,0 +1,235 @@ +# Refcount Tracing and Balancing + +Refcount tracing and balancing are advanced techniques for tracking down +leak of refcounted objects found with +[BloatView](bloatview.md). The first step +is to run Firefox with refcount tracing enabled, which produces one or +more log files. Refcount tracing logs calls to `Addref` and `Release`, +preferably for a particular set of classes, including call-stacks in +symbolic form (on platforms that support this). Refcount balancing is a +follow-up step that analyzes the resulting log to help a developer +figure out where refcounting went wrong. + +## How to build for refcount tracing + +Build with `--enable-debug` or `--enable-logrefcnt`. + +## How to run with refcount tracing on + +There are several environment variables that can be used. + +First, you select one of three environment variables to choose what kind +of logging you want. You almost certainly want `XPCOM_MEM_REFCNT_LOG`. + +NOTE: Due to an issue with the sandbox on Windows (bug +[1345568](https://bugzilla.mozilla.org/show_bug.cgi?id=1345568) +refcount logging currently requires the MOZ_DISABLE_CONTENT_SANDBOX +environment variable to be set. + +`XPCOM_MEM_REFCNT_LOG` + +Setting this environment variable enables refcount tracing. If you set +this environment variable to the name of a file, the log will be output +to that file. You can also set it to 1 to log to stdout or 2 to log to +stderr, but these logs are large and expensive to capture, so you +probably don't want to do that. **WARNING**: you should never use this +without `XPCOM_MEM_LOG_CLASSES` and/or `XPCOM_MEM_LOG_OBJECTS`, because +without some filtering the logging will be completely useless due to how +slow the browser will run and how large the logs it produces will be. + +`XPCOM_MEM_COMPTR_LOG` + +This environment variable enables logging of additions and releases of +objects into `nsCOMPtr`s. This requires C++ dynamic casts, so it is not +supported on all platforms. However, having an nsCOMPtr log and using it +in the creation of the balance tree allows AddRef and Release calls that +we know are matched to be eliminated from the tree, so it makes it much +easier to debug reference count leaks of objects that have a large +amount of reference counting traffic. + +`XPCOM_MEM_ALLOC_LOG` + +For platforms that don't have stack-crawl support, XPCOM supports +logging at the call site to `AddRef`/`Release` using the usual cpp +`__FILE__` and __LINE__ number macro expansion hackery. This results +in slower code, but at least you get some data about where the leaks +might be occurring from. + +You must also set one or two additional environment variables, +`XPCOM_MEM_LOG_CLASSES` and `XPCOM_MEM_LOG_OBJECTS,` to reduce the set +of objects being logged, in order to improve performance to something +vaguely tolerable. + +`XPCOM_MEM_LOG_CLASSES` + +This variable should contain a comma-separated list of names which will +be used to compare against the types of the objects being logged. For +example: + + env XPCOM_MEM_LOG_CLASSES=nsDocShell XPCOM_MEM_REFCNT_LOG=./refcounts.log ./mach run + +This will log the `AddRef` and `Release` calls only for instances of +`nsDocShell` while running the browser using `mach`, to a file +`refcounts.log`. Note that setting `XPCOM_MEM_LOG_CLASSES` will also +list the *serial number* of each object that leaked in the "bloat log" +(that is, the file specified by the `XPCOM_MEM_BLOAT_LOG` variable; see +[the BloatView documentation](bloatview.md) +for more details). An object's serial number is simply a unique number, +starting at one, that is assigned to the object when it is allocated. + +You may use an object's serial number with the following variable to +further restrict the reference count tracing: + + XPCOM_MEM_LOG_OBJECTS + +Set this variable to a comma-separated list of object *serial number* or +ranges of *serial number*, e.g., `1,37-42,73,165` (serial numbers start +from 1, not 0). When this is set, along with `XPCOM_MEM_LOG_CLASSES` and +`XPCOM_MEM_REFCNT_LOG`, a stack track will be generated for *only* the +specific objects that you list. For example, + + env XPCOM_MEM_LOG_CLASSES=nsDocShell XPCOM_MEM_LOG_OBJECTS=2 XPCOM_MEM_REFCNT_LOG=./refcounts.log ./mach run + +will log stack traces to `refcounts.log` for the 2nd `nsDocShell` object +that gets allocated, and nothing else. + +## **Post-processing step 1: finding the leakers** + +First you have to figure out which objects leaked. The script +`tools/rb/find_leakers.py` does this. It grovels through the log file, +and figures out which objects got allocated (it knows because they were +just allocated because they got `AddRef()`-ed and their refcount became +1). It adds them to a list. When it finds an object that got freed (it +knows because its refcount goes to 0), it removes it from the list. +Anything left over is leaked. + +The scripts output looks like the following. + + 0x00253ab0 (1) + 0x00253ae0 (2) + 0x00253bd0 (4) + +The number in parentheses indicates the order in which it was allocated, +if you care. Pick one of these pointers for use with Step 2. + +## Post-processing step 2: filtering the log + +Once you've picked an object that leaked, you can use +`tools/rb/filter-log.pl` to filter the log file to drop the call +stack for other objects; This process reduces the size of the log file +and also improves the performance. + + perl -w tools/rb/filter-log.pl --object 0x00253ab0 < ./refcounts.log > my-leak.log + +### Symbolicating stacks + +The log files often lack function names, file +names and line numbers. You'll need to run a script to fix the call +stack. + + python3 tools/rb/fix_stacks.py < ./refcounts.log > fixed_stack.log + +Also, it is possible to [locally symbolicate](/contributing/debugging/local_symbols.rst) +logs generated on TreeHerder. + +## **Post-processing step 3: building the balance tree** + +Now that you've the log file fully prepared, you can build a *balance +tree*. This process takes all the stack `AddRef()` and `Release()` stack +traces and munges them into a call graph. Each node in the graph +represents a call site. Each call site has a *balance factor*, which is +positive if more `AddRef()`s than `Release()`es have happened at the +site, zero if the number of `AddRef()`s and `Release()`es are equal, and +negative if more `Release()`es than `AddRef()`s have happened at the +site. + +To build the balance tree, run `tools/rb/make-tree.pl`, specifying the +object of interest. For example: + + perl -w tools/rb/make-tree.pl --object 0x00253ab0 < my-leak.log + +This will build an indented tree that looks something like this (except +probably a lot larger and leafier): + + .root: bal=1 + main: bal=1 + DoSomethingWithFooAndReturnItToo: bal=2 + NS_NewFoo: bal=1 + +Let's pretend in our toy example that `NS_NewFoo()` is a factory method +that makes a new foo and returns it. +`DoSomethingWithFooAndReturnItToo()` is a method that munges the foo +before returning it to `main()`, the main program. + +What this little tree is telling you is that you leak *one refcount* +overall on object `0x00253ab0`. But, more specifically, it shows you +that: + +- `NS_NewFoo()` "leaks" a refcount. This is probably "okay" + because it's a factory method that creates an `AddRef()`-ed object. +- `DoSomethingWithFooAndReturnItToo()` leaks *two* refcounts. + Hmm...this probably isn't okay, especially because... +- `main()` is back down to leaking *one* refcount. + +So from this, we can deduce that `main()` is correctly releasing the +refcount that it got on the object returned from +`DoSomethingWithFooAndReturnItToo()`, so the leak *must* be somewhere in +that function. + +So now say we go fix the leak in `DoSomethingWithFooAndReturnItToo()`, +re-run our trace, grovel through the log by hand to find the object that +corresponds to `0x00253ab0` in the new run, and run `make-tree.pl`. What +we'd hope to see is a tree that looks like: + + .root: bal=0 + main: bal=0 + DoSomethingWithFooAndReturnItToo: bal=1 + NS_NewFoo: bal=1 + +That is, `NS_NewFoo()` "leaks" a single reference count; this leak is +"inherited" by `DoSomethingWithFooAndReturnItToo()`; but is finally +balanced by a `Release()` in `main()`. + +## Hints + +Clearly, this is an iterative and analytical process. Here are some +tricks that make it easier. + +**Check for leaks from smart pointers.** If the leak comes from a smart +pointer that is logged in the XPCOM_MEM_COMPTR_LOG, then +find-comptr-leakers.pl will find the exact stack for you, and you don't +have to look at trees. + +**Ignore balanced trees**. The `make-tree.pl` script accepts an option +`--ignore-balanced`, which tells it *not* to bother printing out the +children of a node whose balance factor is zero. This can help remove +some of the clutter from an otherwise noisy tree. + +**Ignore matched releases from smart pointers.** If you've checked (see +above) that the leak wasn't from a smart pointer, you can ignore the +references that came from smart pointers (where we can use the pointer +identity of the smart pointer to match the AddRef and the Release). This +requires using an XPCOM_MEM_REFCNT_LOG and an XPCOM_MEM_COMPTR_LOG that +were collected at the same time. For more details, see the [old +documentation](http://www-archive.mozilla.org/performance/leak-tutorial.html) +(which should probably be incorporated here). This is best used with +`--ignore-balanced` + +**Play Mah Jongg**. An unbalanced tree is not necessarily an evil thing. +More likely, it indicates that one `AddRef()` is cancelled by another +`Release()` somewhere else in the code. So the game is to try to match +them with one another. + +**Exclude Functions.** To aid in this process, you can create an +"excludes file", that lists the name of functions that you want to +exclude from the tree building process (presumably because you've +matched them). `make-tree.pl` has an option `--exclude [file]`, where +`[file]` is a newline-separated list of function names that will be +*excluded* from consideration while building the tree. Specifically, any +call stack that contains that call site will not contribute to the +computation of balance factors in the tree. + +## How to instrument your objects for refcount tracing and balancing + +The process is the same as instrumenting them for BloatView because BloatView +and refcount tracing share underlying infrastructure. diff --git a/docs/performance/memory/tree_map_view.md b/docs/performance/memory/tree_map_view.md new file mode 100644 index 0000000000..30d9968db6 --- /dev/null +++ b/docs/performance/memory/tree_map_view.md @@ -0,0 +1,62 @@ +# Tree map view + +The Tree map view is new in Firefox 48. + +The Tree map view provides a visual representation of the snapshot, that +helps you quickly get an idea of which objects are using the most +memory. + +A treemap displays [\"hierarchical (tree-structured) data as a set of +nested rectangles\"](https://en.wikipedia.org/wiki/Treemapping). The +size of the rectangles corresponds to some quantitative aspect of the +data. + +For the treemaps shown in the Memory tool, things on the heap are +divided at the top level into four categories: + +- **objects**: JavaScript and DOM objects, such as `Function`, + `Object`, or `Array`, and DOM types like `Window` and + `HTMLDivElement`. +- **scripts**: JavaScript sources loaded by the page. +- **strings** +- **other**: this includes internal + [SpiderMonkey](https://developer.mozilla.org/en-US/docs/Tools/Tools_Toolbox#settings/en-US/docs/Mozilla/Projects/SpiderMonkey) objects. + +Each category is represented with a rectangle, and the size of the +rectangle corresponds to the proportion of the heap occupied by items in +that category. This means you can quickly get an idea of roughly what +sorts of things allocated by your site are using the most memory. + +Within top-level categories: + +- **objects** is further divided by the object's type. +- **scripts** is further subdivided by the script's origin. It also + includes a separate rectangle for code that can't be correlated + with a file, such as JIT-optimized code. +- **other** is further subdivided by the object's type. + +Here are some example snapshots, as they appear in the Tree map view: + +![](../img/treemap-domnodes.png) + +This treemap is from the [DOM allocation +example](DOM_allocation_example.md), which runs a +script that creates a large number of DOM nodes (200 `HTMLDivElement` +objects and 4000 `HTMLSpanElement` objects). You can see how almost all +the heap usage is from the `HTMLSpanElement` objects that it creates. + +![](../img/treemap-monsters.png) + +This treemap is from the [monster allocation +example](monster_example.md), which creates three +arrays, each containing 5000 monsters, each monster having a +randomly-generated name. You can see that most of the heap is occupied +by the strings used for the monsters' names, and the objects used to +contain the monsters' other attributes. + +![](../img/treemap-bbc.png) + +This treemap is from <http://www.bbc.com/>, and is probably more +representative of real life than the examples. You can see the much +larger proportion of the heap occupied by scripts, that are loaded from +a large number of origins. diff --git a/docs/performance/perf.md b/docs/performance/perf.md new file mode 100644 index 0000000000..47177c3cfd --- /dev/null +++ b/docs/performance/perf.md @@ -0,0 +1,57 @@ +# Perf + +`perf` is a powerful system-wide instrumentation service that is part of +Linux. This article discusses how it can be relevant to power profiling. + +**Note**: The [power profiling +overview](power_profiling_overview.md) is +worth reading at this point if you haven't already. It may make parts +of this document easier to understand. + +## Energy estimates + +`perf` can access the Intel RAPL energy estimates. The following example +shows how to invoke it for this purpose. + +``` +sudo perf stat -a -r 1 \ + -e "power/energy-pkg/" \ + -e "power/energy-cores/" \ + -e "power/energy-gpu/" \ + -e "power/energy-ram/" \ + <command> +``` + +The `-a` is necessary; it means \"all cores\", and without it all the +measurements will be zero. The `-r 1` means `<command>` is executed +once; higher values can be used to get variations. + +The output will look like the following. + +``` +Performance counter stats for 'system wide': + + 51.58 Joules power/energy-pkg/ [100.00%] + 14.80 Joules power/energy-cores/ [100.00%] + 9.93 Joules power/energy-gpu/ [100.00%] + 27.38 Joules power/energy-ram/ [100.00%] + +5.003049064 seconds time elapsed +``` + +It's not clear from the output, but the following relationship holds. + +``` +energy-pkg >= energy-cores + energy-gpu +``` + +The measurement is in Joules, which is usually less useful than Watts. + +For these reasons +[rapl](tools_power_rapl.md) is usually a +better tool for measuring power consumption on Linux. + +## Wakeups {#Wakeups} + +`perf` can also be used to do [high-context profiling of +wakeups](http://robertovitillo.com/2014/02/04/idle-wakeups-are-evil/). diff --git a/docs/performance/perfstats.md b/docs/performance/perfstats.md new file mode 100644 index 0000000000..6ffaa55da9 --- /dev/null +++ b/docs/performance/perfstats.md @@ -0,0 +1,30 @@ +# PerfStats + +PerfStats is a framework for the low-overhead selective collection of internal performance metrics. +The results are accessible through ChromeUtils, Browsertime output, and in select performance tests. + +## Adding a new PerfStat +Define the new PerfStat by adding it to [this list](https://searchfox.org/mozilla-central/rev/b1e5f2c7c96be36974262551978d54f457db2cae/tools/performance/PerfStats.h#34-53) in [`PerfStats.h`](https://searchfox.org/mozilla-central/rev/52da19becaa3805e7f64088e91e9dade7dec43c8/tools/performance/PerfStats.h). +Then, in C++ code, wrap execution in an RAII object, e.g. +``` +PerfStats::AutoMetricRecording<PerfStats::Metric::MyMetric>() +``` +or call the following function manually: +``` +PerfStats::RecordMeasurement(PerfStats::Metric::MyMetric, Start, End) +``` +For incrementing counters, use the following: +``` +PerfStats::RecordMeasurementCount(PerfStats::Metric::MyMetric, incrementCount) +``` + +[Here's an example of a patch where a new PerfStat was added and used.](https://hg.mozilla.org/mozilla-central/rev/3e85a73d1fa5c816fdaead66ecee603b38f9b725) + +## Enabling collection +To enable collection, use `ChromeUtils.SetPerfStatsCollectionMask(MetricMask mask)`, where `mask=0` disables all metrics and `mask=0xFFFFFFFF` enables all of them. +`MetricMask` is a bitmask based on `Metric`, i.e. `Metric::LayerBuilding (2)` is synonymous to `1 << 2` in `MetricMask`. + +## Accessing results +Results can be accessed with `ChromeUtils.CollectPerfStats()`. +The Browsertime test framework will sum results across processes and report them in its output. +The raptor-browsertime Windows essential pageload tests also collect all PerfStats. diff --git a/docs/performance/platform_microbenchmarks/platform_microbenchmarks.md b/docs/performance/platform_microbenchmarks/platform_microbenchmarks.md new file mode 100644 index 0000000000..761cd0f30d --- /dev/null +++ b/docs/performance/platform_microbenchmarks/platform_microbenchmarks.md @@ -0,0 +1,21 @@ +# Platform microbenchmarks + +Platform microbenchmarks benchmarks specific low-level operations used +by the gecko platform. If a test regresses, it could result in the +degradation in the performance of some user-visible feature. + +The list of tests and their descriptions is currently incomplete. If +something is missing, please search for it in the gecko source and +update this page (or ask the original author to do so, if you're still +not sure). + +## String tests + +* PerfStripWhitespace +* PerfCompressWhitespace +* PerfStripCharsWhitespace +* PerfStripCRLF +* PerfStripCharsCRLF + +These tests measure the amount of time it takes to perform a large +number of operations on low-level strings. diff --git a/docs/performance/power_profiling_overview.md b/docs/performance/power_profiling_overview.md new file mode 100644 index 0000000000..bb8f511fe2 --- /dev/null +++ b/docs/performance/power_profiling_overview.md @@ -0,0 +1,326 @@ +# Power profiling + +This article covers important background information about power +profiling, with an emphasis on Intel processors used in desktop and +laptop machines. It serves as a starting point for anybody doing power +profiling for the first time. + +## Basic physics concepts + +In physics, *[power](https://en.wikipedia.org/wiki/Power_%28physics%29)* +is the rate of doing +*[work](https://en.wikipedia.org/wiki/Work_%28physics%29 "Work (physics)")*. +It is equivalent to an amount of +*[energy](https://en.wikipedia.org/wiki/Energy_%28physics%29 "Energy (physics)"){.mw-redirect}* +consumed per unit time. In SI units, energy is measured in Joules, and +power is measured in Watts, which is equivalent to Joules per second. + +Although power is an instantaneous concept, in practice measurements of +it are determined in a non-instantaneous fashion, i.e. by dividing an +energy amount by a non-infinitesimal time period. Strictly speaking, +such a computation gives the *average power* but this is often referred +to as just the *power* when context makes it clear. + +In the context of computing, a fully-charged mobile device battery (as +found in a laptop or smartphone) holds a certain amount of energy, and +the speed at which that stored energy is depleted depends on the power +consumption of the mobile device. That in turn depends on the software +running on the device. Web browsers are popular applications and can be +power-intensive, and therefore can significantly affect battery life. As +a result, it is worth optimizing (i.e. reducing) the power consumption +caused by Firefox and Firefox OS. + +## Intel processor basics + +### Processor layout + +The following diagram (from the [Intel Power Governor +documentation)](https://software.intel.com/en-us/articles/intel-power-governor) +shows how machines using recent Intel processors are constructed. + +![](img/power-planes.jpg) + +The important points are as follows. + +- The processor has one or more *packages*. These are part of the + actual processor that you buy from Intel. Client processors (e.g. + Core i3/i5/i7) have one package. Server processors (e.g. Xeon) + typically have two or more packages. +- Each package contains multiple *cores*. +- Each core typically has + [hyper-threading](https://en.wikipedia.org/wiki/Hyper-threading), + which means it contains two logical *CPUs*. +- The part of the package outside the cores is called the [*uncore* or + *system agent*](https://en.wikipedia.org/wiki/Uncore)*.* It includes + various components including the L3 cache, memory controller, and, + for processors that have one, the integrated GPU. +- RAM is separate from the processor. + +### C-states + +Intel processors have aggressive power-saving features. The first is the +ability to switch frequently (thousands of times per second) between +active and idle states, and there are actually several different kinds +of idle states. These different states are called +*[C-states](https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states).* +C0 is the active/busy state, where instructions are being executed. The +other states have higher numbers and reflect increasing deeper idle +states. The deeper an idle state is, the less power it uses, but the +longer it takes to wake up from. + +Note: the [ACPI +standard](https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface) +specifies four states, C0, C1, C2 and C3. Intel maps these to +processor-specific states such as C0, C1, C2, C6 and C7. and many tools +report C-states using the latter names. The exact relationship is +confusing, and chapter 13 of the [Intel optimization +manual](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html) +has more details. The important thing is that C0 is always the active +state, and for the idle states a higher number always means less power +consumption. + +The other thing to note about C-states is that they apply both to cores +and the entire package --- i.e. if all cores are idle then the entire +package can also become idle, which reduces power consumption even +further. + +The fraction of time that a package or core spends in an idle C-state is +called the *C-state residency*. This is a misleading term --- the active +state, C0, is also a C-state --- but one that is nonetheless common. + +Intel processors have model-specific registers (MSRs) containing +measurements of how much time is spent in different C-states, and tools +such as [powermetrics](powermetrics.md) +(Mac), powertop and +[turbostat](turbostat.md) (Linux) can +expose this information. + +A *wakeup* occurs when a core or package transitions from an idle state +to the active state. This happens when the OS schedules a process to run +due to some kind of event. Common causes of wakeups include scheduled +timers going off and blocked I/O system calls receiving data. +Maintaining C-state residency is crucial to keep power consumption low, +and so reducing wakeup frequency is one of the best ways to reduce power +consumption. + +One consequence of the existence of C-states is that observations made +during power profiling --- even more than with other kinds of profiling +--- can disturb what is being observed. For example, the Gecko Profiler +takes samples at 1000Hz using a timer. Each of these samples can trigger +a wakeup, which consumes power and obscures Firefox's natural wakeup +patterns. For this reason, integrating power measurements into the Gecko +Profiler is unlikely to be useful, and other power profiling tools +typically use much lower sampling rates (e.g. 1Hz.) + +### P-states + +Intel processors also support multiple *P-states*. P0 is the state where +the processor is operating at maximum frequency and voltage, and +higher-numbered P-states operate at a lower frequency and voltage to +reduce power consumption. Processors can have dozens of P-states, but +the transitions are controlled by the hardware and OS and so P-states +are of less interest to application developers than C-states. + +## Power and power-related measurements + +There are several kinds of power and power-related measurements. Some +are global (whole-system) and some are per-process. The following +sections list them from best to worst. + +### Power measurements + +The best measurements are measured in joules and/or watts, and are taken +by measuring the actual hardware in some fashion. These are global +(whole-system) measurements that are affected by running programs but +also by other things such as (for laptops) how bright the monitor +backlight is. + +- Devices such as ammeters give the best results, but these can be + expensive and difficult to set up. +- A cruder technique that works with mobile machines and devices is to + run a program for a long time and simply time how long it takes for + the battery to drain. The long measurement times required are a + disadvantage, though. + +### Power estimates + +The next best measurements come from recent (Sandy Bridge and later) +Intel processors that implement the *RAPL* (Running Average Power Limit) +interface that provides MSRs containing energy consumption estimates for +up to four *power planes* or *domains* of a machine, as seen in the +diagram above. + +- PKG: The entire package. + - PP0: The cores. + - PP1: An uncore device, usually the GPU (not available on all + processor models.) +- DRAM: main memory (not available on all processor models.) + +The following relationship holds: PP0 + PP1 \<= PKG. DRAM is independent +of the other three domains. + +These values are computed using a power model that uses +processor-internal counts as inputs, and they have been +[verified](http://www.computer.org/csdl/proceedings/ispass/2013/5776/00/06557170.pdf) +as being fairly accurate. They are also updated frequently, at +approximately 1,000 Hz, though the variability in their update latency +means that they are probably only accurate at lower frequencies, e.g. up +to 20 Hz or so. See section 14.9 of Volume 3 of the [Intel Software +Developer's +Manual](http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html) +for more details about RAPL. + +Tools that can take RAPL readings include the following. + +- `tools/power/rapl`: all planes; Linux and Mac. +- [Intel Power + Gadget](intel_power_gadget.md): PKG and + PP0 planes; Windows, Mac and Linux. +- [powermetrics](powermetrics.md): PKG + plane; Mac. +- [perf](perf.md): all planes; Linux. +- [turbostat](turbostat.md): PKG, PP0 and + PP1 planes; Linux. + +Of these, +[tools/power/rapl](tools_power_rapl.md) is +generally the easiest and best to use because it reads all power planes, +it's a command line utility, and it doesn't measure anything else. + +### Proxy measurements + +The next best measurements are proxy measurements, i.e. measurements of +things that affect power consumption such as CPU activity, GPU activity, +wakeup frequency, C-state residency, disk activity, and network +activity. Some of these are measured on a global basis, and some can be +measured on a per-process basis. Some can also be measured via +instrumentation within Firefox itself. + +The correlation between each proxy measure and power consumption is hard +to know and can vary greatly. When used carefully, however, they can +still be useful. This is because they can often be measured in a more +fine-grained fashion than power measurements and estimates, which is +vital for gaining insight into how a program can reduce power +consumption. + +Most profiling tools provide at least some proxy measurements. + +### Hybrid proxy measurements + +These are combinations of proxy measurements. The combinations are +semi-arbitrary, they amplify the unreliability of proxy measurements, +and unlike non-hybrid proxy measurements, they don't have a clear +physical meaning. Avoid them. + +The most notable example of a hybrid proxy measurement is the ["Energy +Impact" used by OS X's Activity +[Monitor](activity_monitor_and_top.md#What-does-Energy-Impact-measure). + +## Ways to user power-related measurements + +### Low-context measurements + +Most power-related measurements are global or per-process. Such +low-context measurements are typically good for understand *if* power +consumption is good or bad, but in the latter case they often don't +provide much insight into why the problem is occurring, which part of +the code is at fault, or how it can be fixed. Nonetheless, they can +still help improve understanding of a problem by using *differential +profiling*. + +- Compare browsers to see if Firefox is doing better or worse than + another browser on a particular workload. +- Compare different versions of Firefox to see if Firefox has improved + or worsened over time on a particular workload. This can identify + specific changes that caused regressions, for example. +- Compare different configurations of Firefox to see if a particular + feature is affecting things. +- Compare different workloads. This can be particularly useful if the + workloads only vary slightly. For example, it can be useful to + gradually remove elements from a web page and see how the + power-related measurements change. Even just switching a tab from + the foreground to the background can make a difference. + +### High-context measurements + +A few power-related measurements can be obtained in a high-context +fashion, e.g. with stack traces that clearly pinpoint specific parts of +the code as being responsible. + +- Standard performance profiling tools that measure CPU usage or + proxies of CPU usage (such as instruction counts) typically provide + high-context measurements. This is useful because high CPU usage + typically causes high power consumption. +- Some tools can provide high-context wakeup measurements: + [dtrace](dtrace.md) (on Mac) and + [perf](perf.md) (on Linux.) +- Source-level instrumentation, such as [TimerFirings + logging](timerfirings_logging.md), can + identify which timers are firing frequently. + +## Power profiling how-to + +This section aims to put together all the above information and provide +a set of strategies for finding, diagnosing and fixing cases of high +power consumption. + +- First of all, all measurements are best done on a quiet machine that + is running little other than the program of interest. Global + measurements in particular can be completely skewed and unreliable + if this is not the case. +- Find or confirm a test case where Firefox's power consumption is + high. "High" can most easily be gauged by comparing against other + browsers. Use power measurements or estimates (e.g. via + [tools/power/rapl](tools_power_rapl.md), + or `mach power` on Mac, or [Intel Power + Gadget](intel_power_gadget.md) on + Windows) for the comparisons. Avoid lower-quality measurements, + especially Activity Monitor's "Energy Impact". +- Try using differential profiling to narrow down the cause. + - Try turning hardware acceleration on or off; e10s on or off; + Flash on or off. + - Try putting the relevant tab in the foreground vs. in the + background. + - If the problem manifests on a particular website, try saving a + local copy of the site and then manually removing HTML elements + to see if a particular page feature is causing the problem +- Many power problems are caused by either high CPU usage or high + wakeup frequency. Use one of the low-context tools to determine if + this is the case (e.g. on Mac use + [powermetrics](powermetrics.md).) If + so, follow that up by using a tool that gives high-context + measurements, which hopefully will identify the cause of the + problem. + - For high CPU usage, many profilers can be used: Firefox's dev + tools profiler, the Gecko Profiler, or generic performance + profilers. + - For high wakeup counts, use + [dtrace](dtrace.md) or + [perf](perf.md) or [TimerFirings logging](timerfirings_logging.md). +- On Mac workloads that use graphics, Activity Monitor's "Energy" + tab can tell you if the high-performance GPU is being used, which + uses more power than the integrated GPU. +- If neither CPU usage nor wakeup frequency identifies the problem, + more ingenuity may be needed. Looking at other measurements (C-state + residency, GPU usage, etc.) may be helpful. +- Animations are sometimes the cause of high power consumption. The + [animation + inspector](/devtools-user/page_inspector/how_to/work_with_animations/index.rst#animation-inspector) + in the Firefox Devtools can identify them. Alternatively, [here is + an + explanation](https://bugzilla.mozilla.org/show_bug.cgi?id=1190721#c10) + of how one developer diagnosed two animation-related problems the + hard way (which required genuine platform expertise). +- The approximate cause of power problems often isn't that hard to + find. Fixing them is often the hard part. Good luck. +- If you do fix a problem by improving a proxy measurement, you should + verify that it also improves a power measurement or estimate. That + way you know the fix had a genuine effect. + +## Further reading + +Chapter 13 of the [Intel optimization +manual](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html) +has many details about optimizing for power consumption. Section 13.5 +("Tuning Software for Intelligent Power Consumption") in particular is +worth reading. diff --git a/docs/performance/powermetrics.md b/docs/performance/powermetrics.md new file mode 100644 index 0000000000..44df0eda9c --- /dev/null +++ b/docs/performance/powermetrics.md @@ -0,0 +1,167 @@ +# powermetrics + +`powermetrics` is a Mac-only command-line utility that provides many +high-quality power-related measurements. It is most useful for getting +CPU, GPU and wakeup measurements in a precise and easily scriptable +fashion (unlike [Activity Monitor and +top](activity_monitor_and_top.md)) +especially in combination with +[rapl](tools_power_rapl.md) via the +`mach power` command. This document describes the version of +`powermetrics` that comes with Mac OS 10.10. The one that comes with +10.9 is less powerful. + +**Note**: The [power profiling +overview](power_profiling_overview.md) is +worth reading at this point if you haven\'t already. It may make parts +of this document easier to understand. + +## Quick start + +`powermetrics` provides a vast number of measurements. The following +command encompasses the most useful ones: + +sudo powermetrics --samplers tasks --show-process-coalition --show-process-gpu -n 1 -i 5000 + +- `--samplers tasks` tells it to just do per-process measurements. +- `--show-process-coalition`` `tells it to group *coalitions* of + related processes, e.g. the Firefox parent process and child + processes. +- `--show-process-gpu` tells it to show per-process GPU measurements. +- `-n 1` tells it to take one sample and then stop. +- `-i 5000` tells it to use a sample length of 5 seconds (5000 ms). + Change this number to get shorter or longer samples. + +The following is example output from such an invocation: + + *** Sampled system activity (Fri Sep 4 17:15:14 2015 +1000) (5009.63ms elapsed) *** + + *** Running tasks *** + + Name ID CPU ms/s User% Deadlines (<2 ms, 2-5 ms) Wakeups (Intr, Pkg idle) GPU ms/s + com.apple.Terminal 293 447.66 274.83 120.35 221.74 + firefox 84627 77.59 55.55 15.37 2.59 91.42 42.12 204.47 + plugin-container 84628 377.22 37.18 43.91 18.56 178.65 75.85 17.29 + Terminal 694 9.86 79.94 0.00 0.00 4.39 2.20 0.00 + powermetrics 84694 1.21 31.53 0.00 0.00 0.20 0.20 0.00 + com.google.Chrome 489 233.83 48.10 25.95 0.00 + Google Chrome Helper 84688 181.57 92.81 0.00 0.00 23.95 12.77 0.00 + Google Chrome 84681 57.26 76.07 4.39 0.00 23.75 12.97 0.00 + Google Chrome Helper 84685 0.13 48.08 0.00 0.00 0.40 0.20 0.00 + kernel_coalition 1 128.64 780.19 330.52 0.00 + kernel_task 0 109.97 0.00 0.20 0.00 779.47 330.35 0.00 + launchd 1 18.88 2.44 0.00 0.00 0.40 0.20 0.00 + com.apple.Safari 488 90.60 108.58 56.48 26.65 + com.apple.WebKit.WebContent 84679 64.21 84.69 0.00 0.00 104.19 54.89 26.66 + com.apple.WebKit.Networking 84678 26.89 58.89 0.40 0.00 1.60 0.00 0.00 + Safari 84676 1.56 55.74 0.00 0.00 2.59 1.40 0.00 + com.apple.Safari.SearchHelper 84690 0.15 49.49 0.00 0.00 0.20 0.20 0.00 + org.mozilla.firefox 482 76.56 124.34 63.47 0.00 + firefox 84496 76.70 89.18 10.58 5.59 124.55 63.48 0.00 + +This sample was taken while the following programs were running: + +- Firefox Beta (single process, invoked from the Mac OS dock, shown in + the `org.mozilla.firefox` coalition.) +- Firefox Nightly (multi-process, invoked from the command line, shown + in the `com.apple.Terminal` coalition.) +- Google Chrome. +- Safari. + +The grouping of parent and child processes (in coalitions) is obvious. +The meaning of the columns is as follows. + +- **Name**: Coalition/process name. Process names within coalitions + are indented. +- **ID**: Coalition/process ID number. +- **CPU ms/s**: CPU time used by the coalition/process, per second, + during the sample period. The sum of the process values typically + exceeds the coalition value slightly, for unknown reasons. +- **User%**: Percentage of that CPU time spent in user space (as + opposed to kernel mode.) +- **Deadlines (\<2 ms, 2-5 ms)**: These two columns count how many + \"short\" timers woke up threads in the process, per second, during + the sample period. High frequency timers, which typically have short + time-to-deadlines, can cause high power consumption and should be + avoided if possible. +- **Wakeups (Intr, Pkg idle)**: These two columns count how many + wakeups occurred, per second, during the sample period. The first + column counts interrupt-level wakeups that resulted in a thread + being dispatched in the process. The second column counts \"package + idle exit\" wakeups, which wake up the entire package as opposed to + just a single core; such wakeups are particularly expensive, and + this count is a subset of the first column\'s count. +- **GPU ms/s**: GPU time used by the coalition/process, per second, + during the sample period. + +Other things to note. + +- Smaller is better --- i.e. results in lower power consumption --- + for all of these measurements. +- There is some overlap between the two \"Deadlines\" columns and the + two \"Wakeups\" columns. For example, firing a single sub-2ms + deadline can also cause a package idle exit wakeup. +- Many of these measurements are also obtainable by passing the + `TASK_POWER_INFO` flag and a `task_power_info` struct to the + `task_info` function. +- By default, the coalitions/processes are sorted by a composite value + computed from several factors, though this can be changed via + command-line options. + +## Other measurements + +`powermetrics` can also report measurements of backlight usage, network +activity, disk activity, interrupt distribution, device power states, +C-state residency, P-state residency, quality of service classes, and +thermal pressure. These are less likely to be useful for profiling +Firefox, however. Run with the `--show-all` to see all of these at once, +but note that you\'ll need a very wide window to see all the data. + +Also note that `powermetrics -h` is a better guide to the the +command-line options than `man powermetrics`. + +## mach power + +You can use the `mach power` command to run `powermetrics` in +combination with `rapl` in a way that gives the most useful summary +measurements for each of Firefox, Chrome and Safari. The following is +sample output. + + total W = _pkg_ (cores + _gpu_ + other) + _ram_ W + #01 17.14 W = 14.98 ( 5.50 + 1.19 + 8.29) + 2.16 W + + 1 sample taken over a period of 30.000 seconds + + Name ID CPU ms/s User% Deadlines (<2 ms, 2-5 ms) Wakeups (Intr, Pkg idle) GPU ms/s + com.google.Chrome 500 439.64 585.35 218.62 19.17 + Google Chrome Helper 67319 284.75 83.03 296.67 0.00 454.05 172.74 0.00 + Google Chrome Helper 67304 55.23 64.83 0.03 0.00 9.43 4.33 19.17 + Google Chrome 67301 63.77 68.09 29.46 0.13 76.11 22.26 0.00 + Google Chrome Helper 67320 38.30 66.70 17.83 0.00 45.78 19.29 0.00 + com.apple.WindowServer 68 102.58 112.36 43.15 80.52 + WindowServer 141 103.03 58.19 60.48 6.40 112.36 43.15 80.53 + com.apple.Safari 499 267.19 110.53 46.05 1.69 + com.apple.WebKit.WebContent 67372 190.15 79.34 2.02 0.14 129.28 53.79 2.33 + com.apple.WebKit.Networking 67292 65.23 52.74 0.07 0.00 4.33 1.40 0.00 + Safari 67290 29.09 77.65 0.23 0.00 7.13 3.37 0.00 + com.apple.Safari.SearchHelper 67371 13.88 91.18 0.00 0.00 0.36 0.05 0.00 + com.apple.WebKit.WebContent 67297 0.81 56.84 0.10 0.00 2.20 1.30 0.00 + com.apple.WebKit.WebContent 67293 0.46 76.40 0.03 0.00 0.57 0.20 0.00 + com.apple.WebKit.WebContent 67295 0.24 67.72 0.00 0.00 0.90 0.37 0.00 + com.apple.WebKit.WebContent 67298 0.17 59.88 0.00 0.00 0.50 0.13 0.00 + com.apple.WebKit.WebContent 67296 0.07 43.51 0.00 0.00 0.10 0.03 0.00 + kernel_coalition 1 111.76 724.80 213.09 0.12 + kernel_task 0 107.06 0.00 5.86 0.00 724.46 212.99 0.12 + org.mozilla.firefox 498 92.17 212.69 75.67 1.81 + firefox 63865 61.00 87.18 1.00 0.87 25.79 9.00 1.81 + plugin-container 67269 31.49 72.46 1.80 0.00 186.90 66.68 0.00 + com.apple.WebKit.Plugin.64 67373 55.55 74.38 0.74 0.00 9.51 3.13 0.02 + com.apple.Terminal 109 6.22 0.40 0.23 0.00 + Terminal 208 6.25 92.99 0.00 0.00 0.33 0.20 0.00 + +The `rapl` output is first, then the `powermetrics` output. As well as +the browser processes, the `WindowServer` and kernel tasks are shown +because browsers often trigger significant load in them. + +The default sample period is 30,000 milliseconds (30 seconds), but that +can be changed with the `-i` option. diff --git a/docs/performance/profiling_with_concurrency_visualizer.md b/docs/performance/profiling_with_concurrency_visualizer.md new file mode 100644 index 0000000000..495fa15538 --- /dev/null +++ b/docs/performance/profiling_with_concurrency_visualizer.md @@ -0,0 +1,5 @@ +# Profiling with Concurrency Visualizer + +Concurrency Visualizer is an excellent alternative to xperf. In newer versions of Visual Studio, it is an addon that needs to be downloaded. + +Here are some scripts that you can be used for manipulating the profiles that have been exported to CSV: [https://github.com/jrmuizel/concurrency-visualizer-scripts](https://github.com/jrmuizel/concurrency-visualizer-scripts) diff --git a/docs/performance/profiling_with_instruments.md b/docs/performance/profiling_with_instruments.md new file mode 100644 index 0000000000..ac37bb2660 --- /dev/null +++ b/docs/performance/profiling_with_instruments.md @@ -0,0 +1,110 @@ +# Profiling with Instruments + +Instruments can be used for memory profiling and for statistical +profiling. + +## Official Apple documentation + +- [Instruments User + Guide](https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/) +- [Instruments User + Reference](https://developer.apple.com/library/mac/documentation/AnalysisTools/Reference/Instruments_User_Reference/) +- [Instruments Help + Articles](https://developer.apple.com/library/mac/recipes/Instruments_help_articles/) +- [Instruments + Help](https://developer.apple.com/library/mac/recipes/instruments_help-collection/) +- [Performance + Overview](https://developer.apple.com/library/mac/documentation/Performance/Conceptual/PerformanceOverview/) + +### Basic Usage + +- Select \"Time Profiler\" from the \"Choose a profiling template + for:\" dialog. +- In the top left, next to the record and pause button, there will be + a \"\[machine name\] \> All Processes\". Click \"All Processes\" and + select \"firefox\" from the \"Running Applications\" section. +- Click the record button (red circle in top left) +- Wait for the amount of time that you want to profile +- Click the stop button + +## Command line tools + +There is +[instruments](https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/instruments.1.html) +and +[iprofiler](https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/iprofiler.1.html). + +How do we monitor performance counters (cache miss etc.)? Instruments +has a \"Counters\" instrument that can do this. + +## Memory profiling + +Instruments will record a call stack at each allocation point. The call +tree view can be quite helpful here. Switch from \"Statistics\". This +`malloc` profiling is done using the `malloc_logger` infrastructure +(similar to `MallocStackLogging`). Currently this means you need to +build with jemalloc disabled (`ac_add_options --disable-jemalloc`). You +also need the fix to [Bug +719427](https://bugzilla.mozilla.org/show_bug.cgi?id=719427 "https://bugzilla.mozilla.org/show_bug.cgi?id=719427") + +## Kernel stacks + +Under "File" -> "Recording Options" you can enable "Record Kernel Callstacks". +To get full symbols and not just the exported ones, you'll to install the matching +[Kernel Debug Kit](https://developer.apple.com/download/all/?q=Kernel%20Debug%20Kit). +Make sure you install the one whose macOS version exactly matches your version, +including the identifier at the end (e.g. "12.3.1 (21E258)"). + +### Allow Instruments to find kernel symbols + +Installing the KDK is often not enough for Instruments to find the symbols. +Instruments uses Spotlight to find the dSYMs with the matching UUID, so you +need to put the dSYM in a place where Spotlight will index it. + +First, check the UUID of your macOS installation's kernel. To do so, run the +following: + +``` +% dwarfdump --uuid /System/Library/Kernels/kernel.release.t6000 +UUID: C342869F-FFB9-3CCE-A5A3-EA711C1E87F6 (arm64e) /System/Library/Kernels/kernel.release.t6000 +``` + +Then, find the corresponding dSYM file in the KDK that you installed, and +run `mdls` on it. For example: + +``` +% mdls /Library/Developer/KDKs/KDK_12.3.1_21E258.kdk/System/Library/Kernels/kernel.release.t6000.dSYM +``` + +(Make sure you use the `.release` variant, not the `.development` variant +or any of the others.) + +If the output from `mdls` contains the string `com_apple_xcode_dsym_uuids` +and the UUID matches, you're done. + +Otherwise, try copying the `kernel.release.t6000.dSYM` bundle to your home +directory, and then run `mdls` on the copied file. For example: + +``` +% cp -r /Library/Developer/KDKs/KDK_12.3.1_21E258.kdk/System/Library/Kernels/kernel.release.t6000.dSYM ~/ +% mdls ~/kernel.release.t6000.dSYM +_kMDItemDisplayNameWithExtensions = "kernel.release.t6000.dSYM" +com_apple_xcode_dsym_paths = ( + "Contents/Resources/DWARF/kernel.release.t6000" +) +com_apple_xcode_dsym_uuids = ( + "C342869F-FFB9-3CCE-A5A3-EA711C1E87F6" +) +kMDItemContentCreationDate = 2022-03-21 15:25:57 +0000 +[...] +``` + +Now Instruments should be able to pick up the kernel symbols. + +## Misc + +The `DTPerformanceSession` api can be used to control profiling from +applications like the old CHUD API we use in Shark builds. [Bug +667036](https://bugzilla.mozilla.org/show_bug.cgi?id=667036 "https://bugzilla.mozilla.org/show_bug.cgi?id=667036") + +System Trace might be useful. diff --git a/docs/performance/profiling_with_xperf.md b/docs/performance/profiling_with_xperf.md new file mode 100644 index 0000000000..030dae7c68 --- /dev/null +++ b/docs/performance/profiling_with_xperf.md @@ -0,0 +1,180 @@ +# Profiling with xperf + +Xperf is part of the Microsoft Windows Performance Toolkit, and has +functionality similar to that of Shark, oprofile, and (for some things) +dtrace/Instruments. For stack walking, Windows Vista or higher is +required; I haven't tested it at all on XP. + +This page applies to xperf version **4.8.7701 or newer**. To see your +xperf version, either run '`xperf`' on a command line with no +arguments, or start '`xperfview`' and look at Help -\> About +Performance Analyzer. (Note that it's not the first version number in +the About window; that's the Windows version.) + +If you have an older version, you will experience bugs, especially +around symbol loading for local builds. + +## Installation + +For all versions, the tools are part of the latest [Windows 7 SDK (SDK +Version +7.1)](http://www.microsoft.com/downloads/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b&displaylang=en "http://www.microsoft.com/downloads/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b&displaylang=en"){.external}. +Use the web installer to install at least the \"Win32 Development +Tools\". Once the SDK installs, execute either `wpt_x86.msi` or +`wpt_x64.msi` in the `Redist/Windows Performance Toolkit `folder of the +SDK's install location (typically Program Files/Microsoft +SDKs/Windows/v7.1/Redist/Windows Performance Toolkit) to actually +install the Windows Performance Toolkit tools. + +It might already be installed by the Windows SDK. Check if C:\\Program +Files\\Microsoft Windows Performance Toolkit already exists. + +For 64-bit Windows 7 or Vista, you'll need to do a registry tweak and +then restart to enable stack walking:\ +\ +`REG ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management" -v DisablePagingExecutive -d 0x1 -t REG_DWORD -f` + +## Symbol Server Setup + +With the latest versions of the Windows Performance Toolkit, you can +modify the symbol path directly from within the program via the Trace +menu. Just make sure you set the symbol paths before enabling \"Load +Symbols\" and before opening a summary view. You can also modify the +`_NT_SYMBOL_PATH` and `_NT_SYMCACHE_PATH` environment variables to make +these changes permanent. + +The standard symbol path that includes both Mozilla's and Microsoft's +symbol server configuration is as follows: + +`_NT_SYMCACHE_PATH: C:\symbols _NT_SYMBOL_PATH: srv*c:\symbols*http://msdl.microsoft.com/download/symbols;srv*c:\symbols*http://symbols.mozilla.org/firefox/` + +To add symbols **from your own builds**, add +`C:\path\to\objdir\dist\bin` to `_NT_SYMBOL_PATH`. As with all Windows +paths, the symbol path uses semicolons (`;`) as separators. + +Make sure you select the Trace -\> Load Symbols menu option in the +Windows Performance Analyzer (xperfview). + +There seems to be a bug in xperf and symbols; it is very sensitive to +when the symbol path is edited. If you change it within the program, +you'll have to close all summary tables and reopen them for it to pick +up the new symbol path data. + +You'll have to agree to a EULA for the Microsoft symbols \-- if you're +not prompted for this, then something isn't configured right in your +symbol path. (Again, make sure that the directories exist; if they +don't, it's a silent error.) + +## Quick Start + +All these tools will live, by default, in C:\\Program Files\\Microsoft +Windows Performance Toolkit. Either run these commands from there, or +add the directory to your path. You will need to use an elevated command +prompt to start or stop profiling. + +Start recording data: + +`xperf -on latency -stackwalk profile` + +\"Latency\" is a special provider name that turns on a few predefined +kernel providers; run \"xperf -providers k\" to view a full list of +providers and groups. You can combine providers, e.g., \"xperf -on +DiagEasy+FILE_IO\". \"-stackwalk profile\" tells xperf to capture a +stack for each PROFILE event; you could also do \"-stackwalk +profile+file_io\" to capture a stack on each cpu profile tick and each +file io completion event. + +Stop: + +`xperf -d out.etl` + +View: + +`xperfview out.etl` + +The MSDN +\"[Quickstart](http://msdn.microsoft.com/en-us/library/ff190971%28v=VS.85%29.aspx){.external}\" +page goes over this in more detail, and also has good explanations of +how to use xperfview. I'm not going to repeat it here, because I'd be +using essentially the same screenshots, so go look there. + +The 'stack' view will give results similar to shark. + +## Heap Profiling + +xperf has good tools for heap allocation profiling, but they have one +major limitation: you can't build with jemalloc and get heap events +generated. The stock windows CRT allocator is horrible about +fragmentation, and causes memory usage to rise drastically even if only +a small fraction of that memory is in use. However, even despite this, +it's a useful way to track allocations/deallocations. + +### Capturing Heap Data + +The \"-heap\" option is used to set up heap tracing. Firefox generates +lots of events, so you may want to play with the +BufferSize/MinBuffers/MaxBuffers options as well to ensure that you +don't get dropped events. Also, when recording the stack, I've found +that a heap trace is often missing module information (I believe this is +a bug in xperf). It's possible to get around that by doing a +simultaneous capture of non-heap data. + +To start a trace session, launching a new Firefox instance: + +`xperf -on base xperf -start heapsession -heap -PidNewProcess "./firefox.exe -P test -no-remote" -stackwalk HeapAlloc+HeapRealloc -BufferSize 512 -MinBuffers 128 -MaxBuffers 512` + +To stop a session and merge the resulting files: + +`xperf -stop heapsession -d heap.etl xperf -d main.etl xperf -merge main.etl heap.etl result.etl` + +\"result.etl\" will contain your merged data; you can delete main.etl +and heap.etl. Note that it's possible to capture even more data for the +non-heap profile; for example, you might want to be able to correlate +heap events with performance data, so you can do +\"`xperf -on base -stackwalk profile`\". + +In the viewer, when summary data is viewed for heap events (Heap +Allocations Outstanding, etc. all lead to the same summary graphs), 3 +types of allocations are listed \-- AIFI, AIFO, AOFI. This is shorthand +for \"Allocated Inside, Freed Inside\", \"Allocated Inside, Freed +Outside\", \"Allocated Outside, Freed Inside\". These refer to the time +range that was selected for the summary graph; for example, something +that's in the AOFI category was allocated before the start of the +selected time range, but the free event happened inside. + +## Tips + +- In the summary views, the yellow bar can be dragged left and right + to change the grouping \-- for example, drag it to the left of the + Module column to have grouping happen only by process (stuff that's + to the left), so that you get symbols in order of weight, regardless + of what module they're in. +- Dragging the columns around will change grouping in various ways; + experiment to get the data that you're looking for. Also experiment + with turning columns on and off; removing a column will allow data + to be aggregated without considering that column's contributions. +- Disabling all but one core will make the numbers add up to 100%. + This can be done by running 'msconfig' and going to Advance + Options from the \"Boot\" tab. + +## Building Firefox + +To get good data from a Firefox build, it is important to build with the +following options in your mozconfig: + +`export CFLAGS="-Oy-" export CXXFLAGS="-Oy-"` + +This disables frame-pointer optimization which lets xperf do a much +better job unwinding the stack. Traces can be captured fine without this +option (for example, from nightlies), but the stack information will not +be useful. + +`ac_add_options --enable-debug-symbols` + +This gives us symbols. + +## For More Information + +Microsoft's [documentation for xperf](http://msdn.microsoft.com/en-us/library/ff191077.aspx "http://msdn.microsoft.com/en-us/library/ff191077.aspx") +is pretty good; there is a lot of depth to this tool, and you should +look there for more details. diff --git a/docs/performance/profiling_with_zoom.md b/docs/performance/profiling_with_zoom.md new file mode 100644 index 0000000000..053fa0cbce --- /dev/null +++ b/docs/performance/profiling_with_zoom.md @@ -0,0 +1,5 @@ +# Profiling with Zoom + +Zoom is a profiler very similar to Shark for Linux. + +You can get the profiler from here: <http://www.rotateright.com/> diff --git a/docs/performance/reporting_a_performance_problem.md b/docs/performance/reporting_a_performance_problem.md new file mode 100644 index 0000000000..efe4f09f9c --- /dev/null +++ b/docs/performance/reporting_a_performance_problem.md @@ -0,0 +1,94 @@ +# Reporting a Performance Problem + +This article will guide you in reporting a performance problem using the +built-in Gecko Profiler tool. + +## Enabling the Profiler toolbar button + +These steps only work in Firefox 75+. + +1. Visit [https://profiler.firefox.com/](https://profiler.firefox.com/) +2. Click on *Enable Profiler Menu Button* +3. The profiler toolbar button will show up in the top right of the URL + bar as a small stopwatch icon. + +![image1](img/reportingperf1.png) + +4. You can right-click on the button and remove it from the toolbar + when you're done with it. + +## Using the Profiler + +When enabled, the profiler toolbar button is not recording by default. +Recording can be done by clicking on the toolbar icon to open its panel. +Make sure to choose an appropriate setting for the recording (if you're +not sure, choose Firefox Platform), and then choosing **Start +Recording**. The toolbar icon turns blue when it is recording. + +The profiler uses a fixed size buffer to store sample data. When it runs +out of space in its buffer, it discards old entries so you may want to +increase the buffer size if you find you are unable to capture the +profile quickly enough after you notice a performance problem. If you +choose Custom Settings (and then clicking Edit Settings) for the +profiler, you can adjust the size of the buffer (presently defaults to +90 MB) and the time interval between data collection (presently defaults +to 1 ms). Note that increasing the buffer size uses more memory and can +make capturing a profile take longer. + +![image2](img/reportingperf2.png) + +Using the keyboard shortcuts is often more convenient than using the +mouse to interact with the UI: + +* Ctrl+Shift+1 - Start/Stop the profiler +* Ctrl+Shift+2 - Take a profile and launch the viewer to view it + +## Capturing and sharing a profile + +1. While the profiler is recording, reproduce the performance problem. + If possible let the problem manifest itself for 5-10 seconds. +2. Press **Ctrl+Shift+2** or click on the profiler toolbar icon in the + top right and select **Capture**. Try to do this within a few + seconds from reproducing the performance problem as only the last + few seconds are recorded. If the timeline has a large red block + it's a good sign. ![Jank markers appearing in the Perf.html profile analysis tool.](img/PerfDotHTMLRedLines.png) +3. The data will open in a new tab. Wait until the \"Symbolicating call + stacks\" notification disappears before sharing the profile. +4. There will be a button in the top right labeled **Upload Local Profile** which + will allow you to upload this profile and once completed will write + out a link. Before uploading, the Upload button asks you what data + you'd like to publish to our servers. +5. Note that while it's possible to strip profiles of potentially + privacy sensitive information, the less information a profile + contains, *the harder it is to analyze and turn into actionable + data.* +6. Once uploaded, copy permalink URL to your clipboard by right + clicking and [add the profile URL to a bug](https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Performance) + for your performance problem and/or send it to the appropriate + person. Try to give some context about what you were doing when the + performance problem arose such as the URL you were viewing and what + actions were you doing (ex. scrolling on gmail.com). + +![image3](img/reportingperf3.png) + +## Viewing addon performance in GeckoView + +Sometimes an addon or more are slowing down Firefox. These addons might +be using the extension API in ways that were not meant to. You can see +which of these addons are causing problems by adding the +**moz-extension** filter. + +![moz-extension filter print screen](img/EJCrt4N.png) + +Make sure you are selecting the process that is using up the CPU since +all of the processes are shown. You might have a content process using +up the CPU and not the main one. + +Make sure you are doing whatever it is that slows down Firefox while +recording the profile. For example you might have one addon that slows down page load +and another one that slows down tab switch. + +Your first reflex once you find what addon is slowing down the profile +might be to disable it and search for alternatives. Before you do this, +please share the performance profile with the addon authors through a +bug report. Gecko profiler allows you to share a link with the profile. diff --git a/docs/performance/scroll-linked_effects.md b/docs/performance/scroll-linked_effects.md new file mode 100644 index 0000000000..90d3c33ed1 --- /dev/null +++ b/docs/performance/scroll-linked_effects.md @@ -0,0 +1,177 @@ +# Scroll-linked effects + +The definition of a scroll-linked effect is an effect implemented on a +webpage where something changes based on the scroll position, for +example updating a positioning property with the aim of producing a +parallax scrolling effect. This article discusses scroll-linked effects, +their effect on performance, related tools, and possible mitigation +techniques. + +## Scrolling effects explained + +Often scrolling effects are implemented by listening for the `scroll` +event and then updating elements on the page in some way (usually the +CSS +[`position`]((https://developer.mozilla.org/en-US/docs/Web/CSS/position "The position CSS property sets how an element is positioned in a document. The top, right, bottom, and left properties determine the final location of positioned elements.") +or +[`transform`](https://developer.mozilla.org/en-US/docs/Web/CSS/transform "The transform CSS property lets you rotate, scale, skew, or translate an element. It modifies the coordinate space of the CSS visual formatting model.") +property.) You can find a sampling of such effects at [CSS Scroll API: +Use +Cases](https://github.com/RByers/css-houdini-drafts/blob/master/css-scroll-api/UseCases.md). + +These effects work well in browsers where the scrolling is done +synchronously on the browser's main thread. However, most browsers now +support some sort of asynchronous scrolling in order to provide a +consistent 60 frames per second experience to the user. In the +asynchronous scrolling model, the visual scroll position is updated in +the compositor thread and is visible to the user before the `scroll` +event is updated in the DOM and fired on the main thread. This means +that the effects implemented will lag a little bit behind what the user +sees the scroll position to be. This can cause the effect to be laggy, +janky, or jittery --- in short, something we want to avoid. + +Below are a couple of examples of effects that would not work well with +asynchronous scrolling, along with equivalent versions that would work +well: + +### Example 1: Sticky positioning + +Here is an implementation of a sticky-positioning effect, where the +\"toolbar\" div will stick to the top of the screen as you scroll down. + +```html +<body style="height: 5000px" onscroll="document.getElementById('toolbar').style.top = Math.max(100, window.scrollY) + 'px'"> + <div id="toolbar" style="position: absolute; top: 100px; width: 100px; height: 20px; background-color: green"></div> +</body> +``` + +This implementation of sticky positioning relies on the scroll event +listener to reposition the "toolbar" div. As the scroll event listener +runs in the JavaScript on the browser's main thread, it will be +asynchronous relative to the user-visible scrolling. Therefore, with +asynchronous scrolling, the event handler will be delayed relative to +the user-visible scroll, and so the div will not stay visually fixed as +intended. Instead, it will move with the user's scrolling, and then +\"snap\" back into position when the scroll event handler runs. This +constant moving and snapping will result in a jittery visual effect. One +way to implement this without the scroll event listener is to use the +CSS property designed for this purpose: + +```html +<body style="height: 5000px"> + <div id="toolbar" style="position: sticky; top: 0px; margin-top: 100px; width: 100px; height: 20px; background-color: green"></div> +</body> +``` + +This version works well with asynchronous scrolling because position of +the \"toolbar\" div is updated by the browser as the user scrolls. + +### Example 2: Scroll snapping + +Below is an implementation of scroll snapping, where the scroll position +snaps to a particular destination when the user's scrolling stops near +that destination. + +```html +<body style="height: 5000px"> + <script> + function snap(destination) { + if (Math.abs(destination - window.scrollY) < 3) { + scrollTo(window.scrollX, destination); + } else if (Math.abs(destination - window.scrollY) < 200) { + scrollTo(window.scrollX, window.scrollY + ((destination - window.scrollY) / 2)); + setTimeout(snap, 20, destination); + } + } + var timeoutId = null; + addEventListener("scroll", function() { + if (timeoutId) clearTimeout(timeoutId); + timeoutId = setTimeout(snap, 200, parseInt(document.getElementById('snaptarget').style.top)); + }, true); + </script> + <div id="snaptarget" class="snaptarget" style="position: relative; top: 200px; width: 100%; height: 200px; background-color: green"></div> +</body> +``` + +In this example, there is a scroll event listener which detects if the +scroll position is within 200 pixels of the top of the \"snaptarget\" +div. If it is, then it triggers an animation to \"snap\" the scroll +position to the top of the div. As this animation is driven by +JavaScript on the browser's main thread, it can be interrupted by other +JavaScript running in other tabs or other windows. Therefore, the +animation can end up looking janky and not as smooth as intended. +Instead, using the CSS snap-points property will allow the browser to +run the animation asynchronously, providing a smooth visual effect to +the user. + +```html +<body style="height: 5000px"> + <style> + body, /* blink currently has bug that requires declaration on `body` */ + html { + scroll-snap-type: y proximity; + } + .snaptarget { + scroll-snap-align: start; + position: relative; + top: 200px; + height: 200px; + background-color: green; + } + </style> + <div class="snaptarget"></div> +</body> +``` + +This version can work smoothly in the browser even if there is +slow-running Javascript on the browser's main thread. + +### Other effects + +In many cases, scroll-linked effects can be reimplemented using CSS and +made to run on the compositor thread. However, in some cases the current +APIs offered by the browser do not allow this. In all cases, however, +Firefox will display a warning to the developer console (starting in +version 46) if it detects the presence of a scroll-linked effect on a +page. Pages that use scrolling effects without listening for scroll +events in JavaScript will not get this warning. See the [Asynchronous +scrolling in Firefox](https://staktrace.com/spout/entry.php?id=834) blog +post for some more examples of effects that can be implemented using CSS +to avoid jank. + +## Future improvements + +Going forward, we would like to support more effects in the compositor. +In order to do so, we need you (yes, you!) to tell us more about the +kinds of scroll-linked effects you are trying to implement, so that we +can find good ways to support them in the compositor. Currently there +are a few proposals for APIs that would allow such effects, and they all +have their advantages and disadvantages. The proposals currently under +consideration are: + +- [Web Animations](https://w3c.github.io/web-animations/): A new API + for precisely controlling web animations in JavaScript, with an + [additional + proposal](https://wiki.mozilla.org/Platform/Layout/Extended_Timelines) + to map scroll position to time and use that as a timeline for the + animation. +- [CompositorWorker](https://docs.google.com/document/d/18GGuTRGnafai17PDWjCHHAvFRsCfYUDYsi720sVPkws/edit?pli=1#heading=h.iy9r1phg1ux4): + Allows JavaScript to be run on the compositor thread in small + chunks, provided it doesn't cause the framerate to drop. +- [Scroll + Customization](https://docs.google.com/document/d/1VnvAqeWFG9JFZfgG5evBqrLGDZYRE5w6G5jEDORekPY/edit?pli=1): + Introduces a new API for content to dictate how a scroll delta is + applied and consumed. As of this writing, Mozilla does not plan to + support this proposal, but it is included for completeness. + +### Call to action + +If you have thoughts or opinions on: + +- Any of the above proposals in the context of scroll-linked effects. +- Scroll-linked effects you are trying to implement. +- Any other related issues or ideas. + +Please get in touch with us! You can join the discussion on the +[public-houdini](https://lists.w3.org/Archives/Public/public-houdini/) +mailing list. diff --git a/docs/performance/sorting_algorithms_comparison.md b/docs/performance/sorting_algorithms_comparison.md new file mode 100644 index 0000000000..8450d116e0 --- /dev/null +++ b/docs/performance/sorting_algorithms_comparison.md @@ -0,0 +1,52 @@ +# Sorting algorithms comparison + +This program compares the performance of three different sorting +algorithms: + +- bubble sort +- selection sort +- quicksort + +It consists of the following functions: + + ----------------------- --------------------------------------------------------------------------------------------------- + **`sortAll()`** Top-level function. Iteratively (200 iterations) generates a randomized array and calls `sort()`. + **`sort()`** Calls each of `bubbleSort()`, `selectionSort()`, `quickSort()` in turn and logs the result. + **`bubbleSort()`** Implements a bubble sort, returning the sorted array. + **`selectionSort()`** Implements a selection sort, returning the sorted array. + **`quickSort()`** Implements quicksort, returning the sorted array. + `swap()` Helper function for `bubbleSort()` and `selectionSort()`. + `partition()` Helper function for `quickSort()`. + ----------------------- --------------------------------------------------------------------------------------------------- + +Its call graph looks like this: + + sortAll() // (generate random array, then call sort) x 200 + + -> sort() // sort with each algorithm, log the result + + -> bubbleSort() + + -> swap() + + -> selectionSort() + + -> swap() + + -> quickSort() + + -> partition() + +The implementations of the sorting algorithms in the program are taken +from <https://github.com/nzakas/computer-science-in-javascript/> and are +used under the MIT license. + +You can try out the example program +[here](https://mdn.github.io/performance-scenarios/js-call-tree-1/index.html) +and clone the code [here](https://github.com/mdn/performance-scenarios) +(be sure to check out the gh-pages branch). You can also [download the +specific profile we +discuss](https://github.com/mdn/performance-scenarios/tree/gh-pages/js-call-tree-1/profile) +- just import it to the Performance tool if you want to follow along. Of +course, you can generate your own profile, too, but the numbers will be +a little different. diff --git a/docs/performance/timerfirings_logging.md b/docs/performance/timerfirings_logging.md new file mode 100644 index 0000000000..dfbe8dca93 --- /dev/null +++ b/docs/performance/timerfirings_logging.md @@ -0,0 +1,136 @@ +# TimerFirings Loggings + +TimerFirings logging is a feature built into Gecko that prints a line of +data for every timer fired. This is useful because timer firings are a +major cause of wakeups, which can cause high power consumption. + +**Note**: The [power profiling +overview](power_profiling_overview.md) +is worth reading at this point if you haven\'t already. It may make +parts of this document easier to understand. + +## Invocation + +TimerFirings logging uses Gecko\'s own logging mechanism, and so is able +to be used in any build. Set the following environment variable to +enable it. + + NSPR_LOG_MODULES=TimerFirings:4 + +## Output + +Once enabled, TimerFirings will print one line of logging output per +timer fired. It\'s best to redirect this output to a file. + +The following sample shows the basics of this output. + + -991946880[7f46c365ba00]: [6775] fn timer (SLACK 100 ms): LayerActivityTracker + -991946880[7f46c365ba00]: [6775] fn timer (ONE_SHOT 250 ms): PresShell::sPaintSuppressionCallback + -991946880[7f46c365ba00]: [6775] fn timer (ONE_SHOT 160 ms): nsBrowserStatusFilter::TimeoutHandler + -991946880[7f46c365ba00]: [6775] iface timer (ONE_SHOT 200 ms): 7f46964d7f80 + -1340643584[7f46c365ec00]: [6775] obs timer (SLACK 1000 ms): 7f46a95a0200 + +Each line has the following information. + +- The first two values identify the thread. This is not especially + useful. +- The next value is the process ID (pid). This is useful in a + multi-process scenario. +- Next is the timer kind, one of `fn` (function), `iface` (interface) + or `obs` (observer), which are the three kinds of timers that Gecko + supports. +- Then comes the function kind, one of `ONE_SHOT` (a single-use + timer), `SLACK` or `PRECISE` (repeating timers of differing + precision). +- Then comes the timer period, measured in milliseconds. +- Finally there is the identifying information for the timer. Function + timers have an informative label. Interface and observer timers only + have an address, which is less useful, but they are uncommon enough + that this usually doesn\'t matter much. + +The above example shows only timers from C++ within Gecko. There are +also timers for `setTimer` or `setInterval` calls in JavaScript code, as +the following sample shows. + + -991946880[7f46c365ba00]: [6775] fn timer (ONE_SHOT 0 ms): [content] chrome://browser/content/tabbrowser.xml:1816:0 + 711637568[7f3219c48000]: [6835] fn timer (ONE_SHOT 100 ms): [content] http://edition.cnn.com/:5:7231 + 711637568[7f3219c48000]: [6835] fn timer (ONE_SHOT 100 ms): [content] http://a.visualrevenue.com/vrs.js:6:9423 + +These JS timers are annotated with `[content]` and show the JavaScript +source location where they were created. They can come from chrome code +within Firefox, or from web content. + +The informative labels are only present on function timers that have had +their creation site annotated. For unannotated function timers, there +are three possible behaviours. + +First, on Mac the code uses `dladdr` to get the name immediately, and +the output will look like the following. + + 2082435840[100445640]: [81190] fn timer (ONE_SHOT 8000 ms): [from dladdr] gfxFontInfoLoader::DelayedStartCallback(nsITimer*, void*) + +Second, on Linux the code uses `dladdr` to get the symbol library and +address, which can be post-processed by `tools/rb/fix_stacks.py`. The +following two lines show the output before and after being +post-processed by that script. + + 2088737280[7f606bf68140]: [30710] fn timer (ONE_SHOT 16 ms): [from dladdr] #0: ???[/home/njn/moz/mi1/o64/dist/bin/libxul.so +0x2144f94] + 2088737280[7f606bf68140]: [30710] fn timer (ONE_SHOT 16 ms): [from dladdr] #0: mozilla::RefreshDriverTimer::TimerTick(nsITimer*, void*) (/home/njn/moz/mi1/o64/layout/b + +Third, on other platforms `dladdr` is not implemented or doesn\'t work +well, and the output will look like the following. + + 711637568[7f3219c48000]: [6835] fn timer (ONE_SHOT 16 ms): ???[dladdr is unimplemented or doesn't work well on this OS] + +The `???` indicates that the function timer lacks an explicit name, and +the comment within the square brackets explains why the fallback +mechanism wasn\'t used`.` + +If an unannotated timer function appears frequently it is worth +explicitly annotating it so that it will be usefully identified on other +platforms. (Running on Mac or Linux is obviously necessary to learn the +timer function\'s name.) This is done by initializing it with +`initWithNamedFuncCallback` or `initWithNameableFuncCallback` instead of +`initWithNameCallback`. + +## Post-processing + +TimerFirings logging quickly produces thousands of lines of output. This +output needs post-processing for it to be useful. If the output is +redirected to a file called *`out`*, then the following command will +pull out the timer-related lines, count how many times each unique line +appears, and then print them with the most common ones first. + + cat out | grep timer | sort | uniq -c | sort -r -n + +The following is sample output from this command. + + 204 801266240[7f7c1f248000]: [7163] fn timer (ONE_SHOT 50 ms): [content] http://widgets.outbrain.com/outbrain.js:20:330 + 135 -495057024[7f74e105ba00]: [7108] fn timer (ONE_SHOT 4 ms): [content] https://self-repair.mozilla.org/en-US/repair/:7:13669 + 118 801266240[7f7c1f248000]: [7163] fn timer (ONE_SHOT 100 ms): [content] http://a.visualrevenue.com/vrs.js:6:9423 + 103 801266240[7f7c1f248000]: [7163] fn timer (ONE_SHOT 50 ms): [content] http://static.dynamicyield.com/scripts/12086/dy-min.js?v=12086:3:3389 + 94 801266240[7f7c1f248000]: [7163] fn timer (ONE_SHOT 50 ms): [content] https://ad.double-click.net/ddm/adi/N7921.1283839CADREON.COM.AU/B9038144.122190976;sz=300x600;click=http://pixel.mathtag.com/click/img?mt_aid=2744535504761193354&mt_id=1895890&mt_adid=148611&mt_sid=973379&mt_exid=9&mt_inapp=0&mt_uuid=353d5460-19f6-4400-9bbd-d0fcc3bcf595&mt_3pck=http%3A//beacon-apac-hkg1.rubiconproject.com/beacon/t/d1f9921d-4e47-448f-b6ba-36cae1c31b65/&redirect=;ord=2744535504761193354?:83:0 + 94 801266240[7f7c1f248000]: [7163] fn timer (ONE_SHOT 160 ms): nsBrowserStatusFilter::TimeoutHandler + 92 -495057024[7f74e105ba00]: [7108] fn timer (ONE_SHOT 160 ms): nsBrowserStatusFilter::TimeoutHandler + +The first column shows how many times the particular line appeared. + +It is sometimes useful to pre-process the output by stripping out +certain parts of each line before doing this aggregation step, for +example, by inserting one or more of the following commands into the +command pipeline. + + sed 's/^[^:]\+: //' # strip thread IDs + sed 's/\[[0-9]\+\] //' # strip process IDs + sed 's/ \+[0-9]\+ ms//' # strip timer periods + +The following is the previous sample output with all three of these +commands added into the pipeline. + + 204 fn timer (ONE_SHOT): [content] http://widgets.outbrain.com/outbrain.js:20:330 + 186 fn timer (ONE_SHOT): nsBrowserStatusFilter::TimeoutHandler + 138 fn timer (ONE_SHOT): [content] https://self-repair.mozilla.org/en-US/repair/:7:13669 + 118 fn timer (ONE_SHOT): [content] http://a.visualrevenue.com/vrs.js:6:9423 + 108 fn timer (SLACK): LayerActivityTracker + 104 fn timer (SLACK): nsIDocument::SelectorCache + 104 fn timer (SLACK): CCTimerFired diff --git a/docs/performance/tools_power_rapl.md b/docs/performance/tools_power_rapl.md new file mode 100644 index 0000000000..3bf2555bd6 --- /dev/null +++ b/docs/performance/tools_power_rapl.md @@ -0,0 +1,113 @@ +# tools/power/rapl + +`tools/power/rapl` (or `rapl` for short) is a command-line utility in +the Mozilla tree that periodically reads and prints all available Intel +RAPL power estimates. These are machine-wide estimates, so if you want +to estimate the power consumption of a single program you should +minimize other activity on the machine while measuring. + +**Note**: The [power profiling overview](power_profiling_overview.md) is +worth reading at this point if you haven't already. It may make parts +of this document easier to understand. + +## Invocation + +First, do a [standard build of Firefox](/setup/index.rst). + +### Mac + +On Mac, `rapl` can be run as follows. + +```bash +$OBJDIR/dist/bin/rapl +``` + +### Linux + +On Linux, `rapl` can be run as root, as follows. + + sudo $OBJDIR/dist/bin/rapl + +Alternatively, it can be run without root privileges by setting the +contents of +[/proc/sys/kernel/perf_event_paranoid](http://unix.stackexchange.com/questions/14227/do-i-need-root-admin-permissions-to-run-userspace-perf-tool-perf-events-ar) +to 0. Note that if you do change this file, its contents may reset when +the machine is next rebooted. + +You must be running Linux kernel version 3.14 or later for `rapl` to +work. Otherwise, it will fail with an error message explaining this +requirement. + +### Windows + +Unfortunately, `rapl` does not work on Windows, and porting it would be +difficult because Windows does not have APIs that allow easy access to +the relevant model-specific registers. + +## Output + +The following is 10 seconds of output from a default invocation of +`rapl`. + +```bash + total W = _pkg_ (cores + _gpu_ + other) + _ram_ W +#01 5.17 W = 1.78 ( 0.12 + 0.10 + 1.56) + 3.39 W +#02 9.43 W = 5.44 ( 1.44 + 1.20 + 2.80) + 3.98 W +#03 14.26 W = 10.21 ( 5.47 + 0.19 + 4.55) + 4.04 W +#04 10.02 W = 6.15 ( 2.62 + 0.43 + 3.10) + 3.86 W +#05 14.63 W = 10.43 ( 4.41 + 0.81 + 5.22) + 4.19 W +#06 11.16 W = 6.90 ( 1.91 + 1.68 + 3.31) + 4.26 W +#07 5.40 W = 1.97 ( 0.20 + 0.10 + 1.67) + 3.44 W +#08 5.17 W = 1.76 ( 0.07 + 0.08 + 1.60) + 3.41 W +#09 5.17 W = 1.76 ( 0.09 + 0.08 + 1.58) + 3.42 W +#10 8.13 W = 4.40 ( 1.55 + 0.11 + 2.74) + 3.73 W +``` + +Things to note include the following. + +- All measurements are in Watts. +- The first line indicates the meaning of each column. +- The underscores in `_pkg_`, `_gpu_` and `_ram_` are present so that + each column's name has five characters. +- The total power is the sum of the package power and the RAM power. +- The package estimate is divided into three parts: cores, GPU, and + \"other\". \"Other\" is computed as the package power minus the + cores power and GPU power. +- If the processor does not support GPU or RAM estimates then + \"` n/a `\" will be printed in the relevant column instead of a + number, and it will contribute zero to the total. + +Once sampling is finished --- either because the user interrupted it, or +because the requested number of samples has been taken --- the following +summary data is shown: + +```bash +10 samples taken over a period of 10.000 seconds + +Distribution of 'total' values: + mean = 8.85 W + std dev = 3.50 W + 0th percentile = 5.17 W (min) + 5th percentile = 5.17 W + 25th percentile = 5.17 W + 50th percentile = 8.13 W + 75th percentile = 11.16 W + 95th percentile = 14.63 W +100th percentile = 14.63 W (max) +``` + +The distribution data is omitted if there was zero or one samples taken. + +## Options + +- `-i --sample-interval`. The length of each sample in milliseconds. + Defaults to 1000. A warning is given if you set it below 50 because + that is likely to lead to inaccurate estimates. +- `-n --sample-count`. The number of samples to take. The default is + 0, which is interpreted as \"unlimited\". + +## Combining with `powermetrics` + +On Mac, you can use the [mach power](powermetrics.md#mach-power) command +to run `rapl` in combination with `powermetrics` in a way that gives the +most useful summary measurements for each of Firefox, Chrome and Safari. diff --git a/docs/performance/turbostat.md b/docs/performance/turbostat.md new file mode 100644 index 0000000000..3eac89c086 --- /dev/null +++ b/docs/performance/turbostat.md @@ -0,0 +1,50 @@ +# Turbostat + +`turbostat` is a Linux command-line utility that prints various +measurements, including numerous per-CPU measurements. This article +provides an introduction to using it. + +**Note**: The [power profiling overview](power_profiling_overview.md) is +worth reading at this point if you haven't already. It may make parts +of this document easier to understand. + +## Invocation + +`turbostat` must be invoked as the super-user: + +```bash +sudo turbostat +``` + +If you get an error saying `"turbostat: no /dev/cpu/0/msr"`, you need to +run the following command: + +```bash +sudo modprobe msr +``` + +The output is as follows: + +``` + Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt + - - 799 21.63 3694 3398 0 12.02 3.16 1.71 61.48 49 49 0.00 0.00 0.00 0.00 22.68 15.13 1.13 + 0 0 821 22.44 3657 3398 0 9.92 2.43 2.25 62.96 39 49 0.00 0.00 0.00 0.00 22.68 15.13 1.13 + 0 4 708 19.14 3698 3398 0 13.22 + 1 1 743 20.26 3666 3398 0 21.40 4.01 1.42 52.90 49 + 1 5 1206 31.98 3770 3398 0 9.69 + 2 2 784 21.29 3681 3398 0 11.78 3.10 1.13 62.70 40 + 2 6 782 21.15 3698 3398 0 11.92 + 3 3 702 19.14 3670 3398 0 8.39 3.09 2.03 67.36 39 + 3 7 648 17.67 3667 3398 0 9.85 +``` + +The man page has good explanations of what each column measures. The +various "Watt" measurements come from the Intel RAPL MSRs. + +If you run with the `-S` option you get a smaller range of measurements +that fit on a single line, like the following: + +``` + Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt + 3614 97.83 3694 3399 0 2.17 0.00 0.00 0.00 77 77 0.00 0.00 0.00 0.00 67.50 57.77 0.46 +``` diff --git a/docs/setup/building_with_debug_symbols.rst b/docs/setup/building_with_debug_symbols.rst new file mode 100644 index 0000000000..316e04af31 --- /dev/null +++ b/docs/setup/building_with_debug_symbols.rst @@ -0,0 +1,61 @@ +Building with Debug Symbols +=========================== + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +By default, a release build of Firefox will not generate debug symbols +suitable for debugging or post-processing into the +:ref:`breakpad <Crash reporting>` symbol format. Use the +following :ref:`mozconfig <Configuring Build Options>` settings +to do a build with symbols: + + + +Building Firefox with symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There is a single configure option to enable building with symbols on +all platforms. This is enabled by default so unless you have explcitly +disabled it your build you should include symbols. + +:: + + ac_add_options --enable-debug-symbols + +This can optionally take an argument for the type of symbols that need +to be produced (like "-g3"). By default it uses "-g" on Linux and MacOS. +This value takes precedence over the flags set in ``MOZ_DEBUG_FLAGS`` + +Note that this will override the values provided for ``CFLAGS`` and +``CXXFLAGS``. + + +Breakpad symbol files +~~~~~~~~~~~~~~~~~~~~~ + +After the build is complete, run the following command to generate an +archive of :ref:`Breakpad <Crash reporting>` symbol files: + +.. code:: bash + + mach buildsymbols + +Treeherder uses an additional ``uploadsymbols`` target to upload +symbols to a socorro server. See +https://searchfox.org/mozilla-central/source/toolkit/crashreporter/tools/upload_symbols.py +for more information about the environment variables used by this +target. + + +``make package`` +~~~~~~~~~~~~~~~~ + +If you use ``make package`` to package your build, symbols will be +stripped. If you want to keep the symbols in the patches, you need to +add this to your mozconfig: + +.. code:: + + ac_add_options --disable-install-strip diff --git a/docs/setup/configuring_build_options.rst b/docs/setup/configuring_build_options.rst new file mode 100644 index 0000000000..fd57930022 --- /dev/null +++ b/docs/setup/configuring_build_options.rst @@ -0,0 +1,404 @@ +Configuring Build Options +========================= + ++--------------------------------------------------------------------+ +| This page is an import from MDN and the contents might be outdated | ++--------------------------------------------------------------------+ + +This document details how to configure Firefox builds. +Most of the time a ``mozconfig`` file is not required. The default +options are the most well-supported, so it is preferable to add as few +options as possible. Please read the following directions carefully +before building, and follow them in order. Skipping any step may cause +the build to fail, or the built software to be unusable. Build options, +including options not usable from the command-line, may appear in +"``confvars.sh``" files in the source tree. + + +Using a ``mozconfig`` configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The choice of which Mozilla project to build and other configuration +options can be configured in a ``mozconfig`` file. (It is possible to +manually call ``configure`` with command-line options, but this is not +recommended). The ``mozconfig`` file should be in your source directory +(that is, ``/mozilla-central/mozconfig``). + +Create a blank ``mozconfig`` file: + +.. code:: bash + + echo "# My first mozilla config" > mozconfig + +If your mozconfig isn't in your source directory, you can also use the +``MOZCONFIG`` environment variable to specify the path to your +``mozconfig``. The path you specify **must** be an **absolute** path or +else ``client.mk`` will not find it. This is useful if you choose to +have multiple ``mozconfig`` files for different projects or +configurations (see below for a full example). Note that in the +``export`` example below the filename was not ``mozconfig``. Regardless +of the name of the actual file you use, we refer to this file as the +``mozconfig`` file in the examples below. + +Setting the ``mozconfig`` path: + +.. code:: bash + + export MOZCONFIG=$HOME/mozilla/mozconfig-firefox + +.. note:: + + Calling the file ``.mozconfig`` (with a leading dot) is also + supported, but this is not recommended because it may make the file + harder to find. This will also help when troubleshooting because + people will want to know which build options you have selected and + will assume that you have put them in your ``mozconfig`` file. + + +``mozconfig`` contains two types of options: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Options prefixed with ``mk_add_options`` are passed to + ``client.mk``. The most important of these is ``MOZ_OBJDIR``, which + controls where your project gets built (also known as the object + directory). +- Options prefixed with ``ac_add_options`` are passed to ``configure``, + and affect the build process. + + +Building with an objdir +~~~~~~~~~~~~~~~~~~~~~~~ + +This means that the source code and object files are not intermingled in +your directory system and you can build multiple projects (e.g., +Firefox and Thunderbird) from the same source tree. If you do not +specify a ``MOZ_OBJDIR``, it will be automatically set to +``@TOPSRCDIR@/obj-@CONFIG_GUESS@``. + +If you need to re-run ``configure``, the easiest way to do it is using +``./mach configure``; running ``configure`` manually is strongly +discouraged. + +Adding the following line to your ``mozconfig`` allows you to change the +objdir: + +.. code:: bash + + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-@CONFIG_GUESS@ + +It is a good idea to have your objdir name start with ``obj`` so that +Mercurial ignores it. + +Sometimes it can be useful to build multiple versions of the source +(such as with and without diagnostic asserts). To avoid the time it +takes to do a full rebuild, you can create multiple ``mozconfig`` files +which specify different objdirs. For example, a ``mozconfig-dbg``: + +.. code:: bash + + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-dbg + ac_add_options --enable-debug + +and a ``mozconfig-rel-opt``: + +.. code:: bash + + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-rel-opt + ac_add_options --disable-debug + ac_add_options --enable-optimize + +allow for building both versions by specifying the configuration via +the ``MOZCONFIG`` environment variable: + +.. code:: bash + + $ env MOZCONFIG=/path/to/mozconfig-dbg ./mach build + $ env MOZCONFIG=/path/to/mozconfig-rel-opt ./mach build + +Don't forget to set the ``MOZCONFIG`` environment variable for the +``mach run`` command as well. + +Be aware that changing your ``mozconfig`` will require the configure +process to be rerun and therefore the build will take considerably +longer, so if you find yourself changing the same options regularly, it +may be worth having a separate ``mozconfig`` for each. The main downside +of this is that each objdir will take up a significant amount of space +on disk. + + +Parallel compilation +~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + **Note**: The build system automatically makes an intelligent guess + for how many CPU cores to use when building. The option below is + typically not needed. + +Most modern systems have multiple cores or CPUs, and they can be +optionally used concurrently to make the build faster. The ``-j`` flag +controls how many parallel builds will run concurrently. You will see +(diminishing) returns up to a value approximately 1.5× to 2.0× the +number of cores on your system. + +.. code:: bash + + mk_add_options MOZ_PARALLEL_BUILD=4 + +If your machine is overheating, you might want to try a lower value. + + +Choose a project +~~~~~~~~~~~~~~~~ + +The ``--enable-project=project`` flag is used to select a project to +build. Firefox is the default. + +Choose one of the following options to add to your ``mozconfig`` file: + +Browser (Firefox) + .. code:: + + ac_add_options --enable-project=browser + + .. note:: + + **Note**: This is the default + +Mail (Thunderbird) + .. code:: + + ac_add_options --enable-project=comm/mail + +Mozilla Suite (SeaMonkey) + .. code:: + + ac_add_options --enable-project=suite + +Calendar (Lightning Extension, uses Thunderbird) + .. code:: + + ac_add_options --enable-project=comm/mail + ac_add_options --enable-calendar + + +Selecting build options +~~~~~~~~~~~~~~~~~~~~~~~ + +The build options you choose depends on what project you are +building and what you will be using the build for. If you want to use +the build regularly, you will want a release build without extra +debugging information; if you are a developer who wants to hack the +source code, you probably want a non-optimized build with extra +debugging macros. + +There are many options recognized by the configure script which are +special-purpose options intended for embedders or other special +situations, and should not be used to build the full suite/XUL +projects. The full list of options can be obtained by running +``./mach configure -- --help``. + +.. warning:: + + Do not use a configure option unless you know what it does. + The default values are usually the right ones. Each additional option + you add to your ``mozconfig`` file reduces the chance that your build + will compile and run correctly. + +The following build options are very common: + +sccache +^^^^^^^ + +`SCCache <https://github.com/mozilla/sccache>`__ allows speeding up subsequent +C / C++ builds by caching compilation results. Unlike +`ccache <https://ccache.dev>`__, it also allows caching Rust artifacts, and +supports `distributed compilation +<https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md>`__. + +In order to enable ``sccache`` for Firefox builds, you can use +``ac_add_options --with-ccache=sccache``. + +Optimization +^^^^^^^^^^^^ + +``ac_add_options --enable-optimize`` + Enables the default compiler optimization options + + .. note:: + + **Note**: This is enabled by default + +``ac_add_options --enable-optimize=-O2`` + Chooses particular compiler optimization options. In most cases, this + will not give the desired results, unless you know the Mozilla + codebase very well; note, however, that if you are building with the + Microsoft compilers, you probably **do** want this as ``-O1`` will + optimize for size, unlike GCC. +``ac_add_options --enable-debug`` + Enables assertions in C++ and JavaScript, plus other debug-only code. + This can significantly slow a build, but it is invaluable when + writing patches. **People developing patches (especially in C++) + should generally use this option.** +``ac_add_options --disable-optimize`` + Disables compiler optimization. This makes it much easier to step + through code in a debugger. +``ac_add_options --enable-release`` + Enables more conservative, release engineering-oriented options. This may + slow down builds. This also turns on full optimizations for Rust. Note this + is the default when building release/beta/esr. +``ac_add_options --enable-debug-js-modules`` + Enable only JavaScript assertions. This is useful when working + locally on JavaScript-powered components like the DevTools. This will + help catch any errors introduced into the JS code, with less of a + performance impact compared to the ``--enable-debug`` option. +``export RUSTC_OPT_LEVEL=2`` + Enable full optimizations for Rust code. + +You can make an optimized build with debugging symbols. See :ref:`Building +with Debug Symbols <Building with Debug Symbols>`. + +Extensions +^^^^^^^^^^ + +``ac_add_options --enable-extensions=default|all|ext1,ext2,-skipext3`` + There are many optional pieces of code that live in {{ + Source("extensions/") }}. Many of these extensions are now considered + an integral part of the browsing experience. There is a default list + of extensions for the suite, and each app-specific ``mozconfig`` + specifies a different default set. Some extensions are not compatible + with all apps, for example: + + - ``cookie`` is not compatible with thunderbird + - ``typeaheadfind`` is not compatible with any toolkit app (Firefox, + Thunderbird) + + Unless you know which extensions are compatible with which apps, do + not use the ``--enable-extensions`` option; the build system will + automatically select the proper default set of extensions. + +Tests +^^^^^ + +``ac_add_options --disable-tests`` + By default, many auxiliary test programs are built, which can + help debug and patch the mozilla source. Disabling these tests can + speed build time and reduce disk space considerably. Developers + should generally not use this option. + +Localization +^^^^^^^^^^^^ + +``mk_add_options MOZ_CO_LOCALES=ISOcode`` + TBD. +``ac_add_options --enable-ui-locale=ISOcode`` + TBD. +``ac_add_options --with-l10n-base=/path/to/base/dir`` + TBD. + +Other Options +^^^^^^^^^^^^^ + +``mk_add_options AUTOCLOBBER=1`` + If a clobber would be required before a build, this will cause mach + to clobber and continue with the build instead of asking the user to + manually clobber and exiting. + +``ac_add_options --enable-crashreporter`` + This enables the machinery that allows Firefox to write out a + `minidump <https://docs.microsoft.com/en-us/windows/desktop/Debug/minidump-files>`__ + files when crashing as well as the tools to process and submit crash + reports to Mozilla. After enabling the crash reporter in your local + build, you will need to run mach with the --enable-crash-reporter + (note the extra dash) to enable it at runtime, like so: + ``./mach run --enable-crash-reporter`` +``ac_add_options --enable-warnings-as-errors`` + This makes compiler warnings into errors which fail the build. This + can be useful since certain warnings coincide with reviewbot lints + which must be fixed before merging. + +.. _Example_.mozconfig_Files: + +Example ``mozconfig`` Files +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Mozilla's official builds use mozconfig files from the appropriate +directory within each repository. + +.. warning:: + + These ``mozconfig`` files are taken from production builds + and are provided as examples only. It is recommended to use the default + build options, and only change the properties from the list above as + needed. The production builds aren't really appropriate for local + builds." + +- .. rubric:: Firefox, `Debugging Build (macOS + 64bits) <http://hg.mozilla.org/mozilla-central/file/tip/browser/config/mozconfigs/macosx64/debug>`__ + :name: Firefox.2C_Default_Release_Configuration + +Building multiple projects from the same source tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is possible to build multiple projects from the same source tree, +as long as you `use a different objdir <#Building_with_an_Objdir>`__ for +each project. + +You need to create multiple ``mozconfig`` files. + +As an example, the following steps can be used to build Firefox and +Thunderbird. You should first create three ``mozconfig`` files. + +``mozconfig-common``: + +.. code:: + + # add common options here, such as making an optimized release build + mk_add_options MOZ_PARALLEL_BUILD=4 + ac_add_options --enable-optimize --disable-debug + +``mozconfig-firefox``: + +.. code:: + + # include the common mozconfig + . ./mozconfig-common + + # Build Firefox + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-firefox + ac_add_options --enable-project=browser + +``mozconfig-thunderbird``: + +.. code:: + + # include the common mozconfig + . ./mozconfig-common + + # Build Thunderbird + mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-thunderbird + ac_add_options --enable-project=comm/mail + +To build Firefox, run the following commands: + +.. code:: + + export MOZCONFIG=/path/to/mozilla/mozconfig-firefox + ./mach build + +To build Thunderbird, run the following commands: + +.. code:: + + export MOZCONFIG=/path/to/mozilla/mozconfig-thunderbird + ./mach build + +Using mozconfigwrapper +^^^^^^^^^^^^^^^^^^^^^^ + +Mozconfigwrapper is similar to using multiple mozconfig files except +that it abstracts and hides them so you don't have to worry about where +they live or which ones you've created. It also saves you from having to +export the MOZCONFIG variable each time. For information on installing +and configuring mozconfigwrapper, see +https://github.com/ahal/mozconfigwrapper. diff --git a/docs/setup/contributing_code.rst b/docs/setup/contributing_code.rst new file mode 100644 index 0000000000..8b24dac87d --- /dev/null +++ b/docs/setup/contributing_code.rst @@ -0,0 +1,181 @@ +How To Contribute Code To Firefox +================================= + +The whole process can be a bit long, and it might take time to get things right. +If at any point you are stuck, please don't hesitate to ask at `https://chat.mozilla.org <https://chat.mozilla.org>`_ +in the `#introduction <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_ channel. + +We make changes to Firefox by writing patches, testing them and pushing them into "the tree", the +term we use for all the code in Mozilla-Central. Let's get started. + +Please see the :ref:`Firefox Contributors Quick Reference <Firefox Contributors' Quick Reference>` for simple check list. + +Finding something to work on +---------------------------- + +| Bugs listed as 'Assigned' are not usually a good place to start, + unless you're sure you have something worthy to contribute. Someone + else is already working on it! +| Even with no assignee, it is polite to check if someone has recently + commented that they're looking at fixing the issue. +| Once you have found something to work on, go ahead and comment! Let + the bug submitter, reviewer, and component owner know that you'd like + to work on the bug. You might receive some extra information, perhaps + also made the assignee. + +Find a bug we've identified as a good fit for new contributors. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With more than a million bugs filed in Bugzilla, it can be hard to know +where to start, so we've created these bug categories to make getting +involved a little easier: + +- `Codetribute <https://codetribute.mozilla.org/>`_ - our site for + finding bugs that are mentored, some are good first bugs, some are + slightly harder. Your mentor will help guide you with the bug fix and + through the submission and landing process. +- `Good First Bugs <https://mzl.la/2yBg3zB>`_ + - are the best way to take your first steps into the Mozilla + ecosystem. They're all about small changes, sometimes as little as a + few lines, but they're a great way to learn about setting up your + development environment, navigating Bugzilla, and making + contributions to the Mozilla codebase. +- `Student Projects <https://bugzil.la/kw:student-project>`_ - are + larger projects, such as might be suitable for a university student + for credit. Of course, if you are not a student, feel free to fix one + of these bugs. We maintain two lists: one for projects `based on the + existing codebase <https://bugzil.la/kw:student-project>`_. + +Fix that one bug +~~~~~~~~~~~~~~~~ + +If there's one particular bug you'd like to fix about Firefox, Thunderbird, or +your other favorite Mozilla application, this can be a great place to +start. There are a number of ways to do this: + +- `Search bugzilla <https://bugzilla.mozilla.org/query.cgi>`_ for + relevant keywords. See pages on + `Bugzilla and Searching Bugzilla <https://bmo.readthedocs.io/en/latest/using/finding.html>`_ for further + help +- Learn the `bugzilla + component <https://bugzilla.mozilla.org/describecomponents.cgi>`_, + with which your pet bug is implemented, using the components list. + Browse this component on bugzilla for related bugs + +Fixing your bug +--------------- + +We leave this in your hands. Here are some further resources to help: + +- Check out + :ref:`Our Developer Guide and its parent document <Working on Firefox>` +- Our :ref:`reviewer checklist <Reviewer Checklist>` is very + useful, if you have a patch near completion, and seek a favorable + review +- Utilize our build tool :ref:`mach`, its linting, + static analysis, and other code checking features + +Getting your code reviewed +-------------------------- + +Once you fix the bug, you can advance to having your code reviewed. + +Mozilla uses +`Phabricator <https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html>`_ +for code review. + +Who is the right person to ask for a review? + +- If you have a mentored bug: ask your mentor. They will help, or can + easily find out. It might be them! +- Run ``{hg, git} blame`` on the file and look for the people who have touched + the functions you're working on. They too are good candidates. + Running ``{hg, git} log`` and looking for regular reviewers might be a + solution too. +- The bug itself may contain a clear indication of the best person to + ask for a review +- Are there related bugs on similar topics? The reviewer in those bugs + might be another good choice +- We have a :ref:`list of modules <Governance>`, which lists peers and + owners for the module. Some of these will be good reviewers. In a + worst case scenario, set the module owner as the reviewer, asking + them in the comments to pick someone more suitable + +Please select only one reviewer. + +Following up and responding +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you've asked for a review, a reviewer will often respond within a +day or two, reviewing the patch, or saying when they will be able to +review it, perhaps due to a backlog. If you don't hear back within this +time, naturally reach out to them: add a comment to the bug saying +'review ping?', check the "Need more information from" box, and add the +reviewer's name. If they don't respond within a day or two, you can ask +for help on Matrix in the +`#introduction:mozilla.org <https://riot.im/app/#/room/#introduction:mozilla.org>`_ +or +`#developers:mozilla.org <https://chat.mozilla.org/#/room/#developers:mozilla.org>`_ +channels. + +Don't hesitate to contact your mentor as well if this isn't moving. + +For most new contributors, and even for long-time Mozillians, the first +review of your patch will be "Requested Changes" (or an "r-" in +Bugzilla). This does not mean you've done bad work. There is more work +to do before the code can be merged into the tree. Your patch may need +some changes - perhaps minor, perhaps major - and your reviewer will +give you some guidance on what needs to be done next. + +This is an important process, so don't be discouraged! With our +long-lived codebase, and hundreds of millions of users, the care and +attention helping contributors bring good patches is the cornerstone of +the Mozilla project. Make any changes your reviewer seeks; if you're +unsure how, be sure to ask! Push your new patch up to Phabricator again and +ask for a further review from the same reviewer. If they accept your +changes, this means your patch can be landed into the tree! + +Getting code into Firefox +------------------------- + +Once your patch has been accepted, it is ready to go. Before it can be +merged into the tree, your patch will need to complete a successful run +through our :ref:`try server <Pushing to Try>`, +making sure there are no unexpected regressions. If you don't have try +server access already, your mentor, or the person who reviewed your +patch, will be able to help. + +Ask the reviewer to land the patch for you. +For more details, see :ref:`push_a_change` + + +Do it all again! +---------------- + +Thank you. You've fixed your very first bug, and the Open Web is +stronger for it. But don't stop now. + +Go back to step 3, as there is plenty more to do. Your mentor might +suggest a new bug for you to work on, or `find one that interests +you <http://www.whatcanidoformozilla.org/>`_. Now that you've got your +first bug fixed you should request level 1 access to the repository to +push to the try server and get automated feedback about your changes on +multiple platforms. After fixing a nontrivial number of bugs you should +request level 3 access so you can land your own code after it has been +reviewed. + +More information +---------------- + +We're in the process of improving information on this page for newcomers +to the project. We'll be integrating some information from these pages +soon, but until then you may find them interesting in their current +form: + +- `A guide to learning the Firefox + codebase <http://www.joshmatthews.net/blog/2010/03/getting-involve-with-mozilla/>`_ +- `A beginner's guide to SpiderMonkey, Mozilla's Javascript + engine <https://wiki.mozilla.org/JavaScript:New_to_SpiderMonkey>`_ +- `Mozilla platform development + cheatsheet <https://web.archive.org/web/20160813112326/http://www.codefirefox.com:80/cheatsheet>`_ + (archive.org) diff --git a/docs/setup/index.rst b/docs/setup/index.rst new file mode 100644 index 0000000000..eb0c68aa4e --- /dev/null +++ b/docs/setup/index.rst @@ -0,0 +1,25 @@ +Getting Set Up To Work On The Firefox Codebase +============================================== + +This page will help you get set up to build Firefox on your own machine. + +Don't hesitate to look at the :ref:`Firefox Contributors Quick Reference <Firefox Contributors' Quick Reference>` to read a quick tutorial. + +.. toctree:: + :caption: Thank you for contributing to Firefox + + /contributing/contributing_to_mozilla + +.. toctree:: + :caption: Setting Up Your Machine + :maxdepth: 1 + + windows_build + macos_build + linux_build + linux_32bit_build_on_64bit_OS + +.. toctree:: + :caption: Getting Ready To Contribute + + contributing_code diff --git a/docs/setup/linux_32bit_build_on_64bit_OS.rst b/docs/setup/linux_32bit_build_on_64bit_OS.rst new file mode 100644 index 0000000000..6e8656fc4a --- /dev/null +++ b/docs/setup/linux_32bit_build_on_64bit_OS.rst @@ -0,0 +1,37 @@ +Building Firefox 32-bit On Linux 64-bit +======================================= + +.. note:: + + Unless you really want to target older hardware, you probably + want to :ref:`Build Firefox 64-bit <Building Firefox On Linux>` + since it is better-supported. + +Before following these 32-bit-Firefox-specific instructions, follow +the :ref:`Building Firefox On Linux` instructions to ensure that +your machine can do a normal build. + +Instructions for Ubuntu 19.10 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These steps were verified to work as of June 2020. + +#. Run ``rustup target install i686-unknown-linux-gnu`` to install the + 32-bit Rust target. +#. Install 32-bit dependencies with the following command (this shouldn't try to + remove packages. If this is the case, those instructions won't work as-is): + + .. code:: + + sudo apt install gcc-multilib g++-multilib libdbus-glib-1-dev:i386 \ + libgtk2.0-dev:i386 libgtk-3-dev:i386 libpango1.0-dev:i386 libxt-dev:i386 \ + libx11-xcb-dev:i386 libpulse-dev:i386 libdrm-dev:i386 + +#. Then, create a ``mozconfig`` file in your Firefox code directory + (probably ``mozilla-unified``) that looks like the following example: + + .. code:: + + ac_add_options --target=i686 + +#. Run ``./mach build``. diff --git a/docs/setup/linux_build.rst b/docs/setup/linux_build.rst new file mode 100644 index 0000000000..8582a52be6 --- /dev/null +++ b/docs/setup/linux_build.rst @@ -0,0 +1,151 @@ +Building Firefox On Linux +========================= + +This document will help you get set up to build Firefox on your own +computer. Getting set up can take a while - we need to download a +lot of bytes! Even on a fast connection, this can take ten to fifteen +minutes of work, spread out over an hour or two. + +Requirements +------------ + +- **Memory:** 4GB RAM minimum, 8GB+ recommended. +- **Disk Space:** At least 30GB of free disk space. +- **Operating System:** A 64-bit installation of Linux. It is strongly advised + that you use a supported distribution; see :ref:`build_hosts`. We also + recommend that your system is fully up-to-date. + +.. note:: + + Some Linux distros are better-supported than others. Mozilla maintains + bootstrapping code for Ubuntu, but others are managed by the + community (thanks!). The more esoteric the distro you're using, + the more likely that you'll need to solve unexpected problems. + + +1. System preparation +--------------------- + +1.1 Install Python +~~~~~~~~~~~~~~~~~~ + +To build Firefox, it's necessary to have a Python of version 3.6 or later +installed. Python 2 is no longer required to build Firefox, although it is still +required for running some kinds of tests. Additionally, you will probably need +Python development files as well to install some pip packages. + +You should be able to install Python using your system package manager: + +- For Debian-based Linux (such as Ubuntu): ``sudo apt-get install curl python3 python3-pip`` +- For Fedora Linux: ``sudo dnf install python3 python3-pip`` + +If you need a version of Python that your package manager doesn't have (e.g.: +the provided Python 3 is too old, or you want Python 2 but it's not available), +then you can use `pyenv <https://github.com/pyenv/pyenv>`_, assuming that your +system is supported. + +1.2 Install Mercurial +~~~~~~~~~~~~~~~~~~~~~ + +Mozilla's source code is hosted in Mercurial repositories. You will +need Mercurial to download and update the code. + +Note that if you'd prefer to use the version of Mercurial that is +packaged by your distro, you can skip this section. However, keep in +mind that distro-packaged Mercurial may be outdated, and therefore +slower and less supported. + +.. code-block:: shell + + python3 -m pip install --user mercurial + +You can test that Mercurial is installed by running: + +.. code-block:: shell + + hg version + +.. note:: + + If your shell is showing ``command not found: hg``, then Python's packages aren't + being found in the ``$PATH``. You can resolve this by doing the following and + restarting your shell: + + .. code-block:: shell + + # If you're using zsh + echo 'export PATH="'"$(python3 -m site --user-base)"'/bin:$PATH"' >> ~/.zshenv + + # If you're using bash + echo 'export PATH="'"$(python3 -m site --user-base)"'/bin:$PATH"' >> ~/.bashrc + + # If you're using a different shell, follow its documentation to see + # how to configure your PATH. Ensure that `$(python3 -m site --user-base)/bin` + # is prepended. + +2. Bootstrap a copy of the Firefox source code +---------------------------------------------- + +Now that your system is ready, we can download the source code and have Firefox +automatically download the other dependencies it needs. The below command +will download a lot of data (years of Firefox history!) then guide you through +the interactive setup process. + +.. code-block:: shell + + curl https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py -O + python3 bootstrap.py + +.. note:: + + In general, the Firefox workflow works best with Mercurial. However, + if you'd prefer to use ``git``, you can grab the source code in + "git" form by running the bootstrap script with the ``vcs`` parameter: + + .. code-block:: shell + + python3 bootstrap.py --vcs=git + + This uses `Git Cinnabar <https://github.com/glandium/git-cinnabar/>`_ under the hood. + +Choosing a build type +~~~~~~~~~~~~~~~~~~~~~ + +If you aren't modifying the Firefox backend, then select one of the +:ref:`Artifact Mode <Understanding Artifact Builds>` options. If you are +building Firefox for Android, you should also see the :ref:`GeckoView Contributor Guide`. + +3. Build +-------- + +Now that your system is bootstrapped, you should be able to build! + +.. code-block:: shell + + cd mozilla-unified + hg up -C central + ./mach build + ./mach run + +🎉 Congratulations! You've built your own home-grown Firefox! + +Now the fun starts +------------------ + +Time to start hacking! You should join us on `Matrix <https://chat.mozilla.org/>`_, +say hello in the `Introduction channel +<https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_, and `find a bug to +start working on <https://codetribute.mozilla.org/>`_. +See the :ref:`Firefox Contributors' Quick Reference` to learn how to test your changes, +send patches to Mozilla, update your source code locally, and more. + +Troubleshooting +--------------- + +Using a non-native file system (NTFS, network drive, etc) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In our experience building Firefox in these hybrid or otherwise complex environments +always ends in unexpected, often silent and always hard-to-diagnose failure. +Building Firefox in that environment is far more likely to reveal the flaws and +shortcomings of those systems than it is to produce a running web browser. diff --git a/docs/setup/macos_build.rst b/docs/setup/macos_build.rst new file mode 100644 index 0000000000..3d32b8aed0 --- /dev/null +++ b/docs/setup/macos_build.rst @@ -0,0 +1,122 @@ +Building Firefox On macOS +========================= + +This document will help you get set up to build Firefox on your own +computer. Getting set up can take a while - we need to download a +lot of bytes! Even on a fast connection, this can take ten to fifteen +minutes of work, spread out over an hour or two. + +Requirements +------------ + +- **Memory:** 4GB RAM minimum, 8GB+ recommended. +- **Disk Space:** At least 30GB of free disk space. +- **Operating System:** macOS - most recent or prior release. It is advisable + to upgrade to the latest “point” release. See :ref:`build_hosts` for more + information. + + +1. System preparation +--------------------- + +1.1. Install Brew +~~~~~~~~~~~~~~~~~ + +Mozilla's source tree requires a number of third-party tools. +You will need to install `Homebrew <https://brew.sh/>`__ so that we +can automatically fetch the tools we need. + +1.2. Install Xcode +~~~~~~~~~~~~~~~~~~ + +Install Xcode from the App Store. +Once done, finalize the installation in your terminal: + +.. code-block:: shell + + sudo xcode-select --switch /Applications/Xcode.app + sudo xcodebuild -license + +1.3 Install Mercurial +~~~~~~~~~~~~~~~~~~~~~ + +Mozilla's source code is hosted in Mercurial repositories. You will +need Mercurial to download and update the code. Additionally, we'll +put user-wide python package installations on the ``$PATH``, so that +both ``hg`` and ``moz-phab`` will be easily accessible: + +**NOTE** Pay special attention to the `==6.1.4`, as Mercurial >=6.2 is incompatible with several plugins + +.. code-block:: shell + + echo 'export PATH="'"$(python3 -m site --user-base)"'/bin:$PATH"' >> ~/.zshenv + python3 -m pip install --user mercurial==6.1.4 + +Now, restart your shell so that the ``PATH`` change took effect. +You can test that Mercurial is installed by running: + +.. code-block:: shell + + hg version + +.. note:: + + If you're using a shell other than ``zsh``, you'll need to manually add Python's + ``bin`` directory to your ``PATH``, as your shell probably won't pick up our + changes in ``~/.zshenv``. + +2. Bootstrap a copy of the Firefox source code +---------------------------------------------- + +Now that your system is ready, we can download the source code and have Firefox +automatically download the other dependencies it needs. The below command +will download a lot of data (years of Firefox history!) then guide you through +the interactive setup process. + +.. code-block:: shell + + curl https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py -O + python3 bootstrap.py + +.. note:: + + In general, the Firefox workflow works best with Mercurial. However, + if you'd prefer to use ``git``, you can grab the source code in + "git" form by running the bootstrap script with the ``vcs`` parameter: + + .. code-block:: shell + + python3 bootstrap.py --vcs=git + + This uses `Git Cinnabar <https://github.com/glandium/git-cinnabar/>`_ under the hood. + +Choosing a build type +~~~~~~~~~~~~~~~~~~~~~ + +If you aren't modifying the Firefox backend, then select one of the +:ref:`Artifact Mode <Understanding Artifact Builds>` options. If you are +building Firefox for Android, you should also see the :ref:`GeckoView Contributor Guide`. + +3. Build +-------- + +Now that your system is bootstrapped, you should be able to build! + +.. code-block:: shell + + cd mozilla-unified + hg up -C central + ./mach build + ./mach run + +🎉 Congratulations! You've built your own home-grown Firefox! + +Now the fun starts +------------------ + +Time to start hacking! You should join us on `Matrix <https://chat.mozilla.org/>`_, +say hello in the `Introduction channel +<https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_, and `find a bug to +start working on <https://codetribute.mozilla.org/>`_. +See the :ref:`Firefox Contributors' Quick Reference` to learn how to test your changes, +send patches to Mozilla, update your source code locally, and more. diff --git a/docs/setup/windows_build.rst b/docs/setup/windows_build.rst new file mode 100644 index 0000000000..2e8da661e9 --- /dev/null +++ b/docs/setup/windows_build.rst @@ -0,0 +1,181 @@ +Building Firefox On Windows +=========================== + +This document will help you get set up to build Firefox on your own +computer. Getting set up can take a while - we need to download a +lot of bytes! Even on a fast connection, this can take ten to fifteen +minutes of work, spread out over an hour or two. + +If you'd prefer to build Firefox for Windows in a virtual machine, +you may be interested in the `Windows images provided by Microsoft +<https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/>`_. + +Requirements +------------ + +- **Memory:** 4GB RAM minimum, 8GB+ recommended. +- **Disk Space:** At least 40GB of free disk space. +- **Operating System:** Windows 10. It is advisable to have Windows Update be fully + up-to-date. See :ref:`build_hosts` for more information. + +1. Install MozillaBuild +----------------------- + +Install `MozillaBuild +<https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe>`_. + +Accept the default installation directory. +Windows may prompt you to "reinstall with the correct settings", which you +should click to accept. + +When working with Firefox tooling, you'll need to do so from within the MozillaBuild +shell. You can start it by running ``C:\mozilla-build\start-shell.bat`` (you may want +to make a shortcut to this file so it's easier to start). + +.. note:: + + The MozillaBuild shell is a lot more like a Linux shell than the Windows ``cmd``. You can + learn more about it `here <https://wiki.mozilla.org/MozillaBuild>`_. + +2. Bootstrap a copy of the Firefox source code +---------------------------------------------- + +Now that your system is ready, we can download the source code and have Firefox +automatically download the other dependencies it needs. The below command +will download a lot of data (years of Firefox history!) then guide you through +the interactive setup process. + +.. code-block:: shell + + # Using the C:\mozilla-build\start-shell.bat shell from step 1: + cd c:/ + mkdir mozilla-source + cd mozilla-source + wget https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py + python3 bootstrap.py +.. note:: + + When running ``bootstrap.py`` there will be a `UAC (User Account Control) prompt <https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/how-user-account-control-works>`_ for PowerShell after + selecting the destination directory for the source code clone. This is + necessary to add the Microsoft Defender Antivirus exclusions automatically. You + should select ``Yes`` on the UAC prompt, otherwise you will need + to :ref:`follow some manual steps below <Ensure antivirus exclusions>`. + +.. note:: + + In general, the Firefox workflow works best with Mercurial. However, + if you'd prefer to use ``git``, you can grab the source code in + "git" form by running the bootstrap script with the ``vcs`` parameter: + + .. code-block:: shell + + python3 bootstrap.py --vcs=git + + This uses `Git Cinnabar <https://github.com/glandium/git-cinnabar/>`_ under the hood. + +Choosing a build type +~~~~~~~~~~~~~~~~~~~~~ + +If you aren't modifying the Firefox backend, then select one of the +:ref:`Artifact Mode <Understanding Artifact Builds>` options. If you are +building Firefox for Android, you should also see the :ref:`GeckoView Contributor Guide`. + +.. _Ensure antivirus exclusions: + +Ensure antivirus exclusions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Microsoft Defender Antivirus and some third-party antivirus products +are known to significantly degrade build times and sometimes even cause failed +builds (due to a "missing file"). This is usually because we have tests for +well-known security bugs that have code samples that antivirus software identifies +as a threat, automatically quarantining/corrupting the files. + +To avoid this, add the following folders to your third-party antivirus exclusion list: + +- The ``C:\mozilla-build`` folder. +- The directory where the Firefox code is (probably ``C:\mozilla-source``). +- The ``%USERPROFILE%/.mozbuild`` directory (probably ``C:\Users\<user>\.mozbuild``). + +The ``bootstrap.py`` script attempts to add the above folders to the Microsoft +Defender Antivirus exclusion list automatically. You should check that they were +successfully added, but if they're missing you will need to `add the exclusions to +Microsoft Defender Antivirus manually +<https://support.microsoft.com/en-ca/help/4028485/windows-10-add-an-exclusion-to-windows-security>`_. + +.. note:: + + If you're already missing files (you'll see them listed in ``hg status``, you can have them + brought back by reverting your source tree: ``hg update -C``). + +3. Build +-------- + +Now that your system is bootstrapped, you should be able to build! + +.. code-block:: shell + + cd c:/mozilla-source/mozilla-unified + hg up -C central + ./mach build + ./mach run + +🎉 Congratulations! You've built your own home-grown Firefox! + +Now the fun starts +------------------ + +Time to start hacking! You should join us on `Matrix <https://chat.mozilla.org/>`_, +say hello in the `Introduction channel +<https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_, and `find a bug to +start working on <https://codetribute.mozilla.org/>`_. +See the :ref:`Firefox Contributors' Quick Reference` to learn how to test your changes, +send patches to Mozilla, update your source code locally, and more. + +.. note:: + + If you'd like to interact with Mach from a different command line environment + than MozillaBuild, there's experimental support for it described + :ref:`over here <Using Mach on Windows Outside MozillaBuild>`. + +Troubleshooting +--------------- + +MozillaBuild out-of-date +~~~~~~~~~~~~~~~~~~~~~~~~ + +The build system expects that you're using the most-recent MozillaBuild release. +However, MozillaBuild doesn't auto-update. If you're running into local issues, +they may be resolved by `upgrading your MozillaBuild <https://wiki.mozilla.org/MozillaBuild>`_. + +Spaces in folder names +~~~~~~~~~~~~~~~~~~~~~~ + +**Firefox will not build** if the path to the installation +tool folders contains **spaces** or other breaking characters such as +pluses, quotation marks, or metacharacters. The Visual Studio tools and +SDKs are an exception - they may be installed in a directory which +contains spaces. It is strongly recommended that you accept the default +settings for all installation locations. + +Quotation marks in ``PATH`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Quotation marks (") aren't translated properly when passed to MozillaBuild +sub-shells. Since they're not usually necessary, you should ensure they're +not in your ``PATH`` environment variable. + +``PYTHON`` environment variable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If ``PYTHON`` is set, the build may fail with the error: "``The system +cannot find the file specified``." Ensure that you aren't having +a ``PYTHON`` environment variable set. + +Cygwin interference +~~~~~~~~~~~~~~~~~~~ + +If you happen to have Cygwin installed, its tools may erroneously be +used when building Firefox. Ensure that MozillaBuild directories (in +``C:\mozilla-build\``) are before Cygwin directories in the ``PATH`` +environment variable. diff --git a/docs/testing-rust-code/index.md b/docs/testing-rust-code/index.md new file mode 100644 index 0000000000..fef3ce9c80 --- /dev/null +++ b/docs/testing-rust-code/index.md @@ -0,0 +1,123 @@ +# Testing & Debugging Rust Code + +This page explains how to test and debug Rust code in Firefox. + +The [build documentation](/build/buildsystem/rust.rst) explains how to add +new Rust code to Firefox. The [code documentation](/writing-rust-code/index.md) +explains how to write and work with Rust code in Firefox. + +## Testing Mozilla crates + +Rust code will naturally be tested as part of system tests such as Mochitests. +This section describes the two methods for unit testing of individual Rust +crates. Which method should be used depends on the circumstances. + +### Rust tests + +If a Mozilla crate has "normal" Rust tests (i.e. `#[test]` functions that run +with `cargo test`), you can add the crate's name to `RUST_TESTS` in +[toolkit/library/rust/moz.build](https://searchfox.org/mozilla-central/source/toolkit/library/rust/moz.build). +(Cargo features can be activated for Rust tests by adding them to +`RUST_TEST_FEATURES` in the same file.) + +Rust tests are run with `./mach rusttests`. They run on automation in a couple +of `rusttests` jobs, but not on all platforms. + +Rust tests have one major restriction: they cannot link against Gecko symbols. +Therefore, Rust tests cannot be used for crates that use Gecko crates like +`nsstring` and `xpcom`. + +It's also possible to use `RUST_TESTS` in a different `moz.build` file. See +`testing/geckodriver/moz.build` and the [geckodriver testing docs] for an +example. + +[geckodriver testing docs]: /testing/geckodriver/Testing.md + +### GTests + +Another way to unit test a Mozilla crate is by writing a GTest that uses FFI to +call into Rust code. This requires the following steps. +- Create a new test crate whose name is the same as the name of crate being + tested, with a `-gtest` suffix. +- Add to the test crate a Rust file, a C++ file containing GTest `TEST()` + functions that use FFI to call into the Rust file, a `Cargo.toml` file that + references the Rust file, and a `moz.build` file that references the C++ + file. +- Add an entry to the `[dependencies]` section in + [toolkit/library/gtest/rust/Cargo.toml](https://searchfox.org/mozilla-central/source/toolkit/library/gtest/rust/Cargo.toml). +- Add an `extern crate` entry to + [toolkit/library/gtest/rust/lib.rs](https://searchfox.org/mozilla-central/source/toolkit/library/gtest/rust/lib.rs). + +See +[xpcom/rust/gtest/nsstring/](https://searchfox.org/mozilla-central/source/xpcom/rust/gtest/nsstring) +for a simple example. (Note that the `moz.build` file is in the parent +directory for that crate.) + +A Rust GTest can be run like any other GTest via `./mach gtest`, using the C++ +`TEST()` functions as the starting point. + +Unlike Rust tests, GTests can be used when linking against Gecko symbols is required. + +## Testing third-party crates + +In general we don't run tests for third-party crates. The assumption is that +these crates are sufficiently well-tested elsewhere. + +## Debugging Rust code + +In theory, Rust code is debuggable much like C++ code, using standard tools +like `gdb`, `rr`, and the Microsoft Visual Studio Debugger. In practice, the +experience can be worse, because shortcomings such as the following can occur. +- Inability to print local variables, even in non-optimized builds. +- Inability to call generic functions. +- Missing line numbers and stack frames. +- Printing of basic types such as `Option` and `Vec` is sometimes sub-optimal. + If you see a warning "Missing auto-load script at offset 0 in section + `.debug_gdb_scripts`" when starting `gdb`, the `rust-gdb` wrapper may give + better results. + +## Logging from Rust code + +### Rust logging + +The `RUST_LOG` environment variable (from the `env_logger` crate) can be used +to enable logging to stderr from Rust code in Firefox. The logging macros from +the `log` crate can be used. In order of importance, they are: `error!`, +`warn!`, `info!`, `debug!`, `trace!`. + +For example, to show all log messages of `info` level or higher, run: +``` +RUST_LOG=info firefox +``` +Module-level logging can also be specified, see the [documentation] for the +`env_logger` crate for details. + +To restrict logging to child processes, use `RUST_LOG_CHILD` instead of +`RUST_LOG`. + +[documentation]: https://docs.rs/env_logger/ + +### Gecko logging + +Rust logging can also be forwarded to the [Gecko logger] for capture via +`MOZ_LOG` and `MOZ_LOG_FILE`. + +[Gecko logger]: /xpcom/logging.rst + +- When parsing modules from `MOZ_LOG`, modules containing `::` are considered + to be Rust modules. To log everything in a top-level module like + `neqo_transport`, specify it as `neqo_transport::*`. For example: +``` +MOZ_LOG=timestamp,sync,nsHostResolver:5,neqo_transport::*:5,proxy:5 firefox +``` +- When logging from a submodule the `::*` is allowed but isn't necessary. + So these two lines are equivalent: +``` +MOZ_LOG=timestamp,sync,neqo_transport::recovery:5 firefox +MOZ_LOG=timestamp,sync,neqo_transport::recovery::*:5 firefox +``` +- `debug!` and `trace!` logs will not appear in non-debug builds. This is due + to our use of the `release_max_level_info` feature in the `log` crate. + +- When using both `MOZ_LOG` and `RUST_LOG`, modules that are specified in + `MOZ_LOG` will not appear in `RUST_LOG`. diff --git a/docs/update-infrastructure/index.md b/docs/update-infrastructure/index.md new file mode 100644 index 0000000000..450c9f52aa --- /dev/null +++ b/docs/update-infrastructure/index.md @@ -0,0 +1,36 @@ +# Mozilla Update Infrastructure + +Firefox, Thunderbird, and Mozilla VPN updates rely on [backend service known as Balrog](https://github.com/mozilla-releng/balrog). Periodically, these applications check for updates by pinging an URL[^1] which contains information about both the application running, and details of the system it is running on. If Balrog finds an update based on the provided information, it returns a simple XML response with a link to the update file, and some metadata about it. + +# Watershed Updates + +Most of the time, an update will take an application directly from whatever version it is currently running to the latest version of that application. This is greatly preferred, both to save time, bandwidth, reduce restarts, and increase security by ensuring we get to the latest version of something as quickly as possible. Unfortunately, sometimes we must route through an intermediate version first, typically the version that is currently running does not provide Balrog with enough information to accurately serve a correct update to the latest version. These are colloquially known as "watershed" updates. (This name comes from the fact that these updates change something about the update process itself, making them a kind of "watershed moment" for updates.) + +At the time of writing (May, 2023), we currently have the following watershed updates in place for Firefox's release channel: +* 12.0, all platforms. In this release [we added support for distinguishing the running and supported architectures in macOS builds in the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=583671). +* 43.0.1, Windows only. This release was [preparation for desupporting SHA-1 hashes in our Windows builds](https://bugzilla.mozilla.org/show_bug.cgi?id=1234277). +* 45.0.2, Linux only. We added support for [sending the GTK 3 version to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1227023). +* 47.0.2, Windows only. We [added CPU instruction set information to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1271761) to later allow SSE1 to be deprecated. +* 56.0, Windows only. We added support for [sending information about the JAWS accessibility application to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1402376) to avoid updating people on crashy versions of it. Additionally, we [added support for LZMA compression to the updater](https://bugzilla.mozilla.org/show_bug.cgi?id=641212) and [swapped to new MAR signing keys](https://bugzilla.mozilla.org/show_bug.cgi?id=1324498). +* 57.0.4[^2], Linux & Mac only. We [added support for LZMA compression to the updater](https://bugzilla.mozilla.org/show_bug.cgi?id=641212) and [swapped to new MAR signing keys](https://bugzilla.mozilla.org/show_bug.cgi?id=1324498). (Note: Windows was not required here because they picked up this change in the above 56.0 watershed.) +* 72.0.2, all platforms. This is a required version due to a [necessary two-step password database migration](https://bugzilla.mozilla.org/show_bug.cgi?id=1615382). +* 109.0.1, macOS only. This updates the channel-prefs.js file (normally excluded from updates) due to [signature issues](https://bugzilla.mozilla.org/show_bug.cgi?id=1804303). + + +[^1]: Here is a sample URL: https://aus5.mozilla.org/update/3/Firefox/85.0/20200518093924/WINNT_x86_64-msvc-x64/en-US/release/Windows_NT%2010.0.0.0.18363.1016%20(x64)/default/default/update.xml +[^2]: While not directly related to the watershed, it is notable that due to LZMA MAR support shipping in the previous version (56.0), which was _not_ a watershed for Linux and Mac, we shipped two different sets of MARs for 57.0, 57.0.1, 57.0.2, 57.0.3, and 57.0.4: we had bz2 MARs, which builds older than 56.0 were served, and a separate set of LZMA MARs that were shipped to 56.0 and higher. More details on this can be found on [this awfully complicated spreadsheet that was produced around that time](https://docs.google.com/spreadsheets/d/1xcs9iTShJI8WBvxrz547Zr5JClqdRUYEZRMbQqdQ58I/edit#gid=0). + + +# Desupport Updates + +From time to time we stop supporting a platform, hardware or library that we depend on. When we do this, we must ensure we don't update affected users to a version that they can no longer run. This can take two forms: +* In the distant past, we would simply stop serving updates altogether, leaving users on their current version. +* More recently, we will first move users to our `esr` channel - generally giving them another year of support before ending updates altogether. + +Below is a list of desupports and moves to `esr` that we've done on the Firefox release channel: +* (Ancient, desupported at various old versions): Darwin 6, Darwin 7, Darwin 8, Darwin 9, Windows_95, Windows_98, Windows_NT 4, Windows_NT 5.0, Windows_NT 5.1.0, Windows_NT 5.1.1, GTK 2.0., GTK 2.1., GTK 2.2., GTK 2.3., GTK 2.4., GTK 2.5., GTK 2.6., GTK 2.7., GTK 2.8., GTK 2.9., GTK 2.10., GTK 2.11., GTK 2.12., GTK 2.13., GTK 2.14., GTK 2.15., GTK 2.16., GTK 2.17., PPC Architecture +* <46.0: [Desupported GTK <3.4](https://bugzilla.mozilla.org/show_bug.cgi?id=1270358) +* <49.0: Desupported [Darwin 10, 11, and 12](https://bugzilla.mozilla.org/show_bug.cgi?id=1275607) (macOS 10.6, 10.7, 10.8), [SSE and MMX instruction sets](https://bugzilla.mozilla.org/show_bug.cgi?id=1284901) +* <52.0: [Moved Windows XP, Server 2003, and Vista users to esr52](https://bugzilla.mozilla.org/show_bug.cgi?id=1318922) +* <53.0: [Desupported 32-bit macOS hardware](https://bugzilla.mozilla.org/show_bug.cgi?id=1325584) +* <77.0: [Moved Darwin 13, 14, and 15](https://bugzilla.mozilla.org/show_bug.cgi?id=1639199) (macOS 10.9, 10.10, and 10.11) to esr78 diff --git a/docs/writing-rust-code/basics.md b/docs/writing-rust-code/basics.md new file mode 100644 index 0000000000..d91288133b --- /dev/null +++ b/docs/writing-rust-code/basics.md @@ -0,0 +1,84 @@ +# Basics + +## Formatting Rust code + +To format all the Rust code within a directory `$DIR`, run: +``` +./mach lint -l rustfmt --fix $DIR +``` + +## Using Cargo + +Many Cargo commands can be run on individual crates. Change into the directory +containing the crate's `Cargo.toml` file, and then run the command with +`MOZ_TOPOBJDIR` set appropriately. For example, to generate and view rustdocs +for the `xpcom` crate, run these commands: + +``` +cd xpcom/rust/xpcom +MOZ_TOPOBJDIR=$OBJDIR cargo doc +cd - +firefox target/doc/xpcom/index.html +``` +where `$OBJDIR` is the path to the object directory. + +## Using static prefs + +Static boolean/integer prefs can be easily accessed from Rust code. Add a +`rust: true` field to the pref definition in +[modules/libpref/init/StaticPrefList.yaml](https://searchfox.org/mozilla-central/source/modules/libpref/init/StaticPrefList.yaml), +like this: +```yaml +- name: my.lucky.pref + type: RelaxedAtomicBool + value: true + mirror: always + rust: true +``` +The pref can then be accessed via the `pref!` macro, like this: +``` +let my_lucky_pref = static_prefs::pref!("my.lucky.pref"); +``` + +## Helper crates + +The following in-tree helper crates provide idiomatic support for some common patterns. +- [nserror](https://searchfox.org/mozilla-central/source/xpcom/rust/nserror/src/lib.rs) +reflects `nsresult` codes into Rust. +- [nsstring](https://searchfox.org/mozilla-central/source/xpcom/rust/nsstring/src/lib.rs) + exposes bindings for XPCOM string types. You can use the same `ns{A,C}String` + types as C++ for owned strings and pass them back and forth over the + boundary. There is also `ns{A,C}Str` for dependent or borrowed strings. +- [xpcom](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/src) + provides multiple building blocks for a component's implementation. + - The `RefPtr` type is for managing reference-counted pointers. + - XPCOM component getters are generated by + [xpcom/components/gen_static_components.py](https://searchfox.org/mozilla-central/source/xpcom/components/gen_static_components.py), + and can be called like this: + ``` + use xpcom::{interfaces::nsIPrefService, RefPtr}; + let pref_service: RefPtr<nsIPrefService> = xpcom::components::Preferences::service()?; + ``` + - There is also a `get_service` function that works like `do_GetService` in + C++, as an alternative. + - A set of `derive` macros help with declaring interface implementations. The + [docs](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/xpcom_macros/src/lib.rs) + have details and examples. +- [moz_task](https://searchfox.org/mozilla-central/source/xpcom/rust/moz_task/src/lib.rs) + wraps XPCOM's threading functions in order to make it easy and safe to write + threaded code. It has helpers for getting and creating threads, dispatching + async runnables, and thread-safe handles. +- [storage](https://searchfox.org/mozilla-central/source/storage/rust/src/lib.rs) + is an interface to mozStorage, our wrapper for SQLite. It can wrap an + existing storage connection, and prepare and execute statements. This crate + wraps the synchronous connection API, and lets you execute statements + asynchronously via `moz_task`. +- [storage_variant](https://searchfox.org/mozilla-central/source/storage/variant/src/lib.rs) + is for working with variants. It also provides a `HashPropertyBag` type + that's useful for passing hash maps over XPCOM to JS. + +Unfortunately, rustdocs are [not yet generated and +hosted](https://bugzilla.mozilla.org/show_bug.cgi?id=1428139) for crates within +mozilla-central. Therefore, the crate links shown above link to files +containing the relevant rustdocs source where possible. However, you can +generate docs locally using the `cargo doc` command described above. diff --git a/docs/writing-rust-code/cpp-interop.md b/docs/writing-rust-code/cpp-interop.md new file mode 100644 index 0000000000..f10fad4221 --- /dev/null +++ b/docs/writing-rust-code/cpp-interop.md @@ -0,0 +1,240 @@ +# Rust/C++ interop + +This document describes how to use FFI in Firefox to get Rust code and C++ code to interoperate. + +## Transferable types + +Generally speaking, the more complicated is the data you want to transfer, the +harder it'll be to transfer across the FFI boundary. + +Booleans, integers, and pointers cause little trouble. +- C++ `bool` matches Rust `bool` +- C++ `uint8_t` matches Rust `u8`, `int32_t` matches Rust `i32`, etc. +- C++ `const T*` matches Rust `*const T`, `T*` matches Rust `*mut T`. + +Lists are handled by C++ `nsTArray` and Rust `ThinVec`. + +For strings, it is best to use the `nsstring` helper crate. Using a raw pointer +plus length is also possible for strings, but more error-prone. + +If you need a hashmap, you'll likely want to decompose it into two lists (keys +and values) and transfer them separately. + +Other types can be handled with tools that generate bindings, as the following +sections describe. + +## Accessing C++ code and data from Rust + +To call a C++ function from Rust requires adding a function declaration to Rust. +For example, for this C++ function: + +``` +extern "C" { +bool UniquelyNamedFunction(const nsCString* aInput, nsCString* aRetVal) { + return true; +} +} +``` +add this declaration to the Rust code: +```rust +extern "C" { + pub fn UniquelyNamedFunction(input: &nsCString, ret_val: &mut nsCString) -> bool; +} +``` + +Rust code can now call `UniquelyNamedFunction()` within an `unsafe` block. Note +that if the declarations do not match (e.g. because the C++ function signature +changes without the Rust declaration being updated) crashes are likely. (Hence +the `unsafe` block.) + +Because of this unsafety, for non-trivial interfaces (in particular when C++ +structs and classes must be accessed from Rust code) it's common to use +[rust-bindgen](https://github.com/rust-lang/rust-bindgen), which generates Rust +bindings. The documentation is +[here](https://rust-lang.github.io/rust-bindgen/). + +## Accessing Rust code and data from C++ + +A common option for accessing Rust code and data from C++ is to use +[cbindgen](https://github.com/eqrion/cbindgen), which generates C++ header +files. for Rust crates that expose a public C API. cbindgen is a very powerful +tool, and this section only covers some basic uses of it. + +### Basics + +First, add suitable definitions to your Rust. `#[no_mangle]` and `extern "C"` +are required. + +```rust +#[no_mangle] +pub unsafe extern "C" fn unic_langid_canonicalize( + langid: &nsCString, + ret_val: &mut nsCString +) -> bool { + ret_val.assign("new value"); + true +} +``` + +Then, add a `cbindgen.toml` file in the root of your crate. It may look like this: + +```toml +header = """/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */""" +autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen. See RunCbindgen.py */ +#ifndef mozilla_intl_locale_MozLocaleBindings_h +#error "Don't include this file directly, instead include MozLocaleBindings.h" +#endif +""" +include_version = true +braces = "SameLine" +line_length = 100 +tab_width = 2 +language = "C++" +# Put FFI calls in the `mozilla::intl::ffi` namespace. +namespaces = ["mozilla", "intl", "ffi"] + +# Export `ThinVec` references as `nsTArray`. +[export.rename] +"ThinVec" = "nsTArray" +``` + +Next, extend the relevant `moz.build` file to invoke cbindgen. + +```python +if CONFIG['COMPILE_ENVIRONMENT']: + CbindgenHeader('unic_langid_ffi_generated.h', + inputs=['/intl/locale/rust/unic-langid-ffi']) + + EXPORTS.mozilla.intl += [ + '!unic_langid_ffi_generated.h', + ] +``` + +This tells the build system to run cbindgen on +`intl/locale/rust/unic-langid-ffi` to generate `unic_langid_ffi_generated.h`, +which will be placed in `$OBJDIR/dist/include/mozilla/intl/`. + +Finally, include the generated header into a C++ file and call the function. + +```c++ +#include "mozilla/intl/unic_langid_ffi_generated.h" + +using namespace mozilla::intl::ffi; + +void Locale::MyFunction(nsCString& aInput) const { + nsCString result; + unic_langid_canonicalize(aInput, &result); +} +``` + +### Complex types + +Many complex Rust types can be exposed to C++, and cbindgen will generate +appropriate bindings for all `pub` types. For example: + +```rust +#[repr(C)] +pub enum FluentPlatform { + Linux, + Windows, + Macos, + Android, + Other, +} + +extern "C" { + pub fn FluentBuiltInGetPlatform() -> FluentPlatform; +} +``` + +```c++ +ffi::FluentPlatform FluentBuiltInGetPlatform() { + return ffi::FluentPlatform::Linux; +} +``` + +For an example using cbindgen to expose much more complex Rust types to C++, +see [this blog post]. + +[this blog post]: https://crisal.io/words/2020/02/28/C++-rust-ffi-patterns-1-complex-data-structures.html + +### Instances + +If you need to create and destroy a Rust struct from C++ code, the following +example may be helpful. + +First, define constructor, destructor and getter functions in Rust. (C++ +declarations for these will be generated by cbindgen.) + +```rust +#[no_mangle] +pub unsafe extern "C" fn unic_langid_new() -> *mut LanguageIdentifier { + let langid = LanguageIdentifier::default(); + Box::into_raw(Box::new(langid)) +} + +#[no_mangle] +pub unsafe extern "C" fn unic_langid_destroy(langid: *mut LanguageIdentifier) { + drop(Box::from_raw(langid)); +} + +#[no_mangle] +pub unsafe extern "C" fn unic_langid_as_string( + langid: &mut LanguageIdentifier, + ret_val: &mut nsACString, +) { + ret_val.assign(&langid.to_string()); +} +``` + +Next, in a C++ header define a destructor via `DefaultDelete`. + +```c++ +#include "mozilla/intl/unic_langid_ffi_generated.h" +#include "mozilla/UniquePtr.h" + +namespace mozilla { + +template <> +class DefaultDelete<intl::ffi::LanguageIdentifier> { + public: + void operator()(intl::ffi::LanguageIdentifier* aPtr) const { + unic_langid_destroy(aPtr); + } +}; + +} // namespace mozilla +``` + +(This definition must be visible any place where +`UniquePtr<intl::ffi::LanguageIdentifier>` is used, otherwise C++ will try to +free the code, which might lead to strange behaviour!) + +Finally, implement the class. + +```c++ +class Locale { +public: + explicit Locale(const nsACString& aLocale) + : mRaw(unic_langid_new()) {} + + const nsCString Locale::AsString() const { + nsCString tag; + unic_langid_as_string(mRaw.get(), &tag); + return tag; + } + +private: + UniquePtr<ffi::LanguageIdentifier> mRaw; +} +``` + +This makes it possible to instantiate a `Locale` object and call `AsString()`, +all from C++ code. + +## Other examples + +For a detailed explanation of an interface in Firefox that doesn't use cbindgen +or rust-bindgen, see [this blog post](https://hsivonen.fi/modern-cpp-in-rust/). diff --git a/docs/writing-rust-code/index.md b/docs/writing-rust-code/index.md new file mode 100644 index 0000000000..721a9be811 --- /dev/null +++ b/docs/writing-rust-code/index.md @@ -0,0 +1,16 @@ +# Writing Rust Code + +This page explains how to write and work with Rust code in Firefox, with an +emphasis on interoperation with C++ code. + +The [build documentation](/build/buildsystem/rust.rst) explains how to add +new Rust code to Firefox. The [test documentation](/testing-rust-code/index.md) +explains how to test and debug Rust code in Firefox. + +```{toctree} +:titlesonly: +:maxdepth: 1 +:glob: + +* +``` diff --git a/docs/writing-rust-code/uniffi.md b/docs/writing-rust-code/uniffi.md new file mode 100644 index 0000000000..56ffc0935a --- /dev/null +++ b/docs/writing-rust-code/uniffi.md @@ -0,0 +1,70 @@ +# Generating Javascript bindings with UniFFI + +Firefox supports auto-generating JS bindings for Rust components using [UniFFI](https://mozilla.github.io/uniffi-rs/). + +## How it works + +The Rust crate contains a +[UniFFI Definition Language (UDL) file](https://mozilla.github.io/uniffi-rs/udl_file_spec.html), which describes the +interface to generate bindings for. + +The UniFFI core generates the scaffolding: Rust code which acts as the FFI layer from the UDL file. The functions of +this layer all use the C calling convention and all structs use a C layout, this is the de facto standard for FFI +interoperability. + +The [`uniffi-bindgen-gecko-js`](https://searchfox.org/mozilla-central/source/toolkit/components/uniffi-bindgen-gecko-js) +tool, which lives in the Firefox source tree, generates 2 things: + - A JS interface for the scaffolding code, which uses [WebIDL](/dom/bindings/webidl/index.rst) + - A module that uses the scaffolding to provide the bindings API. + +Currently, this generated code gets checked in to source control. We are working on a system to avoid this and +auto-generate it at build time instead (see [bugzilla 1756214](https://bugzilla.mozilla.org/show_bug.cgi?id=1756214)). + +## Before creating new bindings with UniFFI + +Keep a few things in mind before you create a new set of bindings: + + - **UniFFI was not written to maximize performance.** It's code is efficient enough to handle many use cases, but at this + point should probably be avoided for performance critical components. + - **uniffi-bindgen-gecko-js bindings run with chrome privileges.** Make sure this is acceptable for your project + - **Only a subset of Rust types can be exposed via the FFI.** Check the [UniFFI Book](https://mozilla.github.io/uniffi-rs/) to see what + types are compatible with UniFFI. + +If any of these are blockers for your work, consider discussing it further with the UniFFI devs to see if we can support +your project: + + - Chat with us on `#uniffi` on Matrix/Element + - File an issue on [mozilla/uniffi](https://github.com/mozilla/uniffi-rs/) + +## Creating new bindings with UniFFI + +You can see an example of this feature in use: [when application-services swapped the tabs js sync engine with rust](https://bugzilla.mozilla.org/show_bug.cgi?id=1791851) + +Here's how you can create a new set of bindings using UniFFI: + + 1. UniFFI your crate (if it isn't already): + - [Create a UDL file to describe your interface](https://mozilla.github.io/uniffi-rs/udl_file_spec.html) + - [Set up your Rust crate to generate scaffolding](https://mozilla.github.io/uniffi-rs/tutorial/Rust_scaffolding.html) + 2. Add your crate as a Firefox dependency (if it isn't already) + - **If the code will exist in the mozilla-central repo:** + - Create a new directory for the Rust crate + - Edit `toolkit/library/rust/shared/Cargo.toml` and add a dependency to your library path + - **If the code exists in an external repo:** + - Edit `toolkit/library/rust/shared/Cargo.toml` and add a dependency to your library URL + - Run `mach vendor rust` to vendor in your Rust code + 3. Generate bindings code for your crate + - Add the path of your UDL (that you made in step 1) in `toolkit/components/uniffi-bindgen-gecko-js/mach_commands.py` + - Run `./mach uniffi generate` + - add your newly generated `Rust{udl-name}.sys.mjs` file to `toolkit/components/uniffi-bindgen-gecko-js/components/moz.build` + - Then simply import your module to the file you want to use it in and start using your APIs! + + Example from tabs module: + + ``` js + ChromeUtils.defineESModuleGetters(lazy, { + ... + TabsStore: "resource://gre/modules/RustTabs.sys.mjs", + }); + ... + this._rustStore = await lazy.TabsStore.init(path); + ``` diff --git a/docs/writing-rust-code/update-policy.md b/docs/writing-rust-code/update-policy.md new file mode 100644 index 0000000000..27d575a36e --- /dev/null +++ b/docs/writing-rust-code/update-policy.md @@ -0,0 +1,150 @@ +# Rust Update Policy + +We document here the decision making and planning around when we update the +Rust toolchains used and required to build Firefox. + +This allows contributors to know when new features will be usable, and +downstream packagers to know what toolchain will be required for each Firefox +release. Both benefit from the predictability of a schedule. + +## Policy + +### Official builds + +_We ship official stable Firefox with a stable Rust._ + +As a general rule, we update the Rust version used to build Firefox Nightly +soon after its release, unless it's less than 7 days away from a soft-freeze, +in which case we wait for the next Nightly train. + +We don't upgrade the Rust version in the beta or release branches of Firefox. + +The following exceptions apply: + +- We may use a Rust version from the Rust beta or nightly channels for new + platforms (e.g. we did so for Android, arm64 Windows and arm64 macOS), and + later upgrade when that Rust version becomes stable (we may even do so on the + Firefox beta branch). + +- We may skip the update (or backout the update) if major problems are + encountered (typically, we've had to do so because of build problems, crash + reporting bustage, or performance issues). + +### Developer builds + +_Local developer builds use whatever Rust toolchain is available on the +system._ + +Someone building Firefox can maintain the latest stable Rust with the `rustup` +or `mach bootstrap` tools, or try other variations. + +### Minimum Supported Rust Version + +_We will update the Minimum Supported Rust Version (MSRV) when required._ + +The MSRV will generally remain unchanged, until a newer version is required +by some code. + +When that happens, we'll prefer to update the MSRV to the strict minimum +required at that moment (e.g. if we require version 1.47.0, the currently used +Rust version is 1.51.0, and a crate needs 1.50.0, we'll prefer to update the +MSRV to 1.50.0 rather than 1.51.0). + +The MSRV won't be updated to a version of Rust that hasn't been used for +Firefox Nightly for at least 14 days. + +We expect ESR releases will keep their MSRV, so backporting security fixes may +require Rust compatibility work. + +### Rationale + +Historically, the Rust ecosystem quickly required new features provided by new +Rust compilers, which made it necessary to update the minimum supported version +quite often, and as such, a scheduled update was deemed a better trade-off. + +Fast-forward several years, and new Rust compiler releases more rarely sport +ground-breaking new features, which has reduced the necessity to update quite +significantly. + +On the flip side, in some instances, we have had to stick to specific versions +of the Rust compiler for extended periods of time because of e.g. regressions, +going against the schedule. + +## Schedule + +Here are the Rust versions for each Firefox version. + +- The "Uses" column indicates the version of Rust used to build + releases shipped to users. + +- The "MSRV" column indicates the minimum supported Rust version to build + the sources. + +| Firefox Version | Uses | MSRV | Rust "Uses" release date | Nightly Soft Freeze | Firefox release date | +|-----------------|------|----------|--------------------------|---------------------|----------------------| +| Firefox 56 | Rust 1.19.0 | 1.17.0 | 2017 April 27 | | 2017 September 26 +| Firefox 57 | Rust 1.19.0 | 1.19.0 | 2017 July 20 | | 2017 November 14 +| Firefox 58 | Rust 1.21.0 | 1.21.0 | 2017 October 12 | | 2018 January 16 +| Firefox 59 | Rust 1.22.1 | 1.22.1 | 2017 November 23 | | 2018 March 13 +| Firefox 60 | Rust 1.24.0 | 1.24.0 | 2018 February 15 | | 2018 May 9 +| Firefox 61 | Rust 1.24.0 | 1.24.0 | 2018 February 15 | | 2018 June 26 +| Firefox 62 | Rust 1.24.0 | 1.24.0 | 2018 February 15 | | 2018 September 5 +| Firefox 63 | Rust 1.28.0 | 1.28.0 | 2018 August 2 | | 2018 October 23 +| Firefox 64 | Rust 1.29.2 | 1.29.0 | 2018 September 13 | 2018 October 15 | 2018 December 11 +| Firefox 65 | Rust 1.30.0 | 1.30.0 | 2018 October 25 | 2018 December 3 | 2019 January 29 +| Firefox 66 | Rust 1.31.0 | 1.31.0 | 2018 December 6 | 2019 January 21 | 2019 March 19 +| Firefox 67 | Rust 1.32.0 | 1.32.0 | 2019 January 17 | 2019 March 11 | 2019 May 21 +| Firefox 68 | Rust 1.34.0 | 1.34.0 | 2019 April 11 | 2019 May 13 | 2019 July 9 +| Firefox 69 | Rust 1.35.0 | 1.35.0 | 2019 May 23 | 2019 July 1 | 2019 September 3 +| Firefox 70 | Rust 1.37.0 | 1.36.0 | 2019 July 4 | 2019 August 26 | 2019 October 22 +| Firefox 71 | Rust 1.37.0 | 1.37.0 | 2019 August 15 | 2019 October 14 | 2019 December 3 +| Firefox 72 | Rust 1.38.0 | 1.37.0 | 2019 August 15 | 2019 November 25 | 2020 January 7 +| Firefox 73 | Rust 1.39.0 | 1.39.0 | 2019 November 7 | 2020 January 1 | 2020 February 11 +| Firefox 74 | Rust 1.39.0 | 1.39.0 | 2019 November 7 | 2020 February 6 | 2020 March 10 +| Firefox 75 | Rust 1.41.0 | 1.41.0 | 2020 January 30 | 2020 March 5 | 2020 April 7 +| Firefox 76 | Rust 1.41.0 | 1.41.0 | 2020 January 30 | 2020 April 2 | 2020 May 5 +| Firefox 77 | Rust 1.41.1 | 1.41.0 | 2020 January 30 | 2020 April 30 | 2020 June 2 +| Firefox 78 | Rust 1.43.0 | 1.41.0 | 2020 April 23 | 2020 May 28 | 2020 June 30 +| Firefox 79 | Rust 1.43.0 | 1.43.0 | 2020 April 23 | 2020 June 26 | 2020 July 28 +| Firefox 80 | Rust 1.43.0 | 1.43.0 | 2020 April 23 | 2020 July 23 | 2020 August 25 +| Firefox 81 | Rust 1.43.0 | 1.43.0 | 2020 April 23 | 2020 August 20 | 2020 September 22 +| Firefox 82 | Rust 1.43.0 | 1.43.0 | 2020 April 23 | 2020 September 17 | 2020 October 20 +| Firefox 83 | Rust 1.43.0 | 1.43.0 | 2020 April 23 | 2020 October 15 | 2020 November 17 +| Firefox 84 | Rust 1.47.0 | 1.43.0 | 2020 October 8 | 2020 November 12 | 2020 December 15 +| Firefox 85 | Rust 1.48.0 | 1.47.0 | 2020 November 19 | 2020 December 10 | 2021 January 26 +| Firefox 86 | Rust 1.49.0 | 1.47.0 | 2020 December 31 | 2021 January 21 | 2021 February 23 +| Firefox 87 | Rust 1.50.0 | 1.47.0 | 2021 February 11 | 2021 February 18 | 2021 March 23 +| Firefox 88 | Rust 1.50.0 | 1.47.0 | 2021 February 11 | 2021 March 18 | 2021 April 19 +| Firefox 89 | Rust 1.51.0 | 1.47.0 | 2021 March 25 | 2021 April 15 | 2021 June 1 +| Firefox 90 | Rust 1.52.0 | 1.47.0 | 2021 May 6 | 2021 May 27 | 2021 June 29 +| Firefox 91 | Rust 1.53.0 | 1.51.0 | 2021 June 17 | 2021 July 8 | 2021 August 10 +| Firefox 92 | Rust 1.54.0 | 1.51.0 | 2021 July 29 | 2021 August 5 | 2021 September 7 +| Firefox 93 | Rust 1.54.0 | 1.51.0 | 2021 July 29 | 2021 September 2 | 2021 October 5 +| Firefox 94 | Rust 1.55.0 | 1.53.0 | 2021 September 9 | 2021 September 30 | 2021 November 2 +| Firefox 95 | Rust 1.56.0 | 1.53.0 | 2021 October 21 | 2021 October 28 | 2021 December 7 +| Firefox 96 | Rust 1.57.0 | 1.53.0 | 2021 December 2 | 2021 December 2 | 2022 January 11 +| Firefox 97 | Rust 1.57.0 | 1.57.0 | 2021 December 2 | 2022 January 6 | 2022 February 8 +| Firefox 98 | Rust 1.58.0 | 1.57.0 | 2022 January 13 | 2022 February 2 | 2022 March 8 +| Firefox 99 | Rust 1.59.0 | 1.57.0 | 2022 February 24 | 2022 March 3 | 2022 April 5 +| Firefox 100 | Rust 1.59.0 | 1.57.0 | 2022 February 24 | 2022 March 31 | 2022 May 3 +| Firefox 101 | Rust 1.60.0 | 1.59.0 | 2022 April 7 | 2022 April 28 | 2022 May 31 +| Firefox 102 | Rust 1.60.0 | 1.59.0 | 2022 April 7 | 2022 May 26 | 2022 June 28 +| Firefox 103 | Rust 1.61.0 | 1.59.0 | 2022 May 19 | 2022 June 23 | 2022 July 27 +| Firefox 104 | Rust 1.62.0 | 1.59.0 | 2022 June 30 | 2022 July 21 | 2022 August 23 +| Firefox 105 | Rust 1.63.0 | 1.61.0 | 2022 August 11 | 2022 August 18 | 2022 September 20 +| Firefox 106 | Rust 1.63.0 | 1.61.0 | 2022 August 11 | 2022 September 15 | 2022 October 18 +| Firefox 107 | Rust 1.64.0 | 1.61.0 | 2022 September 22 | 2022 October 13 | 2022 November 15 +| Firefox 108 | Rust 1.65.0 | 1.63.0 | 2022 November 3 | 2022 November 10 | 2022 December 13 +| Firefox 109 | Rust 1.65.0 | 1.63.0 | 2022 November 3 | 2022 December 8 | 2023 January 17 +| Firefox 110 | Rust 1.66.0 | 1.65.0 | 2022 December 15 | 2023 January 12 | 2023 February 14 +| Firefox 111 | Rust 1.67.0 | 1.65.0 | 2023 January 26 | 2023 February 9 | 2023 March 14 +| Firefox 112 | Rust 1.67.0 | 1.65.0 | 2023 January 26 | 2023 March 9 | 2023 April 11 +| Firefox 113 | Rust 1.68.0 | 1.65.0 | 2023 March 9 | 2023 April 6 | 2023 May 9 +| Firefox 114 | Rust 1.69.0 | 1.65.0 | 2023 April 20 | 2023 May 4 | 2023 June 6 +| **Estimated** | +| Firefox 115 | Rust 1.69.0 | 1.66.0 | 2023 April 20 | 2023 June 1 | 2023 July 4 +| Firefox 116 | Rust 1.70.0 | ? | 2023 June 1 | 2023 June 29 | 2023 August 1 +| Firefox 117 | Rust 1.71.0 | ? | 2023 July 13 | 2023 July 27 | 2023 August 29 +| Firefox 118 | Rust 1.71.0 | ? | 2023 July 13 | 2023 August 24 | 2023 September 26 +| Firefox 119 | Rust 1.72.0 | ? | 2023 August 24 | 2023 September 21 | 2023 October 24 +| Firefox 120 | Rust 1.73.0 | ? | 2023 October 4 | 2023 October 19 | 2023 November 21 diff --git a/docs/writing-rust-code/xpcom.md b/docs/writing-rust-code/xpcom.md new file mode 100644 index 0000000000..dbe297e368 --- /dev/null +++ b/docs/writing-rust-code/xpcom.md @@ -0,0 +1,120 @@ +# XPCOM components in Rust + +XPCOM components can be written in Rust. + +## A tiny example + +The following example shows a new type that implements `nsIObserver`. + +First, create a new empty crate (e.g. with `cargo init --lib`), and add the +following dependencies in its `Cargo.toml` file. + +```toml +[dependencies] +libc = "0.2" +nserror = { path = "../../../xpcom/rust/nserror" } +nsstring = { path = "../../../xpcom/rust/nsstring" } +xpcom = { path = "../../../xpcom/rust/xpcom" } +``` + +(The number of `../` occurrences will depend on the depth of the crate in the +file hierarchy.) + +Next hook it into the build system according to the [build +documentation](/build/buildsystem/rust.rst). + +The Rust code will need to import some basic types. `xpcom::interfaces` +contains all the usual `nsI` interfaces. + +```rust +use libc::c_char; +use nserror::nsresult; +use std::sync::atomic::{AtomicBool, Ordering}; +use xpcom::{interfaces::nsISupports, RefPtr}; +``` + +The next part declares the implementation. + +```rust +#[xpcom(implement(nsIObserver), atomic)] +struct MyObserver { + ran: AtomicBool, +} +``` + +This defines the implementation type, which will be refcounted in the specified +way and implement the listed xpidl interfaces. It will also declare a second +initializer struct `InitMyObserver` which can be used to allocate a new +`MyObserver` using the `MyObserver::allocate` method. + +Next, all interface methods are declared in the `impl` block as `unsafe` methods. + +```rust +impl MyObserver { + #[allow(non_snake_case)] + unsafe fn Observe( + &self, + _subject: *const nsISupports, + _topic: *const c_char, + _data: *const u16, + ) -> nsresult { + self.ran.store(true, Ordering::SeqCst); + nserror::NS_OK + } +} +``` + +These methods always take `&self`, not `&mut self`, so we need to use interior +mutability: `AtomicBool`, `RefCell`, `Cell`, etc. This is because all XPCOM +objects are reference counted (like `Arc<T>`), so cannot provide exclusive access. + +XPCOM methods are unsafe by default, but the +[xpcom_method!](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/src/method.rs) +macro can be used to clean this up. It also takes care of null-checking and +hiding pointers behind references, lets you return a `Result` instead of an +`nsresult,` and so on. + +To use this type within Rust code, do something like the following. + +```rust +let observer = MyObserver::allocate(InitMyObserver { + ran: AtomicBool::new(false), +}); +let rv = unsafe { + observer.Observe(x.coerce(), + cstr!("some-topic").as_ptr(), + ptr::null()) +}; +assert!(rv.succeeded()); +``` + +The implementation has an (auto-generated) `allocate` method that takes in an +initialization struct, and returns a `RefPtr` to the instance. + +`coerce` casts any XPCOM object to one of its base interfaces; in this case, +the base interface is `nsISupports`. In C++, this would be handled +automatically through inheritance, but Rust doesn’t have inheritance, so the +conversion must be explicit. + +## Bigger examples + +The following XPCOM components are written in Rust. + +- [kvstore](https://searchfox.org/mozilla-central/source/toolkit/components/kvstore), + which exposes the LMDB key-value store (via the [Rkv + library](https://docs.rs/rkv)) The API is asynchronous, using `moz_task` to + schedule all I/O on a background thread, and supports getting, setting, and + iterating over keys. +- [cert_storage](https://searchfox.org/mozilla-central/source/security/manager/ssl/cert_storage), + which stores lists of [revoked intermediate certificates](https://blog.mozilla.org/security/2015/03/03/revoking-intermediate-certificates-introducing-onecrl/). +- [bookmark_sync](https://searchfox.org/mozilla-central/source/toolkit/components/places/bookmark_sync), + which [merges](https://mozilla.github.io/dogear) bookmarks from Firefox Sync + with bookmarks in the Places database. + [There's also some docs on how Rust interacts with Sync](/services/sync/rust-engines.rst) +- [webext_storage_bridge](https://searchfox.org/mozilla-central/source/toolkit/components/extensions/storage/webext_storage_bridge), + which powers the WebExtension storage.sync API. It's a self-contained example + that pulls in a crate from application-services for the heavy lifting, wraps + that up in a Rust XPCOM component, and then wraps the component in a JS + interface. There's also some boilerplate there around adding a + `components.conf` file, and a dummy C++ header that declares the component + constructor. [It has some in-depth documentation on how it hangs together](../toolkit/components/extensions/webextensions/webext-storage.rst). -- cgit v1.2.3