Guidelines and HOWTOs/Debugging/Debugging IOSlaves: Difference between revisions

From KDE Community Wiki
(Add ptrace note)
(modernize)
 
(9 intermediate revisions by 4 users not shown)
Line 1: Line 1:
This page describes how you can debug a KIO ioslave.
This page describes how you can debug a KIO ioslave.


==How to get debug output==
==How to Get Debug Output==


=== GUI (Qt5/KF5 instructions) ===
=== GUI (Qt5/KF5 instructions) ===


# Press ALT+F2.
# Launch the  <code>kdebugsettings</code> tool, either from terminal or from KRunner (the latter can be invoked with Alt + F2)
# Enter 'kdebugsettings' without the quotes and press enter.
# Type the name of the KIO Slave (e.g. ftp, http, ...). (If it's not listed, it doesn't use categorized debug output, so either its output is always on, or commented out in the code, in which case it needs to be ported to qCDebug)
# Type the name of the kioslave (e.g. ftp, http, ...). If it's not listed, it doesn't use categorized debug output, so either its output is always on, or commented out in the code (in which case it needs to be ported to qCDebug).
# From the drop-down menu next to each KIO Slave you're interested in, select '''Full Debug'''
# Ensure the combobox for the kioslave says "Debug".  "All" is misleading since it means "no rule", and the default could be off, not on.
# Press '''OK''' to close the dialog and the save your changes
# Press OK to close the dialog.
# You can either run <code>kdeinit5</code> in terminal, in which case the output from any IO slave that's started afterwards will show up in that terminal  OR
# Press ALT+F2, type ''kdeinit5'' and press enter or alternatively log out of KDE and log back in.
# Alternatively log out then log back in, and additional debug info will typically end up in ~/.X.err, ~/.xsession-errors or ~/.local/share/sddm/xorg-session.log


This will print additional debug info to the stderr of your kioslave, which typically ends up in ~/.X.err or ~/.xsession-errors
Notes:
* If you have rebuilt an IO Slave from source with some changes you'll need ensure that <code>kdeinit5</code> will pick it up; this works with KIO from the KDE repos:
{{Input|1=<nowiki>
cd <path to build dir>/bin
export LD_LIBRARY_PATH=$PWD
export QT_PLUGIN_PATH=$PWD
kdeinit5</nowiki>}}
** in the first <code>cd</code> command you change to the directory containing the compiled binaries, in KIO case it's ''<build dir>/bin''.


* Instead of using <code>kdebugsettings</code>, you can change the Qt logging categories rules temporarily, in terminal:
{{Input|1=<nowiki>
export QT_LOGGING_RULES="*kio*=true"
</nowiki>}}
** for more information see [https://doc.qt.io/qt-5/qloggingcategory.html this].
=== GUI (Qt4/kdelibs4 instructions) ===
=== GUI (Qt4/kdelibs4 instructions) ===


Line 24: Line 36:
# Press ALT+F2, type ''kdeinit4'' and press enter or alternatively log out of KDE and log back in.
# Press ALT+F2, type ''kdeinit4'' and press enter or alternatively log out of KDE and log back in.


This will print additional debug info to the stderr of your kdeinit process, which typically ends up in ~/.X.err or ~/.xsession-errors
This will print additional debug info to the stderr of your kdeinit process, which typically ends up in ~/.X.err, ~/.xsession-errors or ~/.local/share/sddm/xorg-session.log


===Manual (Qt4/kdelibs4 instructions)===
===Manual (Qt4/kdelibs4 instructions)===
Line 48: Line 60:
</pre>
</pre>
This will print additional debug info to the stderr of your kdeinit process,
This will print additional debug info to the stderr of your kdeinit process,
which typically ends up in ~/.X.err or ~/.xsession-errors
which typically ends up in ~/.X.err, ~/.xsession-errors or ~/.local/share/sddm/xorg-session.log


==How does an io-slave get started?==


Before KF 5.86: if <code>KDE_FORK_SLAVES</code> environment variable is ''not set'', your application requests 'klauncher' via DBus for a slave. If 'klauncher' does not have an idle slave ready, it will ask kdeinit to start a new one. kdeinit forks and dlopens the library that contains the io-slave. Then it calls a function called kdemain() in the library.


==How does an io-slave get started?==
Since 5.86 (or when setting <code>KDE_FORK_SLAVES</code> before that) the application simply starts the io-slave directly.


Your application requests 'klauncher' via DBus for a slave. If 'klauncher' does not have an idle slave ready, it will ask kdeinit to start a new one. kdeinit forks and dlopens the library that contains the io-slave.
Since 5.95, an io-slave can run in a thread (in the application process). Currently this only happens for kio_file. It can be disabled with <code>export KIO_ENABLE_WORKER_THREADS=0</code>.
Then it calls a function called kdemain() in the library.


==Attaching gdb to an io-slave==
==Attaching gdb to an io-slave==
Due to the above sequence it is rather hard to get an io-slave in your
===For slaves started via klauncher (before KF 5.86)===
debugger. But wait there is hope. You can start <tt>klauncher</tt> in such a way
 
that slaves for a certain protocol (the first parameter of KIO::SlaveBase() constructor of the slave class) are started in debug mode.
If <code>KDE_FORK_SLAVES</code> environment variable is ''not set'', your application asks <code>klauncher</code> via DBus for an io-slave. If <code>klauncher</code> does not have an idle io-slave ready, it will ask <code>kdeinit</code> to start a new one. <code>kdeinit</code> forks and dlopens the library that contains the requested io-slave.
Then it calls a function called <code>kdemain()</code> in the library.
 
Due to the above sequence it is rather hard to get an io-slave in your debugger. But wait there is hope! You can start </code>klauncher</code> in such a way that io-slaves for a certain protocol (the first parameter of KIO::SlaveBase() constructor of the Slave class) are started in debug mode.


E.g. to start all 'http' slaves in debug mode, you type:
E.g. to start all 'http' slaves in debug mode, you type:
Line 75: Line 91:
</pre>
</pre>


For example, these commands don't work:
For example, these commands won't work:
<pre>
<pre>
KDE_SLAVE_DEBUG_WAIT=imap4 kdeinit5
KDE_SLAVE_DEBUG_WAIT=imap4 kdeinit5
Line 81: Line 97:
</pre>
</pre>


When your application now requests a http slave, the slave will be started
When your application now requests an http io-slave, the io-slave will be started kdeinit, but before it calls kdemain() (cq. main()) it will suspend the slave by sending it a SIGSTOP signal.
by kdeinit, but before it calls kdemain() (cq. main()) it will suspend the
slave by sending it a SIGSTOP signal.


In the terminal from which you started kdeinit you will get the following
In the terminal from which you started kdeinit you will get a message like this:
message:
<pre>
<pre>
kdeinit: Suspending process
kdeinit: Suspending process
Line 93: Line 106:
</pre>
</pre>


You can now debug your slave by typing (or pasting) 'gdb kdeinit 16779' in
You can now debug your slave by using <code>gdb kdeinit 16779</code> in a terminal.
a terminal.  
 
Note that modern Linux Kernels disable ptrace. If gdb says "ptrace: Operation not permitted." then you need to use a command like this:
<pre>
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
</pre>
 
If you don't want to debug a slave you can let it continue by sending it a SIGCONT, with e.g. <code>kill -SIGCONT 16779</code>. Be aware that slaves will not be killed while they are suspended.


Note that modern linux kernels disable ptrace. If gdb says "ptrace: Operation not permitted." then you need this:
Once you have started gdb, you can set e.g. breakpoints and then resume the slave by typing <code>continue</code> (or <code>c</code> for short). The debugger will return immediate with a message that a "SIGSTOP has been received" so you will have to type <code>continue</code> a second time.


<pre>echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope</pre>
See also [[Development/Tutorials/Debugging/Debugging_on_MS_Windows#Debugging_kioslaves|Windows-specific notes on debugging io-slaves]].


If you don't want to debug a slave you can let it continue by
===For slaves started directly by the application (forked)===
sending it a SIGCONT by typing 'kill -SIGCONT 16779'.
Be aware that slaves will not be killed while they are suspended.


Once you have started gdb, you can set e.g. breakpoints and then resume the  
The only difference between this section and the previous one is how the io-slave is started.
slave by typing 'continue'. The debugger will return immediate with a message
that a SIGSTOP has been received so you will have to type 'continue' a second
time.


See also [[Development/Tutorials/Debugging/Debugging_on_MS_Windows#Debugging_kioslaves|Windows-specific notes on debugging io-slaves]].
When you start your application, a dedicated io-slave will be created in-process by the <code>kioslave</code> executable. To make the io-slave start then wait for debug, just like with the kdeinit/klauncher approach, you need to export <code>KDE_SLAVE_DEBUG_WAIT</code>, for example:
<pre>
// Will start any io-slave then call `kill -SIGSTOP pid` to make it wait for debugging,
// e.g. you can create a breakpoint ...etc
export KDE_SLAVE_DEBUG_WAIT=all
kioslave5: Suspending process to debug io slave(s): all
kioslave5: 'gdb kioslave5 28008' to debug
kioslave5: 'kill -SIGCONT 28008' to continue
 
// This will do the same but only for kio_file
export KDE_SLAVE_DEBUG_WAIT=file
kioslave5: Suspending process to debug io slave(s): file
kioslave5: 'gdb kioslave5 25208' to debug
kioslave5: 'kill -SIGCONT 25208' to continue
</pre>
 
then follow the same debugging steps from the previous section.
 
===For slaves started in a thread (kio_file since KF 5.95)===
 
Just put a breakpoint in <code>KIO::WorkerThread::WorkerThread</code>


==Debugging io-slaves with valgrind==
==Debugging io-slaves with valgrind (for slaves started via klauncher)==
KLauncher can be told to run certain io-slaves through valgrind. The following
KLauncher can be told to run certain io-slaves through valgrind. The following
command can be used to let klauncher run all https io-slaves via valgrind:
command can be used to let klauncher run all https io-slaves via valgrind:
Line 126: Line 160:


== specific kioslaves ==
== specific kioslaves ==
* [[Development/Tutorials/Debugging/Debugging IOSlaves/Debugging kio_fish|kio_fish]]
* [[Guidelines_and_HOWTOs/Debugging/Debugging IOSlaves/Debugging kio_fish|kio_fish]]
* [[Development/Tutorials/Debugging/Debugging IOSlaves/Debugging kio_sftp|kio_sftp]]
* [[Guidelines_and_HOWTOs/Debugging/Debugging IOSlaves/Debugging kio_sftp|kio_sftp]]
* [[Guidelines_and_HOWTOs/Debugging/Debugging IOSlaves/Debugging kio_smb|kio_smb]]

Latest revision as of 08:22, 16 May 2022

This page describes how you can debug a KIO ioslave.

How to Get Debug Output

GUI (Qt5/KF5 instructions)

  1. Launch the kdebugsettings tool, either from terminal or from KRunner (the latter can be invoked with Alt + F2)
  2. Type the name of the KIO Slave (e.g. ftp, http, ...). (If it's not listed, it doesn't use categorized debug output, so either its output is always on, or commented out in the code, in which case it needs to be ported to qCDebug)
  3. From the drop-down menu next to each KIO Slave you're interested in, select Full Debug
  4. Press OK to close the dialog and the save your changes
  5. You can either run kdeinit5 in terminal, in which case the output from any IO slave that's started afterwards will show up in that terminal OR
  6. Alternatively log out then log back in, and additional debug info will typically end up in ~/.X.err, ~/.xsession-errors or ~/.local/share/sddm/xorg-session.log

Notes:

  • If you have rebuilt an IO Slave from source with some changes you'll need ensure that kdeinit5 will pick it up; this works with KIO from the KDE repos:
cd <path to build dir>/bin
export LD_LIBRARY_PATH=$PWD
export QT_PLUGIN_PATH=$PWD
kdeinit5
    • in the first cd command you change to the directory containing the compiled binaries, in KIO case it's <build dir>/bin.
  • Instead of using kdebugsettings, you can change the Qt logging categories rules temporarily, in terminal:
export QT_LOGGING_RULES="*kio*=true"
    • for more information see this.

GUI (Qt4/kdelibs4 instructions)

  1. Press ALT+F2.
  2. Enter 'kdebugdialog --fullmode' without the quotes and press enter.
  3. Select the desired number in the "Debug area", e.g. 7103 for http.
  4. In the [Information] box, select "File" as the output.
  5. Enter the desired file name, e.g. /tmp/kio_http.log.
  6. Press OK to close the dialog.
  7. Press ALT+F2, type kdeinit4 and press enter or alternatively log out of KDE and log back in.

This will print additional debug info to the stderr of your kdeinit process, which typically ends up in ~/.X.err, ~/.xsession-errors or ~/.local/share/sddm/xorg-session.log

Manual (Qt4/kdelibs4 instructions)

It is useful to redirect the debug output of your particular slave to a file instead of stderr. E.g. I myself use the following lines in $KDEDIR/share/config/kdebugrc.

[7113]
InfoOutput=0
InfoFilename=/tmp/http
[7103]
InfoOutput=0
InfoFilename=/tmp/http 

This redirects all debug info for areas 7103 and 7113 (as used by kio_http) to the file /tmp/http.

To get debug information from the SMB slave you can add the following to kioslaverc:

[SMB]
DebugLevel=100

This will print additional debug info to the stderr of your kdeinit process, which typically ends up in ~/.X.err, ~/.xsession-errors or ~/.local/share/sddm/xorg-session.log

How does an io-slave get started?

Before KF 5.86: if KDE_FORK_SLAVES environment variable is not set, your application requests 'klauncher' via DBus for a slave. If 'klauncher' does not have an idle slave ready, it will ask kdeinit to start a new one. kdeinit forks and dlopens the library that contains the io-slave. Then it calls a function called kdemain() in the library.

Since 5.86 (or when setting KDE_FORK_SLAVES before that) the application simply starts the io-slave directly.

Since 5.95, an io-slave can run in a thread (in the application process). Currently this only happens for kio_file. It can be disabled with export KIO_ENABLE_WORKER_THREADS=0.

Attaching gdb to an io-slave

For slaves started via klauncher (before KF 5.86)

If KDE_FORK_SLAVES environment variable is not set, your application asks klauncher via DBus for an io-slave. If klauncher does not have an idle io-slave ready, it will ask kdeinit to start a new one. kdeinit forks and dlopens the library that contains the requested io-slave. Then it calls a function called kdemain() in the library.

Due to the above sequence it is rather hard to get an io-slave in your debugger. But wait there is hope! You can start klauncher in such a way that io-slaves for a certain protocol (the first parameter of KIO::SlaveBase() constructor of the Slave class) are started in debug mode.

E.g. to start all 'http' slaves in debug mode, you type:

KDE_SLAVE_DEBUG_WAIT=http kdeinit5

This will restart 'kdeinit' and 'klauncher'.

Note: The string after the equal signal designates the name of a service, not the name of the slave! E.g. if you want to debug the kio_imap4, you must use:

KDE_SLAVE_DEBUG_WAIT=imap kdeinit5

For example, these commands won't work:

KDE_SLAVE_DEBUG_WAIT=imap4 kdeinit5
KDE_SLAVE_DEBUG_WAIT=143 kdeinit5

When your application now requests an http io-slave, the io-slave will be started kdeinit, but before it calls kdemain() (cq. main()) it will suspend the slave by sending it a SIGSTOP signal.

In the terminal from which you started kdeinit you will get a message like this:

kdeinit: Suspending process
kdeinit: 'gdb kdeinit 16779' to debug
kdeinit: 'kill -SIGCONT 16779' to continue

You can now debug your slave by using gdb kdeinit 16779 in a terminal.

Note that modern Linux Kernels disable ptrace. If gdb says "ptrace: Operation not permitted." then you need to use a command like this:

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

If you don't want to debug a slave you can let it continue by sending it a SIGCONT, with e.g. kill -SIGCONT 16779. Be aware that slaves will not be killed while they are suspended.

Once you have started gdb, you can set e.g. breakpoints and then resume the slave by typing continue (or c for short). The debugger will return immediate with a message that a "SIGSTOP has been received" so you will have to type continue a second time.

See also Windows-specific notes on debugging io-slaves.

For slaves started directly by the application (forked)

The only difference between this section and the previous one is how the io-slave is started.

When you start your application, a dedicated io-slave will be created in-process by the kioslave executable. To make the io-slave start then wait for debug, just like with the kdeinit/klauncher approach, you need to export KDE_SLAVE_DEBUG_WAIT, for example:

// Will start any io-slave then call `kill -SIGSTOP pid` to make it wait for debugging,
// e.g. you can create a breakpoint ...etc
export KDE_SLAVE_DEBUG_WAIT=all
kioslave5: Suspending process to debug io slave(s): all
kioslave5: 'gdb kioslave5 28008' to debug
kioslave5: 'kill -SIGCONT 28008' to continue

// This will do the same but only for kio_file
export KDE_SLAVE_DEBUG_WAIT=file
kioslave5: Suspending process to debug io slave(s): file
kioslave5: 'gdb kioslave5 25208' to debug
kioslave5: 'kill -SIGCONT 25208' to continue

then follow the same debugging steps from the previous section.

For slaves started in a thread (kio_file since KF 5.95)

Just put a breakpoint in KIO::WorkerThread::WorkerThread

Debugging io-slaves with valgrind (for slaves started via klauncher)

KLauncher can be told to run certain io-slaves through valgrind. The following command can be used to let klauncher run all https io-slaves via valgrind:

KDE_SLAVE_VALGRIND=https kdeinit5

The valgrind output will appear as the stderr output of the kdeinit process. The $VALGRIND_OPTS environment variable can be used to pass options to valgrind. If you want to use a different skin:

KDE_SLAVE_VALGRIND_SKIN=callgrind      ( for example )

specific kioslaves