mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-21 15:54:39 +01:00
Mitigated Serial Monitor resource exhaustion when the connected device sends a lot of data
Fixes #2233
This commit is contained in:
parent
1be99c3a1d
commit
35848e09a8
@ -19,6 +19,7 @@
|
|||||||
package processing.app;
|
package processing.app;
|
||||||
|
|
||||||
import processing.app.debug.MessageConsumer;
|
import processing.app.debug.MessageConsumer;
|
||||||
|
import processing.app.debug.TextAreaFIFO;
|
||||||
import processing.core.*;
|
import processing.core.*;
|
||||||
import static processing.app.I18n._;
|
import static processing.app.I18n._;
|
||||||
|
|
||||||
@ -26,13 +27,12 @@ import java.awt.*;
|
|||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.*;
|
import javax.swing.border.*;
|
||||||
import javax.swing.event.*;
|
|
||||||
import javax.swing.text.*;
|
import javax.swing.text.*;
|
||||||
|
|
||||||
public class SerialMonitor extends JFrame implements MessageConsumer {
|
public class SerialMonitor extends JFrame implements MessageConsumer,ActionListener {
|
||||||
private Serial serial;
|
private Serial serial;
|
||||||
private String port;
|
private String port;
|
||||||
private JTextArea textArea;
|
private TextAreaFIFO textArea;
|
||||||
private JScrollPane scrollPane;
|
private JScrollPane scrollPane;
|
||||||
private JTextField textField;
|
private JTextField textField;
|
||||||
private JButton sendButton;
|
private JButton sendButton;
|
||||||
@ -40,6 +40,8 @@ public class SerialMonitor extends JFrame implements MessageConsumer {
|
|||||||
private JComboBox lineEndings;
|
private JComboBox lineEndings;
|
||||||
private JComboBox serialRates;
|
private JComboBox serialRates;
|
||||||
private int serialRate;
|
private int serialRate;
|
||||||
|
private javax.swing.Timer updateTimer;
|
||||||
|
private StringBuffer updateBuffer;
|
||||||
|
|
||||||
public SerialMonitor(String port) {
|
public SerialMonitor(String port) {
|
||||||
super(port);
|
super(port);
|
||||||
@ -67,7 +69,9 @@ public class SerialMonitor extends JFrame implements MessageConsumer {
|
|||||||
Font editorFont = Preferences.getFont("editor.font");
|
Font editorFont = Preferences.getFont("editor.font");
|
||||||
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
|
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
|
||||||
|
|
||||||
textArea = new JTextArea(16, 40);
|
textArea = new TextAreaFIFO(4000000);
|
||||||
|
textArea.setRows(16);
|
||||||
|
textArea.setColumns(40);
|
||||||
textArea.setEditable(false);
|
textArea.setEditable(false);
|
||||||
textArea.setFont(font);
|
textArea.setFont(font);
|
||||||
|
|
||||||
@ -171,6 +175,9 @@ public class SerialMonitor extends JFrame implements MessageConsumer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateBuffer = new StringBuffer(1048576);
|
||||||
|
updateTimer = new javax.swing.Timer(33, this); // redraw serial monitor at 30 Hz
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPlacement(int[] location) {
|
protected void setPlacement(int[] location) {
|
||||||
@ -203,9 +210,9 @@ public class SerialMonitor extends JFrame implements MessageConsumer {
|
|||||||
|
|
||||||
public void openSerialPort() throws SerialException {
|
public void openSerialPort() throws SerialException {
|
||||||
if (serial != null) return;
|
if (serial != null) return;
|
||||||
|
|
||||||
serial = new Serial(port, serialRate);
|
serial = new Serial(port, serialRate);
|
||||||
serial.addListener(this);
|
serial.addListener(this);
|
||||||
|
updateTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeSerialPort() {
|
public void closeSerialPort() {
|
||||||
@ -219,13 +226,32 @@ public class SerialMonitor extends JFrame implements MessageConsumer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void message(final String s) {
|
public void message(String s) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
// TODO: can we pass a byte array, to avoid overhead of String
|
||||||
public void run() {
|
addToUpdateBuffer(s);
|
||||||
textArea.append(s);
|
|
||||||
if (autoscrollBox.isSelected()) {
|
|
||||||
textArea.setCaretPosition(textArea.getDocument().getLength());
|
|
||||||
}
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void addToUpdateBuffer(String s) {
|
||||||
|
updateBuffer.append(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized String consumeUpdateBuffer() {
|
||||||
|
String s = updateBuffer.toString();
|
||||||
|
updateBuffer.setLength(0);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
final String s = consumeUpdateBuffer();
|
||||||
|
if (s.length() > 0) {
|
||||||
|
//System.out.println("gui append " + s.length());
|
||||||
|
boolean scroll = autoscrollBox.isSelected();
|
||||||
|
textArea.allowTrim(scroll);
|
||||||
|
textArea.append(s);
|
||||||
|
if (scroll) {
|
||||||
|
textArea.setCaretPosition(textArea.getDocument().getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
78
app/src/processing/app/debug/TextAreaFIFO.java
Normal file
78
app/src/processing/app/debug/TextAreaFIFO.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2014 Paul Stoffregen <paul@pjrc.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
// adapted from https://community.oracle.com/thread/1479784
|
||||||
|
|
||||||
|
package processing.app.debug;
|
||||||
|
|
||||||
|
import javax.swing.JTextArea;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
|
||||||
|
public class TextAreaFIFO extends JTextArea implements DocumentListener {
|
||||||
|
private int maxChars;
|
||||||
|
|
||||||
|
private int updateCount; // limit how often we trim the document
|
||||||
|
|
||||||
|
private boolean doTrim;
|
||||||
|
|
||||||
|
public TextAreaFIFO(int max) {
|
||||||
|
maxChars = max;
|
||||||
|
updateCount = 0;
|
||||||
|
doTrim = true;
|
||||||
|
getDocument().addDocumentListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void allowTrim(boolean trim) {
|
||||||
|
doTrim = trim;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
if (++updateCount > 150 && doTrim) {
|
||||||
|
updateCount = 0;
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
trimDocument();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trimDocument() {
|
||||||
|
int len = 0;
|
||||||
|
len = getDocument().getLength();
|
||||||
|
if (len > maxChars) {
|
||||||
|
int n = len - maxChars;
|
||||||
|
System.out.println("trimDocument: remove " + n + " chars");
|
||||||
|
try {
|
||||||
|
getDocument().remove(0, n);
|
||||||
|
} catch (BadLocationException ble) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,9 @@ ARDUINO 1.0.7
|
|||||||
* Fixed missing NOT_AN_INTERRUPT constant in digitalPinToInterrupt() macro
|
* Fixed missing NOT_AN_INTERRUPT constant in digitalPinToInterrupt() macro
|
||||||
* Fixed performance regression in HardwareSerial::available() introduced with https://github.com/arduino/Arduino/pull/2057
|
* Fixed performance regression in HardwareSerial::available() introduced with https://github.com/arduino/Arduino/pull/2057
|
||||||
|
|
||||||
|
[ide]
|
||||||
|
* Mitigated Serial Monitor resource exhaustion when the connected device sends a lot of data (Paul Stoffregen)
|
||||||
|
|
||||||
ARDUINO 1.0.6 - 2014.09.16
|
ARDUINO 1.0.6 - 2014.09.16
|
||||||
|
|
||||||
[core]
|
[core]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user