diff options
Diffstat (limited to 'doc/antora/modules/developers')
-rw-r--r-- | doc/antora/modules/developers/nav.adoc | 7 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/bugs.adoc | 194 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/coding-methods.adoc | 235 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/contributing.adoc | 126 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/coverage.adoc | 11 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/index.adoc | 18 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/profile.adoc | 41 | ||||
-rw-r--r-- | doc/antora/modules/developers/pages/release-method.adoc | 55 |
8 files changed, 687 insertions, 0 deletions
diff --git a/doc/antora/modules/developers/nav.adoc b/doc/antora/modules/developers/nav.adoc new file mode 100644 index 0000000..ed6962a --- /dev/null +++ b/doc/antora/modules/developers/nav.adoc @@ -0,0 +1,7 @@ +* xref:index.adoc[Developers] +** xref:bugs.adoc[Bugs] +** xref:coding-methods.adoc[Coding Methods] +** xref:coverage.adoc[Code Coverage] +** xref:profile.adoc[Profiling] +** xref:contributing.adoc[Contributing] +** xref:release-method.adoc[Release Method] diff --git a/doc/antora/modules/developers/pages/bugs.adoc b/doc/antora/modules/developers/pages/bugs.adoc new file mode 100644 index 0000000..b63329c --- /dev/null +++ b/doc/antora/modules/developers/pages/bugs.adoc @@ -0,0 +1,194 @@ += Bugs + +== Introduction + +The FreeRADIUS web site is at https://freeradius.org/, and most +information referenced in this document can be found there. + +This document is primarily for non-developers of the FreeRADIUS +server. If you are able to patch the code to work correctly, then +we invite you to join the development list to discuss it. If +you’re the type who know little about how to code, then this is +the place for you! + +== You found a bug + +Where the server terminates ungracefully due to a bus error, +segmentation violation, or other memory error, you should create a new +issue in the issue tracker https://bugs.freeradius.org/, including +information from the debugging sections below. + +For any other issues, you should first discuss them on the +https://freeradius.org/support/[FreeRADIUS users list], to +see if anyone can reproduce them. Often there’s a simple explanation of +why the server behaves as it does, and it’s not necessarily a bug in the +code, so browse the lists’ archives of the last two months, and if you +don’t see messages about it, ask! + +If the behavior is correct but confusing, we think that’s a bug too, and +you should file a bug against our documentation. + +For more information about the users list, the lists’ archives and the +faq, please visit https://www.freeradius.org/list/users.html Please make +sure to READ and RESPECT the house-rules. You will get much better +response and much faster if you do! + +== Core dumps + +If the server (or one of the accompanying programs) core dumps, then you +should rebuild the server as follows: + +``` +$ ./configure --enable-developer +$ make +$ make install +``` + +and then run the program again. You may have to to enable core dumps, +via: + +``` +$ ulimit -c unlimited +``` + +When it core dumps, do: + +``` +$ gdb /path/to/executable /path/to/core/file +``` + +Enable logging in `gdb` via the following commands: + +``` +(gdb) set logging file gdb-radiusd.log +(gdb) set logging on +``` + +and follow the instructions in the proceeding section. + +You can also enable the `panic_action` given in +`raddb/radiusd.conf`. See the comments in that file for more details +about automatically collecting gdb debugging information when the server +crashes. + +== Debugging a live server + +If you can’t get a core dump, or the problem doesn’t result in a core +dump, you may have to run the server under gdb. To do this, ensure that +you have symbols in the binaries (i.e. a 'non-stripped' binary) by +re-building the server as described in the previous section. Then, run +the server under gdb as follows: + +``` +$ gdb radiusd +``` + +Enable logging in `gdb` via the following commands: + +``` +(gdb) set logging file gdb-radiusd.log +(gdb) set logging on +``` + +Tell `gdb` to pass any necessary command-line arguments to the server: + +``` +(gdb) set args ... +``` + +Where the ``…'' are the command-line arguments you normally pass to +radiusd. For debugging, you probably want to do: + +``` +(gdb) set args -fxx +``` + +Then, do: + +``` +(gdb) run +``` + +When something interesting happens, you can hit CTRL-C in the window, +and you should be back at the gdb prompt: + +``` +(gdb) +``` + +And follow the instructions in the next section. + +== Obtaining useful information + +Once you have a core dump loaded into gdb, or FreeRADIUS running under +gdb, you may use the commands below to get useful information about the +state of the server. + +If the server was built with threads, you can do: + +``` +(gdb) info threads +``` + +Which will give you information about the threads. If the server isn’t +threaded, that command-line will print a message saying so. + +Then, do: + +``` +(gdb) thread apply all bt full +``` + +If the server isn’t threaded, the `thread apply` section isn’t +necessary + +The output should be printed to the screen, and also sent to the +`gdb-radiusd.log` file. + +You should then submit the information from the log file, along with any +server output, the output of `radiusd -xv`, and information about your +operating system to: + +https://bugs.freeradius.org/ + +Submitting it to the bug database ensures that the bug report won’t get +forgotten, and that it will be dealt with in due course. + +You should provide the issue number in any mail sent to the user’s list. + +== Valgrind + +On Linux systems, `valgrind` is a useful tool that can catch certain +classes of bugs. To use it, run the server via: + +``` +$ valgrind --tool=memcheck --leak-check=full radiusd -Xm +``` + +It will print out certain kinds of errors to the screen. There may be a +number of errors related to OpenSSL, dlopen(), or libtldl. We cannot do +anything about those problems. However, any errors that are inside of +the FreeRADIUS source should be brought to our attention. + +== Running with `screen` + +If the bug is a crash of the server, and it takes a long time for the +crash to happen, perform the following steps: + +* Log in as root. +* Open a https://www.gnu.org/software/screen/[screen] session: `$ screen bash`. +* Make sure FreeRADIUS is not running. +* Make sure you have all the debug symbols about, or a debugable version +of the server installed (one built with `--enable-developer` as above). +* Configure screen to log to a file by pressing `Ctrl+a`, then `h`. +* Type `gdb /path/to/radiusd` (or /path/to/freeradius on Debian). +* At the `(gdb)` prompt, type `run -X`. +* Detach from screen with `Ctrl+a`, `d`. +* When you notice FreeRADIUS has died, reconnect to your screen session +`$ screen -D -r`. +* At the `(gdb)` prompt type `where` or for _lots_ of info try +`thread apply all bt full`. +* Tell screen to stop logging, `Ctrl+a`, `h`. +* Logout from screen. + +FreeRADIUS Project, copyright 2019 diff --git a/doc/antora/modules/developers/pages/coding-methods.adoc b/doc/antora/modules/developers/pages/coding-methods.adoc new file mode 100644 index 0000000..3de92c4 --- /dev/null +++ b/doc/antora/modules/developers/pages/coding-methods.adoc @@ -0,0 +1,235 @@ += Coding Methods + +The following is a short set of guidelines to follow while programming. It does +not address coding styles, function naming methods, or debugging methods. +Rather, it describes the processes which should go on in the programmer’s mind +while they are programming. + +Coding standards apply to function names, the look of the code, and coding +consistency. Coding methods apply to the daily practices used by the programmer +to write code. + +== Comment your code + +If you don’t, you’ll be forced to debug it six months later, when you have no clue +as to what it’s doing. + +If someone _really_ hates you, you’ll be forced to debug un-commented code that +someone else wrote. You don’t want to do that. + +For FreeRADIUS, use doxygen `@`-style comments so you get the +benefits of the developer documentation site, https://doc.freeradius.org/. + +== Give things reasonable names + +Variables and functions should have names. Calling them `x`, `xx`, +and `xxx` makes your life hell. Even `foo` and `i` are +problematic. + +Avoid smurfs. Don’t re-use struct names in field names, i. e. + +[source,c] +---- +struct smurf { + char *smurf_pappa_smurf; +} +---- + +If your code reads as full English sentences, you’re doing it right. + +== Check input parameters in the functions you write + +Your function _cannot_ do anything right if the user passed in garbage +and you were too lazy to check for garbage input. + +`assert()` (`fr_assert()`) is ugly. Use it. + +[NOTE] +==== +GIGO, "Garbage In, Garbage Out," is wrong. If your function gets +garbage input, it should complain loudly and with great +descriptiveness. +==== + +== Write useful error messages + +"Function failed" is useless as an error message. It makes debugging the code +impossible without source-level instrumentation. + +If you’re going to instrument the code at source level for error messages, leave +the error messages there, so the next sucker won’t have to do the same work all +over again. + +== Check error conditions from the functions you call + +Your function _cannot_ do anything right if you called another function, and +they gave you garbage output. + +One of the most common mistakes is: + +[source,c] +---- +fp = fopen(...); +fgetc(fp); /* core dumps! */ +---- + +If the programmer had bothered to check for a `NULL` fp (error +condition), then they could have produced a descriptive error message +instead of having the program core dump. + +== Core dumps are for weenies + +If your program core dumps accidentally, you’re a bad programmer. You don’t know +what your program is doing, or what it’s supposed to be doing when anything goes +wrong. + +If it hits an `assert()` and calls `abort()`, you’re a genius. You’ve thought +ahead to what _might_ go wrong, and put in an assertion to ensure that it fails +in a _known manner_ when something _does_ go wrong. (As it usually does…) + +== Initialize your variables + +`memset()` (`talloc_zero()`) is your friend. `ptr = NULL` is nice, +too. + +Having variables containing garbage values makes it easy for the code to do +garbage things. The contents of local variables are inputs to your function. See +xref:#_check_input_parameters_in_the_functions_you_write[#3]. + +It’s also nearly impossible for you to debug any problems, as you can’t tell the +variables with garbage values from the real ones. + +== Don’t allow buffer over-runs + +They’re usually accidental, but they cause core dumps. `strcpy()` and `strcat()` +are ugly. Use them under duress. + +`sizeof()` is your friend. + +== `const` is your friend + +If you don’t mean to modify an input structure to your function, declare it +`const`. Declare string constants `const`. It can’t hurt, and it allows more +errors to be found at compile time. + +Use `const` everywhere. Once you throw a few into your code, and have it save +you from stupid bugs, you’ll blindly throw in `const` everywhere. It’s a +life-saver. + +== Use C compiler warnings + +Turn on all of the C compiler warnings possible. You might have to turn some off +due to broken system header files, though. But the more warnings the merrier. + +Getting error messages at compile time is much preferable to getting core dumps +at run time. See xref:#_initialize_your_variables[#7]. + +Notice that the C compiler error messages are helpful? You should write error +messages like this, too. See xref:#_write_useful_error_messages[#4]. + +== Avoid UNIXisms and ASCIIisms and visualisms + +You don’t know under what system someone will try to run your code. Don’t demand +that others use the same OS or character set as you use. + +Never assign numbers to pointers. If foo is a `char*`, and you want it to be be +`NULL`, assign `NULL`, not `0`. The zeroth location is perfectly as addressable +as any other on plenty of OSes. Not all the world runs on Unix (though it should +:) ). + +Another common mistake is to assume that the zeroth character in the character +set is the string terminator. Instead of terminating a string with `0`, use +`'\0'`, which is always right. Similarly, `memset()` with the appropriate value: +`NULL`, `'\0'`, or `0` for pointers, chars, and numbers. + +Don’t put tabs in string constants, either. Always use `'\t'` to represent a +tab, instead of ASCII 9. Literal tabs are presented to readers of your code as +arbitrary whitespace, and it’s easy to mess up. + +== Make conditionals explicit + +Though it’s legal to test `if (foo) {}` if you test against the appropriate +value (like `NULL` or `'\0'`), your code is prettier and easier for others to +read without having to eyeball your prototypes continuously to figure out what +you’re doing (especially if your variables aren’t well-named). See +xref:#_give_things_reasonable_names[#2]. + +== Test your code + +Even Donald Knuth writes buggy code. You’ll never find all of the bugs in your +code. But writing a test program definitely helps. + +This means that you’ll have to write your code so that it will be easily +testable. As a result, it will look better and be easier to debug. + +== Hints, Tips, and Tricks + +This section lists many of the common `rules` associated with code submitted to +the project. There are always exceptions… but you must have a really good reason +for doing so. + +== Read the Documentation and follow the CodingStyle + +The FreeRADIUS server has a common coding style. Use real tabs to indent. There +is whitespace in variable assignments (`i = 1`, not `i=1`). + +When in doubt, format your code to look the same as code already in the server. +If your code deviates too much from the current style, it is likely to be +rejected without further review, and without comment. + +== #ifdefs are ugly + +Code cluttered with `#ifdef` s is difficult to read and maintain. Don’t do it. +Instead, put your `#ifdef` s in a header, and conditionally define `static +inline` functions, or macros, which are used in the code. Let the compiler +optimize away the 'no-op' case. + +Simple example, of poor code: + +[source,c] +---- +#ifdef CONFIG_MY_FUNKINESS + init_my_stuff(foo); +#endif +---- + +Cleaned-up example: + +(in header): + +[source,c] +---- +#ifndef CONFIG_MY_FUNKINESS + static inline void init_my_stuff(char *foo) {} +#endif +---- + +(in the code itself): + +[source,c] +---- +init_my_stuff(dev); +---- + +== `static inline` is better than a macro + +Static inline functions are greatly preferred over macros. They provide type +safety, have no length limitations, no formatting limitations, and under gcc +they are as cheap as macros. + +Macros should only be used for cases where a static inline is clearly suboptimal +(there a few, isolated cases of this in fast paths), or where it is impossible +to use a static inline function (such as string-izing). + +`static inline` is preferred over `$$static __inline__$$`, `extern inline`, and +`$$extern __inline__$$`. + +== Don’t over-design + +Don’t try to anticipate nebulous future cases which may or may not be useful: +_Make it as simple as you can, and no simpler._ + +Split up functionality as much as possible. If your code needs to do two +unrelated things, write two functions. Mashing two kinds of work into one +function makes the server difficult to debug and maintain. + diff --git a/doc/antora/modules/developers/pages/contributing.adoc b/doc/antora/modules/developers/pages/contributing.adoc new file mode 100644 index 0000000..e4a4b0a --- /dev/null +++ b/doc/antora/modules/developers/pages/contributing.adoc @@ -0,0 +1,126 @@ += Contributing + +== Submitting patches or diff’s to the FreeRADIUS project + +For a person or company wishing to submit a change to the FreeRADIUS +project the process can sometimes be daunting if you’re not familiar +with "the system." This text is a collection of suggestions which can +greatly increase the chances of your change being accepted. + +Note: Only trivial patches will be accepted via email. Large patches, or +patches that modify a number of files MUST be submitted as a +https://github.com/FreeRADIUS/freeradius-server/pulls[pull-request via GitHub]. + +== Hints and tips + +=== 1. Describe your changes + +Describe the technical detail of the change(s) your patch or commit +includes. + +Be as specific as possible. The WORST descriptions possible include +things like "update file X", "bug fix for file X", or "this patch +includes updates for subsystem X. Please apply." + +If your description starts to get long, that’s a sign that you probably +need to split up your commit. See the next point. + +=== 2. Separate your changes + +Separate each logical change into its own commit. + +For example, if your changes include both bug fixes and performance +enhancements for a single module, separate those changes into two or +more patches. + +On the other hand, if you make a single change to numerous files, group +those changes into a single commit. Thus a single LOGICAL change is +contained within a single commit. + +If one commit depends on another commit in order for a change to be +complete, that is OK. Simply note "this commit depends on commit X" in +the extended commit description. + +If your commit includes significant whitespace changes these should also +be broken out into another, separate, commit. + +== Submitting patches via GitHub + +See the following links for more details about submitting via github: + +* https://help.github.com/articles/fork-a-repo +* http://wiki.freeradius.org/contributing/GitHub + +== Submitting patches via email + +=== 1. diff -u + +Use `diff -u` or `diff -urN` to create patches. + +All changes to the source occur in the form of patches, as generated by +diff(1). When creating your patch, make sure to create it in unified +diff format, as supplied by the `-u` argument to diff(1). Patches +should be based in the root source directory, not in any lower +subdirectory. + +To create a patch for a single file, it is often sufficient to do:: + +``` +SRCTREE=/home/user/src/freeradiusd/ +MYFILE=src/modules/rlm_foo/foo.c + +cd $SRCTREE +cp $MYFILE $MYFILE.orig +vi $MYFILE # make your change +diff -u $MYFILE.orig $MYFILE > /tmp/patch +``` + +To create a patch for multiple files, you should unpack a `vanilla`, +or unmodified source tree, and generate a diff against your own source +tree. For example: + +``` +MYSRC=/home/user/src/freeradiusd-feature/ + +gunzip freeradiusd-version.tar.gz +tar xvf freeradiusd-version.tar +diff -urN freeradiusd-version $MYSRC > ~/feature-version.patch +``` + +=== 2. Select e-mail destination + +If you are on the developers mailing list, send the patch there. +mailto:freeradius-devel@lists.freeradius.org[freeradius-devel@lists.freeradius.org] + +Otherwise, send the patch to +mailto:patches@freeradius.org[patches@freeradius.org] + +=== 3. No MIME, no links, no compression, no attachments. Just plain text + +The developers need to be able to read and comment on the changes you +are submitting. It is important for a developer to be able to `quote` +your changes, using standard e-mail tools, so that they may comment on +specific portions of your code. + +For this reason, all patches should be submitting e-mail `inline`. + +Do not attach the patch as a MIME attachment, compressed or not. Many +popular e-mail applications will not always transmit a MIME attachment +as plain text, making it impossible to comment on your code. A MIME +attachment also takes a bit more time to process, decreasing the +likelihood of your MIME-attached change being accepted. + +Compressed patches are generally rejected outright. If the developer has +to do additional work to read your patch, the odds are that it will be +ignored completely. + +=== 4. E-mail size + +Large changes are not appropriate for mailing lists, and some +maintainers. If your patch, exceeds 5Kb in size, you must submit the +patch via GitHub instead. + +=== 5. Name the version of the server + +It is important to note, either in the subject line or in the patch +description, the server version to which this patch applies. diff --git a/doc/antora/modules/developers/pages/coverage.adoc b/doc/antora/modules/developers/pages/coverage.adoc new file mode 100644 index 0000000..af6048e --- /dev/null +++ b/doc/antora/modules/developers/pages/coverage.adoc @@ -0,0 +1,11 @@ += Code Coverage + +We use the link:https://gcc.gnu.org/onlinedocs/gcc/Gcov-Intro.html#Gcov-Intro[gcov] tool to know our tests coverage. + +[source,shell] +---- +$ make clean +$ make coverage +---- + +If completed with success, a pretty report will be available in `${source_tree}/build/coverage/index.html` diff --git a/doc/antora/modules/developers/pages/index.adoc b/doc/antora/modules/developers/pages/index.adoc new file mode 100644 index 0000000..e66ef61 --- /dev/null +++ b/doc/antora/modules/developers/pages/index.adoc @@ -0,0 +1,18 @@ += FreeRADIUS Development + +List with some usual howtos for FreeRADIUS. + +Programming reference documentation can be found at the +https://doc.freeradius.org/[Doxygen] site. + +== Topics + +* xref:bugs.adoc[Bugs] +* xref:coding-methods.adoc[Coding Methods] +* xref:coverage.adoc[Code Coverage] +* xref:profile.adoc[Profiling] +* xref:contributing.adoc[Contributing] +* xref:release-method.adoc[Release Method] + +Also see the xref:installation:dependencies.adoc[build +dependencies] page. diff --git a/doc/antora/modules/developers/pages/profile.adoc b/doc/antora/modules/developers/pages/profile.adoc new file mode 100644 index 0000000..ca94f53 --- /dev/null +++ b/doc/antora/modules/developers/pages/profile.adoc @@ -0,0 +1,41 @@ += Profiling + +Build with gperftools, and ensure that it's built: + +[source,shell] +---- +$ grep profile Make.inc +GPERFTOOLS_LIBS = -lprofiler +---- + +Run your test using the profiling tools. One signal will start the +profiling, another will stop it. + +[source,shell] +---- +env CPUPROFILE=/tmp/freeradius.prof CPUPROFILESIGNAL=12 freeradius ... +killall -12 freeradius + ... wait ... +killall -12 freeradius +---- + +View the results + +[source,shell] +---- +pprof --text /path/to/freeradius /tmp/freeradius.prof +---- + +or as a graph + +[source,shell] +---- +pprof --gv /path/to/freeradius /tmp/freeradius.prof +---- + +or as cachgrind output + +[source,shell] +---- +pprof --cachegrind /path/to/freeradius /tmp/freeradius.prof +---- diff --git a/doc/antora/modules/developers/pages/release-method.adoc b/doc/antora/modules/developers/pages/release-method.adoc new file mode 100644 index 0000000..1de9e2d --- /dev/null +++ b/doc/antora/modules/developers/pages/release-method.adoc @@ -0,0 +1,55 @@ += Release Method + +== Topics + +[arabic] +. As of 2.0, the release process is much simpler. Edit the Changelog +with the version number and any last updates. + +``` +# vi doc/ChangeLog +# git commit doc/ChangeLog +``` + +[arabic, start=2] +. Change version numbers in the VERSION file: + +``` +# vi VERSION +# git commit VERSION +``` + +[arabic, start=3] +. Make the files + +NOTE: It also does `make dist-check`, which checks the build rules for +various packages. + +``` +# make dist +``` + +[arabic, start=4] +. Validate that the packages are OK. If so, tag the release. + +NOTE: This does NOT actually do the tagging! You will have to run the +command it prints out yourself. + +``` +# make dist-tag +``` + +[arabic, start=5] +. Sign the packages. You will need the correct GPG key for this to work. + +``` +# make dist-sign +``` + +[arabic, start=6] +. Push to the FTP site. You will need write access to the FTP site for +this to work. + +``` +# make dist-publish +``` |