LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-26-2018, 12:40 PM   #1
hazel
LQ Guru
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 5,321
Blog Entries: 15

Rep: Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110
How are programs able to handle events, given the procedural nature of most languages?


Lots of programs can handle unpredictable events. You can write a handler for a Unix signal or for an X-event like a mouse click. There will be a marshalling function of some kind that lets you link your handler to the event in question. But how does this actually work, given that the cpu processes code sequentially? Where in this sequence of small steps does the handler lurk, ready to jump in when required?
 
Old 08-26-2018, 01:13 PM   #2
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 9,985

Rep: Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568Reputation: 4568
They (AFAIK all) have the following architecture:

https://en.wikipedia.org/wiki/Event_loop

Last edited by dugan; 08-26-2018 at 01:15 PM.
 
Old 08-26-2018, 01:23 PM   #3
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,194

Rep: Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040
More to the basics, when a program is loaded it can set addresses of certain handlers. Then the OS is told that at a certain event a certain function must be executed by telling the OS the handler address. Once this event occurs, the program is literally interrupted, the complete programs state is preserved, the handler executed and once finished the program state is restored and the program continues execution where it left off.

In GUI programs often an event loop is running, which receives events from the OS and dispatches those events to the application code. Often, the running program is not interrupted but simple handles the next event when it is ready. That is event-driven programming.

jlinkels
 
1 members found this post helpful.
Old 08-26-2018, 01:42 PM   #4
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=14, FreeBSD_12{.0|.1}
Posts: 5,583
Blog Entries: 11

Rep: Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599
An important part of the process, and what you seem to be asking about is what are called "interrupts". The normal sequential execution of code is interrupted by an "interrput" signal.

There are two basic kinds of interrupt, hardware and software. Hardware interrupts are generated by hardware events, such as a key press, a network interface receiving data or a disk drive I/O operation completing, for example. Software interrupts can be generated by any running process, and also by certain conditions internal to the CPU.

Here is a simplistic description of how it works.

When the kernel receives an interrupt it pushes its current state, what it is doing now, onto the stack and jumps to whatever handler has been assigned for the particular interrupt. This is usually a device driver for hardware interrupts. Some interrupts will block others until they are complete, others may themselves be interrupted as any other code.

Different interrupt sources have different priorities, the kernel handles them in priority order so that things which need immediate attention receive it, typically changes in hardware state.

When the interrupt handler code returns, the kernel pulls its previous state from the stack and resumes what it was doing.

If your program was waiting for some change of state, i.e. an event, it may provide an interrupt handler itself, or it may detect a change in system state and respond to the event it was waiting for.

Last edited by astrogeek; 08-26-2018 at 01:54 PM.
 
Old 08-26-2018, 01:53 PM   #5
hazel
LQ Guru
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 5,321

Original Poster
Blog Entries: 15

Rep: Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110
So the sequence is basically:

1) Request to be notified of events and go to sleep
2) Wake up if an event is reported
3) Test the reported event to find out what kind of event it is.
4) Run the appropriate handler for that kind of event.
5) When handler returns, go back to 1).

The signals I'm most familiar with in programming are gtk signals and their underlying gdk events and they certainly follow that loop model. You set up your graphical interface, link your handlers to these signals or events, and call gtk_main(). After that the only code that can be processed is handler code. Any code beyond the gtk_main() call is inaccessible until some handler calls gtk_main_quit() to break the loop.

But Unix signals don't seem to work like that. They affect programs that aren't looping or waiting. That Wikipedia article tries to explain it but it's beyond my level. And what about signals that come from other programs via something like dbus? A running program can't simply sit and wait for those.

Oops! We have a race condition!
@jlinkels: your mechanism would explain how Unix signals are handled. It isn't the program that runs the handler, it's the kernel.
@astrogeek: I think hardware interrupts are a bit different.

Last edited by hazel; 08-26-2018 at 02:01 PM. Reason: Added brief answers to additional posts
 
Old 08-26-2018, 02:03 PM   #6
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=14, FreeBSD_12{.0|.1}
Posts: 5,583
Blog Entries: 11

Rep: Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599Reputation: 3599
Quote:
Originally Posted by hazel View Post
But Unix signals don't seem to work like that. They affect programs that aren't looping or waiting. That Wikipedia article tries to explain it but it's beyond my level. And what about signals that come from other programs via something like dbus? A running program can't simply sit and wait for those.
The whole idea of an interrupt in this context is that they are asynchronous, the system or program does not have to sit and wait - they can go on about their business! That "business" may be a simple event loop, where it is waiting for a keypress, for example. But it may be be anything - the program is not constrained to wait.
 
Old 08-26-2018, 08:36 PM   #7
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,590

Rep: Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908Reputation: 1908
Quote:
Originally Posted by hazel View Post
And what about signals that come from other programs via something like dbus? A running program can't simply sit and wait for those.
D-Bus messages come over a socket, the receiving program does have to explicitly check for them.

Quote:
It isn't the program that runs the handler, it's the kernel.
The kernel arranges for the program to start running the handler (that is, the handler code itself is run in userspace).
 
1 members found this post helpful.
Old 08-27-2018, 01:33 AM   #8
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,232

Rep: Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451Reputation: 5451
I think what you are talking about in post #5 is more or less callback function, not an interrupt or signal.

In X you register callback functions if you want to handle events. X itself catches the interrupt or signal an look for the registered callback functions and invoke them.
But also there are message buses where anyone can send a message and anyone can read (if interested...). This is another approach again.
 
1 members found this post helpful.
Old 08-27-2018, 06:57 AM   #9
mina86
Member
 
Registered: Aug 2008
Distribution: Debian
Posts: 517

Rep: Reputation: 228Reputation: 228Reputation: 228
Quote:
Originally Posted by hazel View Post
@astrogeek: I think hardware interrupts are a bit different.
Hardware interrupts and Unix signals are pretty much the same idea: you set up handlers for interrupts/signals then go about your business until that business is interrupted when interrupt/signal arrives. In the former itís the kernel setting up pointers in an interrupt table and hardware jumping to that code on an interrupt. In the latter itís user space setting up signal handlers and kernel calling the handler functions when signal arrives to the process. In both cases, the handlers might do relatively little and rather signal to the Ďmainí code that an interrupt/signal needs to be processed.

Another way to handle signals is via signalfd.

But there are many ways of how asynchronous events can be handled interrupts and signals being one. Event loops being another. Multithreading being yet another.
 
1 members found this post helpful.
Old 08-27-2018, 07:40 AM   #10
hazel
LQ Guru
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 5,321

Original Poster
Blog Entries: 15

Rep: Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110
Quote:
Originally Posted by mina86 View Post
But there are many ways of how asynchronous events can be handled interrupts and signals being one. Event loops being another. Multithreading being yet another.
Yes, it's obvious that having a parallel thread to wait for events and handle them would be a complete solution. It would leave the main instruction thread able to concentrate on the job in hand.

So let me see if I can understand this. There isn't a single way to handle events, there are several different ways. A parallel event-monitoring thread is one possibility. Graphical programs can just wait in a loop until a user-triggered event takes place, run a handler and loop again. These programs often don't have anything else to do but wait for user instructions. Or the kernel can stop a program and restart it at a handler entry point, which is how Unix inter-process signals work. I think I'll mark this one as solved.
 
1 members found this post helpful.
Old 08-29-2018, 03:36 AM   #11
mina86
Member
 
Registered: Aug 2008
Distribution: Debian
Posts: 517

Rep: Reputation: 228Reputation: 228Reputation: 228
Quote:
Originally Posted by hazel View Post
A parallel event-monitoring thread is one possibility.
This is essentially how futures work. And depending on type of events, you might have one or multiple threads waiting for them. And this does not preclude an event-loop since such events may simply wake up the main thread which will do the actual work.

Quote:
Originally Posted by hazel View Post
Graphical programs can just wait in a loop until a user-triggered event takes place, run a handler and loop again.
Note that whether program is graphical or not isn’t really relevant. A text-based IRC/chat client may use a single-threaded event loop and even handle signals synchronously in that loop. Also remember that not all events are user-triggered.
 
Old 08-29-2018, 05:33 AM   #12
hazel
LQ Guru
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 5,321

Original Poster
Blog Entries: 15

Rep: Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110Reputation: 3110
Quote:
Originally Posted by mina86 View Post
This is essentially how futures work.
What are futures?
Quote:
Note that whether program is graphical or not isnít really relevant. A text-based IRC/chat client may use a single-threaded event loop and even handle signals synchronously in that loop.
Good point! After all, the shell works in a very similar way: waits for a command, finds an executable with the same name, runs it, and goes back to waiting.

I remember once seeing some code in which a signal handler changed a global variable and the main loop just checked that variable synchronously each time it ran. The trouble is that if the loop is waiting anyway (say for user input) it might not get to checking for signals for quite some time.
 
Old 08-29-2018, 07:25 AM   #13
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,194

Rep: Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040Reputation: 1040
It would take a few pages (about the size of a book) to explain the current state of interrupts and event handling. The mechanisms behind have evolved for about 50 years. Although there was a restart at zero when DOS was introduced.

No, event driven programming and GUI can be seen separately, although there is a reason that event driven programming became almost a requirement for GUI programming.

First, in a classic system where you only have a single foreground process on a real terminal (a 70-ies Unix system so to say) the keyboard input hardware would generate an interrupt at every keypress. The OS would be interrupted on whatever it was doing, to handle the keyboard input. This was done by the keyboard interrupt handler, which translated the keyboard scan code to an ASCII code, and put it in a buffer somewhere, ready fo the foreground process to read.

However, some keys were (are) special, like CTRL-C. This input would be handed directly to the OS, which signalled the OS that the running foreground process had to be sent a software interrupt: SIGHUP. So this is part of your question how a running process gets interrupted.

All other keycodes would be in the keyboard buffer, which was polled by the shell. Once a predefined character was read from the buffer (usually 0x0D, or return) the shell understood the command was complete and executed the command. It can be somewhat regarded as event driven. The shell would read events (key presses) from the buffer and act accordingly.

In these situations there was just one foreground process, and it was easy to see where all keypresses had to go.

However, when GUI programming became current, a program would consist of many graphical elements, like a window canvas, menu bar, buttons, and whatnot. When then a key was pressed, the program had to decide where each keypress had to be handled. It was not so clear anymore. So whenever an event (keypress or mouse event) is received, it is sent through a chain of graphical objects, where usually the objects themselves knows whether to handle the event, or send it to the next object in the chain.

For example, while I am typing this, the keypresses are sent to the active window by the X driver. The active window, Firefox, sends the keypresses into its chain of objects. Eventually the editor object knows it should handle the keypresses and does so, ending the journey of the event. Before that, the event was ignored bu all other objects, tabs, menu bars, links and buttons because they knew by their state they should not handle the event.

And yes, events remain in the queue when the application is doing other things. If for example you open a Word document, OOWriter is busy opening the document and while it is doing so nothing happens when you click on File on the menu bar. Once the document is loaded, you suddenly see the File menu drop down.

jlinkels

Last edited by jlinkels; 08-29-2018 at 07:33 AM.
 
2 members found this post helpful.
Old 08-29-2018, 08:23 AM   #14
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.8.2003
Posts: 5,384

Rep: Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021Reputation: 2021
Helen,
Thank you for starting a very interesting thread!
 
Old 08-29-2018, 01:17 PM   #15
mina86
Member
 
Registered: Aug 2008
Distribution: Debian
Posts: 517

Rep: Reputation: 228Reputation: 228Reputation: 228
Quote:
Originally Posted by hazel View Post
What are futures?
https://en.wikipedia.org/wiki/Futures_and_promises

Quote:
Originally Posted by hazel View Post
I remember once seeing some code in which a signal handler changed a global variable and the main loop just checked that variable synchronously each time it ran. The trouble is that if the loop is waiting anyway (say for user input) it might not get to checking for signals for quite some time.
This can be solved by using non-blocking I/O, blocking all signals during normal code execution and using pselect to unblocked signals and wait for all file descriptors (like the code Iíve linked to). This way, waiting for signals and user input is done in at the same time. signalfd(2)+select(2) may be even simpler solution.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] How does Linux handle programs and execution memory? Lsatenstein Linux - Desktop 3 04-27-2015 05:54 PM
programs to be run on boot (and other events) KansaiRobot Linux - Newbie 1 03-09-2015 04:38 AM
Bash- Some Simple Code on how to log events and handle errors mtm100 Linux - Newbie 3 10-28-2011 12:41 PM
handle information in foreign languages tooparam Linux - Software 2 02-01-2006 12:11 PM
loading procedural languages in Postgresql sibtay Linux - Software 1 12-09-2004 08:23 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:48 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration